branch develop updated (cb15b56 -> c3e3ecb)
This is an automated email from the git hooks/post-receive script. New change to branch develop in repository jaxx. See https://gitlab.nuiton.org/nuiton/jaxx.git discards cb15b56 Fixes #3669 Merge branch 'feature/3669' into develop discards 1ddc6ec Rename runtime package to org.nuiton.jaxx.runtime (See #3669) discards 8a000ad Rename demo package to org.nuiton.jaxx.demo (See #3669) discards af1539e Rename compiler package to org.nuiton.jaxx.compiler (See #3669) discards 306a1ea Rename validator package to org.nuiton.jaxx.validator (See #3669) discards 2c85079 Rename config package to org.nuiton.jaxx.config (See #3669) new 34ea6e1 Rename runtime package to org.nuiton.jaxx.runtime (See #3669) new c3e3ecb Update jdk level to 1.8 (Fixes #2645) This update added new revisions after undoing existing revisions. That is to say, some revisions that were in the old version of the branch are not in the new version. This situation occurs when a user --force pushes a change and generates a repository containing something like this: * -- * -- B -- O -- O -- O (cb15b56) \ N -- N -- N refs/heads/develop (c3e3ecb) You should already have received notification emails for all of the O revisions, and so the following emails describe only the N revisions from the common base, B. Any revisions marked "omits" are not gone; other references still refer to them. Any revisions marked "discards" are gone forever. The 2 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit c3e3ecb0192ae3aca3b2d538c3d1cbfd9def6ec3 Author: Tony CHEMIT <chemit@codelutin.com> Date: Fri Dec 30 10:24:13 2016 +0100 Update jdk level to 1.8 (Fixes #2645) commit 34ea6e1dd405bf2719f63fd4f00969b01fea2df5 Author: Tony CHEMIT <chemit@codelutin.com> Date: Fri Dec 30 10:23:56 2016 +0100 Rename runtime package to org.nuiton.jaxx.runtime (See #3669) Summary of changes: .../jaxx/compiler/finalizers/DefaultFinalizer.java | 1191 ++++++++++++++++++++ .../jaxx/compiler/finalizers/SwingFinalizer.java | 89 ++ .../compiler/finalizers/ValidatorFinalizer.java | 278 +++++ .../org/nuiton/jaxx/runtime/FileChooserUtil.java | 358 ++++++ .../jaxx/runtime/swing/session/JTableState.java | 154 +++ .../runtime/swing/editor/I18nEditorHandler.java | 246 ++++ .../runtime/swing/editor/NumberEditorHandler.java | 623 ++++++++++ .../swing/editor/bean/BeanComboBoxHandler.java | 556 +++++++++ .../swing/editor/bean/BeanDoubleListHandler.java | 565 ++++++++++ .../swing/editor/bean/BeanDoubleListModel.java | 350 ++++++ .../editor/bean/BeanFilterableComboBoxHandler.java | 736 ++++++++++++ .../swing/editor/bean/BeanListHeaderHandler.java | 291 +++++ pom.xml | 4 +- 13 files changed, 5439 insertions(+), 2 deletions(-) create mode 100644 jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/DefaultFinalizer.java create mode 100644 jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/SwingFinalizer.java create mode 100644 jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/ValidatorFinalizer.java create mode 100644 jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/FileChooserUtil.java create mode 100644 jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/JTableState.java create mode 100644 jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/I18nEditorHandler.java create mode 100644 jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/NumberEditorHandler.java create mode 100644 jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanComboBoxHandler.java create mode 100644 jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanDoubleListHandler.java create mode 100644 jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanDoubleListModel.java create mode 100644 jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanFilterableComboBoxHandler.java create mode 100644 jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanListHeaderHandler.java -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jaxx. See https://gitlab.nuiton.org/nuiton/jaxx.git commit 34ea6e1dd405bf2719f63fd4f00969b01fea2df5 Author: Tony CHEMIT <chemit@codelutin.com> Date: Fri Dec 30 10:23:56 2016 +0100 Rename runtime package to org.nuiton.jaxx.runtime (See #3669) --- jaxx-application-swing/pom.xml | 2 +- .../swing/AbstractApplicationUIHandler.java | 34 +- .../jaxx/application/swing/ApplicationUI.java | 2 +- .../swing/action/ApplicationActionUI.jaxx | 2 +- .../swing/action/ApplicationActionUIHandler.java | 4 +- .../jaxx/application/swing/tab/CustomTab.java | 2 +- .../swing/table/AbstractApplicationTableModel.java | 2 +- .../ApplicationTableModelValidatorDataLocator.java | 2 +- .../swing/util/ApplicationExceptionHandler.java | 2 +- .../application/swing/util/ApplicationUIUtil.java | 4 +- .../src/main/java/jaxx/compiler/ClassMap.java | 117 - .../main/java/jaxx/compiler/CompiledObject.java | 791 -- .../jaxx/compiler/CompiledObjectDecorator.java | 105 - .../java/jaxx/compiler/CompilerConfiguration.java | 179 - .../main/java/jaxx/compiler/CompilerException.java | 68 - .../compiler/DefaultCompilerConfiguration.java | 373 - .../src/main/java/jaxx/compiler/EventHandler.java | 86 - .../src/main/java/jaxx/compiler/I18nHelper.java | 144 - .../src/main/java/jaxx/compiler/IDHelper.java | 117 - .../src/main/java/jaxx/compiler/JAXXCompiler.java | 2139 ---- .../main/java/jaxx/compiler/JAXXCompilerFile.java | 204 - .../src/main/java/jaxx/compiler/JAXXEngine.java | 484 - .../src/main/java/jaxx/compiler/JAXXFactory.java | 156 - .../src/main/java/jaxx/compiler/JAXXProfile.java | 386 - .../src/main/java/jaxx/compiler/SymbolTable.java | 89 - .../compiler/UnsupportedAttributeException.java | 65 - .../jaxx/compiler/UnsupportedTagException.java | 63 - .../java/jaxx/compiler/beans/BeanInfoUtil.java | 58 - .../jaxx/compiler/beans/JAXXBeanDescriptor.java | 37 - .../java/jaxx/compiler/beans/JAXXBeanInfo.java | 59 - .../compiler/beans/JAXXEventSetDescriptor.java | 60 - .../jaxx/compiler/beans/JAXXFeatureDescriptor.java | 76 - .../java/jaxx/compiler/beans/JAXXIntrospector.java | 190 - .../compiler/beans/JAXXPropertyDescriptor.java | 112 - .../java/jaxx/compiler/binding/DataBinding.java | 309 - .../jaxx/compiler/binding/DataBindingHelper.java | 260 - .../java/jaxx/compiler/binding/DataListener.java | 93 - .../java/jaxx/compiler/binding/DataSource.java | 882 -- .../java/jaxx/compiler/binding/JavaParserUtil.java | 387 - .../compiler/binding/PseudoClassDataBinding.java | 130 - .../binding/writers/AbstractJAXXBindingWriter.java | 94 - .../binding/writers/DefaultJAXXBindingWriter.java | 134 - .../binding/writers/JAXXBindingWriter.java | 84 - .../writers/SimpleJAXXObjectBindingWriter.java | 108 - .../java/jaxx/compiler/css/StylesheetHelper.java | 702 -- .../java/jaxx/compiler/css/parser/CSSParser.java | 831 -- .../compiler/css/parser/CSSParserConstants.java | 118 - .../compiler/css/parser/CSSParserTokenManager.java | 1176 --- .../css/parser/CSSParserTreeConstants.java | 76 - .../compiler/css/parser/JJTCSSParserState.java | 148 - .../main/java/jaxx/compiler/css/parser/Node.java | 73 - .../jaxx/compiler/css/parser/ParseException.java | 42 - .../jaxx/compiler/css/parser/SimpleCharStream.java | 429 - .../java/jaxx/compiler/css/parser/SimpleNode.java | 149 - .../main/java/jaxx/compiler/css/parser/Token.java | 98 - .../jaxx/compiler/css/parser/TokenMgrError.java | 149 - .../decorators/BoxedCompiledObjectDecorator.java | 77 - .../decorators/DefaultCompiledObjectDecorator.java | 359 - .../HelpRootCompiledObjectDecorator.java | 218 - .../compiler/finalizers/AbstractFinalizer.java | 87 - .../jaxx/compiler/finalizers/DefaultFinalizer.java | 1191 --- .../compiler/finalizers/JAXXCompilerFinalizer.java | 87 - .../jaxx/compiler/finalizers/SwingFinalizer.java | 89 - .../compiler/finalizers/ValidatorFinalizer.java | 278 - .../main/java/jaxx/compiler/java/JavaArgument.java | 83 - .../java/jaxx/compiler/java/JavaConstructor.java | 95 - .../main/java/jaxx/compiler/java/JavaElement.java | 129 - .../jaxx/compiler/java/JavaElementFactory.java | 179 - .../main/java/jaxx/compiler/java/JavaField.java | 294 - .../src/main/java/jaxx/compiler/java/JavaFile.java | 518 - .../java/jaxx/compiler/java/JavaFileGenerator.java | 453 - .../main/java/jaxx/compiler/java/JavaMethod.java | 355 - .../compiler/java/parser/JJTJavaParserState.java | 148 - .../jaxx/compiler/java/parser/JavaCharStream.java | 560 - .../java/jaxx/compiler/java/parser/JavaParser.java | 10117 ------------------- .../compiler/java/parser/JavaParserConstants.java | 404 - .../java/parser/JavaParserTokenManager.java | 2156 ---- .../java/parser/JavaParserTreeConstants.java | 361 - .../main/java/jaxx/compiler/java/parser/Node.java | 73 - .../jaxx/compiler/java/parser/ParseException.java | 238 - .../java/jaxx/compiler/java/parser/SimpleNode.java | 163 - .../main/java/jaxx/compiler/java/parser/Token.java | 101 - .../jaxx/compiler/java/parser/TokenMgrError.java | 149 - .../jaxx/compiler/reflect/ClassDescriptor.java | 295 - .../compiler/reflect/ClassDescriptorHelper.java | 533 - .../compiler/reflect/ClassDescriptorResolver.java | 67 - .../jaxx/compiler/reflect/FieldDescriptor.java | 54 - .../jaxx/compiler/reflect/MemberDescriptor.java | 61 - .../jaxx/compiler/reflect/MethodDescriptor.java | 75 - .../ClassDescriptorResolverFromJavaClass.java | 200 - .../ClassDescriptorResolverFromJavaFile.java | 746 -- .../ClassDescriptorResolverFromJaxxFile.java | 199 - .../jaxx/compiler/script/ScriptInitializer.java | 42 - .../java/jaxx/compiler/script/ScriptManager.java | 482 - .../java/jaxx/compiler/spi/DefaultInitializer.java | 234 - .../main/java/jaxx/compiler/spi/Initializer.java | 41 - .../compiler/tags/DefaultComponentHandler.java | 465 - .../jaxx/compiler/tags/DefaultObjectHandler.java | 1350 --- .../java/jaxx/compiler/tags/ImportHandler.java | 101 - .../java/jaxx/compiler/tags/ScriptHandler.java | 115 - .../main/java/jaxx/compiler/tags/StyleHandler.java | 110 - .../main/java/jaxx/compiler/tags/TagHandler.java | 68 - .../main/java/jaxx/compiler/tags/TagManager.java | 646 -- .../compiler/tags/swing/ApplicationHandler.java | 82 - .../java/jaxx/compiler/tags/swing/CellHandler.java | 221 - .../compiler/tags/swing/CompiledItemContainer.java | 69 - .../java/jaxx/compiler/tags/swing/ItemHandler.java | 174 - .../compiler/tags/swing/JAXXComboBoxHandler.java | 80 - .../jaxx/compiler/tags/swing/JAXXListHandler.java | 83 - .../jaxx/compiler/tags/swing/JAXXTabHandler.java | 33 - .../jaxx/compiler/tags/swing/JAXXTreeHandler.java | 88 - .../jaxx/compiler/tags/swing/JCheckBoxHandler.java | 44 - .../jaxx/compiler/tags/swing/JComboBoxHandler.java | 62 - .../compiler/tags/swing/JInternalFrameHandler.java | 72 - .../jaxx/compiler/tags/swing/JListHandler.java | 64 - .../jaxx/compiler/tags/swing/JMenuHandler.java | 44 - .../compiler/tags/swing/JPasswordFieldHandler.java | 43 - .../compiler/tags/swing/JPopupMenuHandler.java | 50 - .../compiler/tags/swing/JProgressBarHandler.java | 44 - .../compiler/tags/swing/JRadioButtonHandler.java | 106 - .../compiler/tags/swing/JScrollPaneHandler.java | 101 - .../jaxx/compiler/tags/swing/JSliderHandler.java | 67 - .../jaxx/compiler/tags/swing/JSpinnerHandler.java | 121 - .../compiler/tags/swing/JSplitPaneHandler.java | 99 - .../compiler/tags/swing/JTabbedPaneHandler.java | 168 - .../compiler/tags/swing/JTextComponentHandler.java | 112 - .../jaxx/compiler/tags/swing/JToolBarHandler.java | 78 - .../jaxx/compiler/tags/swing/JTreeHandler.java | 65 - .../jaxx/compiler/tags/swing/JWindowHandler.java | 80 - .../jaxx/compiler/tags/swing/JXLayerHandler.java | 108 - .../java/jaxx/compiler/tags/swing/RowHandler.java | 108 - .../java/jaxx/compiler/tags/swing/TabHandler.java | 218 - .../jaxx/compiler/tags/swing/TableHandler.java | 175 - .../tags/validator/BeanValidatorHandler.java | 1092 -- .../validator/ExcludeFieldValidatorHandler.java | 127 - .../tags/validator/FieldValidatorHandler.java | 153 - .../jaxx/compiler/tasks/CompileFirstPassTask.java | 127 - .../jaxx/compiler/tasks/CompileSecondPassTask.java | 92 - .../java/jaxx/compiler/tasks/FinalizeTask.java | 75 - .../compiler/tasks/GenerateConstructorsTask.java | 508 - .../compiler/tasks/GenerateMissingRulesTask.java | 130 - .../java/jaxx/compiler/tasks/GenerateTask.java | 205 - .../main/java/jaxx/compiler/tasks/InitTask.java | 83 - .../java/jaxx/compiler/tasks/JAXXEngineTask.java | 83 - .../main/java/jaxx/compiler/tasks/ProfileTask.java | 53 - .../java/jaxx/compiler/tasks/StyleSheetTask.java | 77 - .../java/jaxx/compiler/tools/PrintTagInfo.java | 143 - .../tools/jaxxcapture/AbstractContextNode.java | 41 - .../compiler/tools/jaxxcapture/CapturedObject.java | 176 - .../compiler/tools/jaxxcapture/ContextNode.java | 30 - .../compiler/tools/jaxxcapture/JAXXCapture.java | 405 - .../compiler/tools/jaxxcapture/LiteralNode.java | 43 - .../compiler/tools/jaxxcapture/MethodNode.java | 41 - .../compiler/tools/jaxxcapture/PropertyNode.java | 41 - .../jaxx/compiler/tools/jaxxcapture/ValueNode.java | 36 - .../jaxxcapture/handlers/JTabbedPaneHandler.java | 48 - .../tools/jaxxcapture/handlers/ObjectHandler.java | 346 - .../tools/jaxxcapture/handlers/TableHandler.java | 36 - .../java/jaxx/compiler/types/ColorConverter.java | 60 - .../types/GridBagConstraintsConverter.java | 48 - .../java/jaxx/compiler/types/InsetsConverter.java | 61 - .../jaxx/compiler/types/KeyStrokeConverter.java | 46 - .../jaxx/compiler/types/PrimitiveConverter.java | 122 - .../java/jaxx/compiler/types/TypeConverter.java | 32 - .../main/java/jaxx/compiler/types/TypeManager.java | 126 - .../java/org/nuiton/jaxx/compiler/ClassMap.java | 117 + .../org/nuiton/jaxx/compiler/CompiledObject.java | 791 ++ .../jaxx/compiler/CompiledObjectDecorator.java | 105 + .../jaxx/compiler/CompilerConfiguration.java | 179 + .../nuiton/jaxx/compiler/CompilerException.java | 68 + .../compiler/DefaultCompilerConfiguration.java | 373 + .../org/nuiton/jaxx/compiler/EventHandler.java | 86 + .../java/org/nuiton/jaxx/compiler/I18nHelper.java | 144 + .../java/org/nuiton/jaxx/compiler/IDHelper.java | 117 + .../org/nuiton/jaxx/compiler/JAXXCompiler.java | 2139 ++++ .../org/nuiton/jaxx/compiler/JAXXCompilerFile.java | 204 + .../java/org/nuiton/jaxx/compiler/JAXXEngine.java | 484 + .../java/org/nuiton/jaxx/compiler/JAXXFactory.java | 156 + .../java/org/nuiton/jaxx/compiler/JAXXProfile.java | 386 + .../java/org/nuiton/jaxx/compiler/SymbolTable.java | 89 + .../compiler/UnsupportedAttributeException.java | 67 + .../jaxx/compiler/UnsupportedTagException.java | 63 + .../nuiton/jaxx/compiler/beans/BeanInfoUtil.java | 58 + .../jaxx/compiler/beans/JAXXBeanDescriptor.java | 37 + .../nuiton/jaxx/compiler/beans/JAXXBeanInfo.java | 59 + .../compiler/beans/JAXXEventSetDescriptor.java | 60 + .../jaxx/compiler/beans/JAXXFeatureDescriptor.java | 76 + .../jaxx/compiler/beans/JAXXIntrospector.java | 190 + .../compiler/beans/JAXXPropertyDescriptor.java | 112 + .../nuiton/jaxx/compiler/binding/DataBinding.java | 309 + .../jaxx/compiler/binding/DataBindingHelper.java | 260 + .../nuiton/jaxx/compiler/binding/DataListener.java | 93 + .../nuiton/jaxx/compiler/binding/DataSource.java | 882 ++ .../jaxx/compiler/binding/JavaParserUtil.java | 387 + .../compiler/binding/PseudoClassDataBinding.java | 130 + .../binding/writers/AbstractJAXXBindingWriter.java | 94 + .../binding/writers/DefaultJAXXBindingWriter.java | 134 + .../binding/writers/JAXXBindingWriter.java | 84 + .../writers/SimpleJAXXObjectBindingWriter.java | 108 + .../nuiton/jaxx/compiler/css/StylesheetHelper.java | 702 ++ .../nuiton}/jaxx/compiler/css/parser/CSS.jj | 0 .../nuiton}/jaxx/compiler/css/parser/CSS.jjt | 0 .../nuiton/jaxx/compiler/css/parser/CSSParser.java | 831 ++ .../compiler/css/parser/CSSParserConstants.java | 118 + .../compiler/css/parser/CSSParserTokenManager.java | 1176 +++ .../css/parser/CSSParserTreeConstants.java | 76 + .../compiler/css/parser/JJTCSSParserState.java | 148 + .../org/nuiton/jaxx/compiler/css/parser/Node.java | 73 + .../jaxx/compiler/css/parser/ParseException.java | 42 + .../jaxx/compiler/css/parser/SimpleCharStream.java | 429 + .../jaxx/compiler/css/parser/SimpleNode.java | 149 + .../org/nuiton/jaxx/compiler/css/parser/Token.java | 98 + .../jaxx/compiler/css/parser/TokenMgrError.java | 149 + .../decorators/BoxedCompiledObjectDecorator.java | 77 + .../decorators/DefaultCompiledObjectDecorator.java | 359 + .../HelpRootCompiledObjectDecorator.java | 218 + .../compiler/finalizers/AbstractFinalizer.java | 87 + .../jaxx/compiler/finalizers/DefaultFinalizer.java | 1191 +++ .../compiler/finalizers/JAXXCompilerFinalizer.java | 87 + .../jaxx/compiler/finalizers/SwingFinalizer.java | 89 + .../compiler/finalizers/ValidatorFinalizer.java | 278 + .../nuiton/jaxx/compiler/java/JavaArgument.java | 83 + .../nuiton/jaxx/compiler/java/JavaConstructor.java | 95 + .../org/nuiton/jaxx/compiler/java/JavaElement.java | 129 + .../jaxx/compiler/java/JavaElementFactory.java | 179 + .../org/nuiton/jaxx/compiler/java/JavaField.java | 294 + .../org/nuiton/jaxx/compiler/java/JavaFile.java | 518 + .../jaxx/compiler/java/JavaFileGenerator.java | 452 + .../org/nuiton/jaxx/compiler/java/JavaMethod.java | 355 + .../compiler/java/parser/JJTJavaParserState.java | 148 + .../nuiton}/jaxx/compiler/java/parser/Java1.5.jj | 0 .../nuiton}/jaxx/compiler/java/parser/Java1.5.jjt | 0 .../jaxx/compiler/java/parser/JavaCharStream.java | 560 + .../jaxx/compiler/java/parser/JavaParser.java | 10117 +++++++++++++++++++ .../compiler/java/parser/JavaParserConstants.java | 404 + .../java/parser/JavaParserTokenManager.java | 2156 ++++ .../java/parser/JavaParserTreeConstants.java | 361 + .../org/nuiton/jaxx/compiler/java/parser/Node.java | 73 + .../jaxx/compiler/java/parser/ParseException.java | 240 + .../jaxx/compiler/java/parser/SimpleNode.java | 163 + .../nuiton/jaxx/compiler/java/parser/Token.java | 101 + .../jaxx/compiler/java/parser/TokenMgrError.java | 149 + .../jaxx/compiler/reflect/ClassDescriptor.java | 295 + .../compiler/reflect/ClassDescriptorHelper.java | 533 + .../compiler/reflect/ClassDescriptorResolver.java | 67 + .../jaxx/compiler/reflect/FieldDescriptor.java | 54 + .../jaxx/compiler/reflect/MemberDescriptor.java | 61 + .../jaxx/compiler/reflect/MethodDescriptor.java | 75 + .../ClassDescriptorResolverFromJavaClass.java | 200 + .../ClassDescriptorResolverFromJavaFile.java | 746 ++ .../ClassDescriptorResolverFromJaxxFile.java | 199 + .../jaxx/compiler/script/ScriptInitializer.java | 42 + .../nuiton/jaxx/compiler/script/ScriptManager.java | 482 + .../jaxx/compiler/spi/DefaultInitializer.java | 228 + .../org/nuiton/jaxx/compiler/spi/Initializer.java | 41 + .../compiler/tags/DefaultComponentHandler.java | 465 + .../jaxx/compiler/tags/DefaultObjectHandler.java | 1350 +++ .../nuiton/jaxx/compiler/tags/ImportHandler.java | 101 + .../nuiton/jaxx/compiler/tags/ScriptHandler.java | 115 + .../nuiton/jaxx/compiler/tags/StyleHandler.java | 110 + .../org/nuiton/jaxx/compiler/tags/TagHandler.java | 68 + .../org/nuiton/jaxx/compiler/tags/TagManager.java | 646 ++ .../compiler/tags/swing/ApplicationHandler.java | 82 + .../jaxx/compiler/tags/swing/CellHandler.java | 221 + .../compiler/tags/swing/CompiledItemContainer.java | 69 + .../jaxx/compiler/tags/swing/ItemHandler.java | 174 + .../compiler/tags/swing/JAXXComboBoxHandler.java | 80 + .../jaxx/compiler/tags/swing/JAXXListHandler.java | 83 + .../jaxx/compiler/tags/swing/JAXXTabHandler.java | 33 + .../jaxx/compiler/tags/swing/JAXXTreeHandler.java | 88 + .../jaxx/compiler/tags/swing/JCheckBoxHandler.java | 44 + .../jaxx/compiler/tags/swing/JComboBoxHandler.java | 62 + .../compiler/tags/swing/JInternalFrameHandler.java | 72 + .../jaxx/compiler/tags/swing/JListHandler.java | 64 + .../jaxx/compiler/tags/swing/JMenuHandler.java | 44 + .../compiler/tags/swing/JPasswordFieldHandler.java | 43 + .../compiler/tags/swing/JPopupMenuHandler.java | 50 + .../compiler/tags/swing/JProgressBarHandler.java | 44 + .../compiler/tags/swing/JRadioButtonHandler.java | 106 + .../compiler/tags/swing/JScrollPaneHandler.java | 101 + .../jaxx/compiler/tags/swing/JSliderHandler.java | 67 + .../jaxx/compiler/tags/swing/JSpinnerHandler.java | 121 + .../compiler/tags/swing/JSplitPaneHandler.java | 99 + .../compiler/tags/swing/JTabbedPaneHandler.java | 168 + .../compiler/tags/swing/JTextComponentHandler.java | 112 + .../jaxx/compiler/tags/swing/JToolBarHandler.java | 78 + .../jaxx/compiler/tags/swing/JTreeHandler.java | 65 + .../jaxx/compiler/tags/swing/JWindowHandler.java | 80 + .../jaxx/compiler/tags/swing/JXLayerHandler.java | 108 + .../jaxx/compiler/tags/swing/RowHandler.java | 108 + .../jaxx/compiler/tags/swing/TabHandler.java | 218 + .../jaxx/compiler/tags/swing/TableHandler.java | 175 + .../tags/validator/BeanValidatorHandler.java | 1092 ++ .../validator/ExcludeFieldValidatorHandler.java | 127 + .../tags/validator/FieldValidatorHandler.java | 153 + .../jaxx/compiler/tasks/CompileFirstPassTask.java | 127 + .../jaxx/compiler/tasks/CompileSecondPassTask.java | 92 + .../nuiton/jaxx/compiler/tasks/FinalizeTask.java | 75 + .../compiler/tasks/GenerateConstructorsTask.java | 508 + .../compiler/tasks/GenerateMissingRulesTask.java | 130 + .../nuiton/jaxx/compiler/tasks/GenerateTask.java | 205 + .../org/nuiton/jaxx/compiler/tasks/InitTask.java | 83 + .../nuiton/jaxx/compiler/tasks/JAXXEngineTask.java | 83 + .../nuiton/jaxx/compiler/tasks/ProfileTask.java | 53 + .../nuiton/jaxx/compiler/tasks/StyleSheetTask.java | 77 + .../nuiton/jaxx/compiler/tools/PrintTagInfo.java | 143 + .../tools/jaxxcapture/AbstractContextNode.java | 41 + .../compiler/tools/jaxxcapture/CapturedObject.java | 176 + .../compiler/tools/jaxxcapture/ContextNode.java | 30 + .../compiler/tools/jaxxcapture/JAXXCapture.java | 405 + .../compiler/tools/jaxxcapture/LiteralNode.java | 43 + .../compiler/tools/jaxxcapture/MethodNode.java | 41 + .../compiler/tools/jaxxcapture/PropertyNode.java | 41 + .../jaxx/compiler/tools/jaxxcapture/ValueNode.java | 36 + .../jaxxcapture/handlers/JTabbedPaneHandler.java | 48 + .../tools/jaxxcapture/handlers/ObjectHandler.java | 346 + .../tools/jaxxcapture/handlers/TableHandler.java | 36 + .../nuiton/jaxx/compiler/types/ColorConverter.java | 60 + .../types/GridBagConstraintsConverter.java | 48 + .../jaxx/compiler/types/InsetsConverter.java | 61 + .../jaxx/compiler/types/KeyStrokeConverter.java | 46 + .../jaxx/compiler/types/PrimitiveConverter.java | 122 + .../nuiton/jaxx/compiler/types/TypeConverter.java | 32 + .../nuiton/jaxx/compiler/types/TypeManager.java | 126 + .../services/jaxx.compiler.CompiledObjectDecorator | 3 - .../services/jaxx.compiler.JAXXCompilerFinalizer | 3 - .../services/jaxx.compiler.spi.Initializer | 1 - .../services/jaxx.compiler.types.TypeConverter | 5 - ...rg.nuiton.jaxx.compiler.CompiledObjectDecorator | 3 + ....jaxx.compiler.finalizers.JAXXCompilerFinalizer | 3 + .../org.nuiton.jaxx.compiler.spi.Initializer | 1 + .../org.nuiton.jaxx.compiler.types.TypeConverter | 5 + .../java/jaxx/compiler/beans/BeanIntoUtilTest.java | 56 - .../jaxx/compiler/binding/JavaParserUtilTest.java | 324 - .../java/jaxx/compiler/java/JavaFieldTest.java | 124 - .../java/jaxx/compiler/java/JavaMethodTest.java | 88 - .../jaxx/compiler/java/parser/JavaParserTest.java | 128 - .../jaxx/compiler/reflect/ClassDescriptorTest.java | 153 - .../jaxx/compiler/reflect/MyAbstractClass.java | 35 - .../java/jaxx/compiler/reflect/MyChildClass.java | 45 - .../java/jaxx/compiler/reflect/MyChildClass2.java | 37 - .../test/java/jaxx/compiler/reflect/MyClass.java | 65 - .../test/java/jaxx/compiler/reflect/MyEnum.java | 42 - .../java/jaxx/compiler/reflect/MyInterface.java | 35 - .../java/jaxx/compiler/reflect/MyInterface2.java | 37 - .../java/jaxx/compiler/reflect/MyInterface3.java | 37 - .../ClassDescriptorResolverFromJavaFileTest.java | 394 - .../java/jaxx/compiler/tags/TagManagerTest.java | 168 - .../jaxx/compiler/types/ColorConverterTest.java | 72 - .../jaxx/compiler/types/InsetsConverterTest.java | 71 - .../compiler/types/PrimitiveConverterTest.java | 134 - .../java/jaxx/compiler/types/TypeManagerTest.java | 77 - .../jaxx/compiler/beans/BeanIntoUtilTest.java | 56 + .../jaxx/compiler/binding/JavaParserUtilTest.java | 324 + .../nuiton/jaxx/compiler/java/JavaFieldTest.java | 124 + .../nuiton/jaxx/compiler/java/JavaMethodTest.java | 88 + .../jaxx/compiler/java/parser/JavaParserTest.java | 128 + .../jaxx/compiler/reflect/ClassDescriptorTest.java | 153 + .../jaxx/compiler/reflect/MyAbstractClass.java | 35 + .../nuiton/jaxx/compiler/reflect/MyChildClass.java | 45 + .../jaxx/compiler/reflect/MyChildClass2.java | 37 + .../org/nuiton/jaxx/compiler/reflect/MyClass.java | 65 + .../org/nuiton/jaxx/compiler/reflect/MyEnum.java | 42 + .../nuiton/jaxx/compiler/reflect/MyInterface.java | 35 + .../nuiton/jaxx/compiler/reflect/MyInterface2.java | 37 + .../nuiton/jaxx/compiler/reflect/MyInterface3.java | 37 + .../ClassDescriptorResolverFromJavaFileTest.java | 394 + .../nuiton/jaxx/compiler/tags/TagManagerTest.java | 168 + .../jaxx/compiler/types/ColorConverterTest.java | 72 + .../jaxx/compiler/types/InsetsConverterTest.java | 71 + .../compiler/types/PrimitiveConverterTest.java | 134 + .../jaxx/compiler/types/TypeManagerTest.java | 77 + jaxx-compiler/src/test/resources/log4j.properties | 2 +- .../swing/config/ConfigCallBackUIHandler.java | 191 - .../runtime/swing/config/ConfigCategoryUI.jaxx | 87 - .../swing/config/ConfigCategoryUIHandler.java | 266 - .../runtime/swing/config/ConfigTableEditor.java | 173 - .../runtime/swing/config/ConfigTableRenderer.java | 126 - .../java/jaxx/runtime/swing/config/ConfigUI.jaxx | 56 - .../jaxx/runtime/swing/config/ConfigUIHandler.java | 433 - .../jaxx/runtime/swing/config/ConfigUIHelper.java | 221 - .../runtime/swing/config/model/CallBackEntry.java | 79 - .../swing/config/model/CallBackFinalizer.java | 40 - .../runtime/swing/config/model/CallBackMap.java | 56 - .../swing/config/model/CallBacksManager.java | 248 - .../runtime/swing/config/model/CategoryModel.java | 223 - .../swing/config/model/ConfigTableModel.java | 155 - .../runtime/swing/config/model/ConfigUIModel.java | 443 - .../swing/config/model/ConfigUIModelBuilder.java | 550 - .../swing/config/model/MainCallBackFinalizer.java | 63 - .../runtime/swing/config/model/OptionModel.java | 224 - .../nuiton/jaxx}/config/ConfigCallBackUI.jaxx | 0 .../jaxx/config/ConfigCallBackUIHandler.java | 191 + .../org/nuiton/jaxx/config/ConfigCategoryUI.jaxx | 87 + .../nuiton/jaxx}/config/ConfigCategoryUI.jcss | 0 .../jaxx/config/ConfigCategoryUIHandler.java | 266 + .../org/nuiton/jaxx/config/ConfigTableEditor.java | 173 + .../nuiton/jaxx/config/ConfigTableRenderer.java | 126 + .../main/java/org/nuiton/jaxx/config/ConfigUI.jaxx | 56 + .../swing => org/nuiton/jaxx}/config/ConfigUI.jcss | 0 .../org/nuiton/jaxx/config/ConfigUIHandler.java | 433 + .../org/nuiton/jaxx/config/ConfigUIHelper.java | 221 + .../nuiton/jaxx/config/model/CallBackEntry.java | 79 + .../jaxx/config/model/CallBackFinalizer.java | 40 + .../org/nuiton/jaxx/config/model/CallBackMap.java | 56 + .../nuiton/jaxx/config/model/CallBacksManager.java | 248 + .../nuiton/jaxx/config/model/CategoryModel.java | 223 + .../nuiton/jaxx/config/model/ConfigTableModel.java | 155 + .../nuiton/jaxx/config/model/ConfigUIModel.java | 443 + .../jaxx/config/model/ConfigUIModelBuilder.java | 550 + .../jaxx/config/model/MainCallBackFinalizer.java | 63 + .../org/nuiton/jaxx/config/model/OptionModel.java | 224 + .../nuiton/jaxx}/config/model/package.html | 0 .../swing => org/nuiton/jaxx}/config/package.html | 0 .../swing/config/model/MyDelegateConfig.java | 267 - .../swing/config/model/MyDelegateConfigTest.java | 337 - .../swing/config/model/MyInheritedConfig.java | 278 - .../swing/config/model/MyInheritedConfigTest.java | 349 - .../nuiton/jaxx/config/model/MyDelegateConfig.java | 267 + .../jaxx/config/model/MyDelegateConfigTest.java | 337 + .../jaxx/config/model/MyInheritedConfig.java | 278 + .../jaxx/config/model/MyInheritedConfigTest.java | 349 + jaxx-demo/pom.xml | 4 +- .../java/jaxx/demo/DemoApplicationContext.java | 175 - jaxx-demo/src/main/java/jaxx/demo/DemoConfig.java | 512 - .../src/main/java/jaxx/demo/DemoHelpBroker.java | 148 - jaxx-demo/src/main/java/jaxx/demo/DemoPanel.jaxx | 63 - jaxx-demo/src/main/java/jaxx/demo/DemoSources.jaxx | 90 - .../main/java/jaxx/demo/DemoSourcesHandler.java | 199 - jaxx-demo/src/main/java/jaxx/demo/DemoUI.jaxx | 110 - .../src/main/java/jaxx/demo/DemoUIHandler.java | 581 -- jaxx-demo/src/main/java/jaxx/demo/RunDemo.java | 158 - .../demo/component/jaxx/BoxedDecoratorDemo.jaxx | 122 - .../component/jaxx/StatusMessagePanelDemo.jaxx | 32 - .../component/jaxx/editor/BeanComboBoxDemo.jaxx | 53 - .../jaxx/editor/BeanComboBoxDemoHandler.java | 76 - .../component/jaxx/editor/BeanDoubleListDemo.jaxx | 48 - .../jaxx/editor/BeanDoubleListDemoHandler.java | 77 - .../jaxx/editor/BeanFilterableComboBoxDemo.jaxx | 54 - .../editor/BeanFilterableComboBoxDemoHandler.java | 78 - .../component/jaxx/editor/ComboEditorDemo.jaxx | 66 - .../demo/component/jaxx/editor/DatePickerDemo.jaxx | 96 - .../demo/component/jaxx/editor/FileEditorDemo.jaxx | 121 - .../demo/component/jaxx/editor/I18nEditorDemo.jaxx | 92 - .../component/jaxx/editor/ListSelectorDemo.jaxx | 101 - .../component/jaxx/editor/NumberEditorDemo.jaxx | 113 - .../jaxx/editor/NumberEditorDemoModel.java | 62 - .../jaxx/editor/SimpleTimeEditorDemo.jaxx | 81 - .../jaxx/editor/SimpleTimeEditorDemoHandler.java | 47 - .../jaxx/editor/SimpleTimeEditorDemoModel.java | 54 - .../demo/component/jaxx/editor/TimeEditorDemo.jaxx | 84 - .../component/jaxx/editor/TimeEditorDemoModel.java | 53 - .../component/jaxx/editor/gis/CoordinateDemo.jaxx | 97 - .../jaxx/editor/gis/CoordinateDemoHandler.java | 175 - .../jaxx/editor/gis/CoordinateDemoModel.java | 64 - .../jaxx/widgets/datetime/DateTimeEditorDemo.jaxx | 76 - .../datetime/DateTimeEditorDemoHandler.java | 80 - .../widgets/datetime/DateTimeEditorDemoModel.java | 74 - .../jaxx/widgets/datetime/TimeEditorDemo.jaxx | 54 - .../widgets/datetime/TimeEditorDemoHandler.java | 66 - .../jaxx/widgets/datetime/TimeEditorDemoModel.java | 50 - .../jaxx/widgets/gis/CoordinatesEditorDemo.jaxx | 55 - .../widgets/gis/CoordinatesEditorDemoHandler.java | 68 - .../widgets/gis/CoordinatesEditorDemoModel.java | 72 - .../jaxx/widgets/number/NumberEditorDemo.jaxx | 111 - .../widgets/number/NumberEditorDemoHandler.java | 56 - .../jaxx/widgets/number/NumberEditorDemoModel.java | 72 - .../widgets/select/FilterableDoubleListDemo.jaxx | 55 - .../select/FilterableDoubleListDemoHandler.java | 98 - .../select/FilterableDoubleListDemoModel.java | 52 - .../jaxx/demo/component/swing/HidorButtonDemo.jaxx | 42 - .../jaxx/demo/component/swing/JButtonDemo.jaxx | 61 - .../jaxx/demo/component/swing/JCheckBoxDemo.jaxx | 62 - .../jaxx/demo/component/swing/JComboBoxDemo.jaxx | 70 - .../jaxx/demo/component/swing/JDialogDemo.jaxx | 110 - .../java/jaxx/demo/component/swing/JListDemo.jaxx | 81 - .../jaxx/demo/component/swing/JMenuItemDemo.jaxx | 49 - .../demo/component/swing/JPasswordFieldDemo.jaxx | 32 - .../demo/component/swing/JProgressBarDemo.jaxx | 120 - .../demo/component/swing/JRadioButtonDemo.jaxx | 41 - .../jaxx/demo/component/swing/JSliderDemo.jaxx | 39 - .../jaxx/demo/component/swing/JSpinnerDemo.jaxx | 34 - .../jaxx/demo/component/swing/JSplitPaneDemo.jaxx | 38 - .../jaxx/demo/component/swing/JTextAreaDemo.jaxx | 51 - .../jaxx/demo/component/swing/JTextFieldDemo.jaxx | 45 - .../demo/component/swing/JToggleButtonDemo.jaxx | 32 - .../java/jaxx/demo/entities/AbstractDemoBean.java | 79 - .../java/jaxx/demo/entities/DemoDataProvider.java | 113 - .../jaxx/demo/entities/DemoDecoratorProvider.java | 48 - .../src/main/java/jaxx/demo/entities/Identity.java | 105 - .../src/main/java/jaxx/demo/entities/Model.java | 66 - .../src/main/java/jaxx/demo/entities/Movie.java | 138 - .../src/main/java/jaxx/demo/entities/People.java | 134 - .../feature/databinding/BaseBeanDataBinding.jaxx | 48 - .../feature/databinding/BindingExtremeDemo.jaxx | 290 - .../feature/databinding/DefaultDemoUIModel.java | 137 - .../jaxx/demo/feature/databinding/DemoUIModel.java | 96 - .../main/java/jaxx/demo/feature/nav/NavDemo.jaxx | 98 - .../java/jaxx/demo/feature/nav/NavDemoHandler.java | 298 - .../feature/nav/content/AbstractContentUI.jaxx | 46 - .../demo/feature/nav/content/ActorContentUI.jaxx | 56 - .../demo/feature/nav/content/ActorsContentUI.jaxx | 81 - .../demo/feature/nav/content/MovieContentUI.jaxx | 57 - .../demo/feature/nav/content/MoviesContentUI.jaxx | 81 - .../feature/nav/tree/ActorsTreeNodeLoador.java | 78 - .../feature/nav/tree/MoviesTreeNodeLoador.java | 93 - .../feature/nav/tree/NavDemoTreeCellRenderer.java | 115 - .../demo/feature/nav/tree/NavDemoTreeHelper.java | 85 - .../demo/feature/nav/tree/NavDemoTreeNode.java | 46 - .../nav/treetable/ActorsTreeTableNodeLoador.java | 79 - .../nav/treetable/MoviesTreeTableNodeLoador.java | 94 - .../nav/treetable/NavDemoTreeTableHelper.java | 85 - .../nav/treetable/NavDemoTreeTableModel.java | 116 - .../nav/treetable/NavDemoTreeTableNode.java | 44 - .../validation/list/ListBeanValidationDemo.jaxx | 103 - .../list/ListBeanValidationDemoHandler.java | 187 - .../feature/validation/list/PeopleTableModel.java | 150 - .../simple/SimpleBeanValidationByListDemo.jaxx | 372 - .../simple/SimpleBeanValidationByTableDemo.jaxx | 381 - .../main/java/jaxx/demo/fun/CalculatorDemo.jaxx | 143 - .../main/java/jaxx/demo/fun/CalculatorEngine.java | 208 - .../src/main/java/jaxx/demo/fun/CounterDemo.jaxx | 31 - .../main/java/jaxx/demo/fun/LabelStyleDemo.jaxx | 121 - .../main/java/jaxx/demo/tree/DemoCellRenderer.java | 106 - .../main/java/jaxx/demo/tree/DemoDataProvider.java | 253 - .../src/main/java/jaxx/demo/tree/DemoNode.java | 66 - .../main/java/jaxx/demo/tree/DemoNodeLoador.java | 84 - .../main/java/jaxx/demo/tree/DemoTreeHelper.java | 58 - .../nuiton/jaxx/demo/DemoApplicationContext.java | 175 + .../main/java/org/nuiton/jaxx/demo/DemoConfig.java | 512 + .../java/org/nuiton/jaxx/demo/DemoHelpBroker.java | 148 + .../main/java/org/nuiton/jaxx/demo/DemoPanel.jaxx | 63 + .../java/org/nuiton/jaxx/demo/DemoSources.jaxx | 90 + .../{ => org/nuiton}/jaxx/demo/DemoSources.jcss | 0 .../org/nuiton/jaxx/demo/DemoSourcesHandler.java | 199 + .../java/{ => org/nuiton}/jaxx/demo/DemoTab.jaxx | 0 .../src/main/java/org/nuiton/jaxx/demo/DemoUI.jaxx | 110 + .../java/{ => org/nuiton}/jaxx/demo/DemoUI.jcss | 0 .../java/org/nuiton/jaxx/demo/DemoUIHandler.java | 581 ++ .../main/java/org/nuiton/jaxx/demo/RunDemo.java | 158 + .../demo/component/jaxx/BoxedDecoratorDemo.jaxx | 122 + .../demo/component/jaxx/BoxedDecoratorDemo.jcss | 0 .../component/jaxx/StatusMessagePanelDemo.jaxx | 31 + .../component/jaxx/editor/BeanComboBoxDemo.jaxx | 53 + .../component/jaxx/editor/BeanComboBoxDemo.jcss | 0 .../jaxx/editor/BeanComboBoxDemoHandler.java | 76 + .../component/jaxx/editor/BeanDoubleListDemo.jaxx | 48 + .../component/jaxx/editor/BeanDoubleListDemo.jcss | 0 .../jaxx/editor/BeanDoubleListDemoHandler.java | 77 + .../jaxx/editor/BeanFilterableComboBoxDemo.jaxx | 54 + .../jaxx/editor/BeanFilterableComboBoxDemo.jcss | 0 .../editor/BeanFilterableComboBoxDemoHandler.java | 78 + .../component/jaxx/editor/ComboEditorDemo.jaxx | 66 + .../demo/component/jaxx/editor/DatePickerDemo.jaxx | 96 + .../demo/component/jaxx/editor/FileEditorDemo.jaxx | 121 + .../demo/component/jaxx/editor/I18nEditorDemo.jaxx | 92 + .../component/jaxx/editor/ListSelectorDemo.jaxx | 102 + .../component/jaxx/editor/NumberEditorDemo.jaxx | 113 + .../jaxx/editor/NumberEditorDemoModel.java | 62 + .../jaxx/editor/SimpleTimeEditorDemo.jaxx | 81 + .../jaxx/editor/SimpleTimeEditorDemo.jcss | 0 .../jaxx/editor/SimpleTimeEditorDemoHandler.java | 47 + .../jaxx/editor/SimpleTimeEditorDemoModel.java | 54 + .../demo/component/jaxx/editor/TimeEditorDemo.jaxx | 84 + .../demo/component/jaxx/editor/TimeEditorDemo.jcss | 0 .../component/jaxx/editor/TimeEditorDemoModel.java | 53 + .../component/jaxx/editor/gis/CoordinateDemo.jaxx | 97 + .../component/jaxx/editor/gis/CoordinateDemo.jcss | 0 .../jaxx/editor/gis/CoordinateDemoHandler.java | 175 + .../jaxx/editor/gis/CoordinateDemoModel.java | 64 + .../jaxx/widgets/datetime/DateTimeEditorDemo.jaxx | 76 + .../jaxx/widgets/datetime/DateTimeEditorDemo.jcss | 0 .../datetime/DateTimeEditorDemoHandler.java | 80 + .../widgets/datetime/DateTimeEditorDemoModel.java | 74 + .../jaxx/widgets/datetime/TimeEditorDemo.jaxx | 56 + .../jaxx/widgets/datetime/TimeEditorDemo.jcss | 0 .../widgets/datetime/TimeEditorDemoHandler.java | 66 + .../jaxx/widgets/datetime/TimeEditorDemoModel.java | 50 + .../jaxx/widgets/gis/CoordinatesEditorDemo.jaxx | 55 + .../jaxx/widgets/gis/CoordinatesEditorDemo.jcss | 0 .../widgets/gis/CoordinatesEditorDemoHandler.java | 68 + .../widgets/gis/CoordinatesEditorDemoModel.java | 72 + .../jaxx/widgets/number/NumberEditorDemo.jaxx | 112 + .../jaxx/widgets/number/NumberEditorDemo.jcss | 0 .../widgets/number/NumberEditorDemoHandler.java | 56 + .../jaxx/widgets/number/NumberEditorDemoModel.java | 72 + .../widgets/select/FilterableDoubleListDemo.jaxx | 55 + .../widgets/select/FilterableDoubleListDemo.jcss | 0 .../select/FilterableDoubleListDemoHandler.java | 98 + .../select/FilterableDoubleListDemoModel.java | 52 + .../jaxx/demo/component/swing/HidorButtonDemo.jaxx | 42 + .../jaxx/demo/component/swing/JButtonDemo.jaxx | 61 + .../jaxx/demo/component/swing/JButtonDemo.jcss | 0 .../jaxx/demo/component/swing/JCheckBoxDemo.jaxx | 62 + .../component/swing/JCheckBoxMenuItemDemo.jaxx | 0 .../jaxx/demo/component/swing/JComboBoxDemo.jaxx | 70 + .../jaxx/demo/component/swing/JDialogDemo.jaxx | 110 + .../jaxx/demo/component/swing/JListDemo.jaxx | 81 + .../jaxx/demo/component/swing/JMenuItemDemo.jaxx | 49 + .../demo/component/swing/JPasswordFieldDemo.jaxx | 32 + .../demo/component/swing/JProgressBarDemo.jaxx | 120 + .../demo/component/swing/JRadioButtonDemo.jaxx | 41 + .../component/swing/JRadioButtonMenuItemDemo.jaxx | 0 .../jaxx/demo/component/swing/JSliderDemo.jaxx | 39 + .../jaxx/demo/component/swing/JSpinnerDemo.jaxx | 34 + .../jaxx/demo/component/swing/JSplitPaneDemo.jaxx | 38 + .../jaxx/demo/component/swing/JTextAreaDemo.jaxx | 51 + .../jaxx/demo/component/swing/JTextFieldDemo.jaxx | 45 + .../demo/component/swing/JToggleButtonDemo.jaxx | 32 + .../jaxx/demo/entities/AbstractDemoBean.java | 79 + .../jaxx/demo/entities/DemoDataProvider.java | 113 + .../jaxx/demo/entities/DemoDecoratorProvider.java | 48 + .../org/nuiton/jaxx/demo/entities/Identity.java | 105 + .../java/org/nuiton/jaxx/demo/entities/Model.java | 66 + .../java/org/nuiton/jaxx/demo/entities/Movie.java | 138 + .../java/org/nuiton/jaxx/demo/entities/People.java | 134 + .../feature/databinding/BaseBeanDataBinding.jaxx | 48 + .../feature/databinding/BeanDataBindingDemo.jaxx | 0 .../feature/databinding/BindingExtremeDemo.jaxx | 290 + .../feature/databinding/DefaultDemoUIModel.java | 137 + .../jaxx/demo/feature/databinding/DemoUIModel.java | 96 + .../org/nuiton/jaxx/demo/feature/nav/NavDemo.jaxx | 98 + .../jaxx/demo/feature/nav/NavDemoHandler.java | 298 + .../feature/nav/content/AbstractContentUI.jaxx | 46 + .../demo/feature/nav/content/ActorContentUI.jaxx | 56 + .../demo/feature/nav/content/ActorsContentUI.jaxx | 81 + .../demo/feature/nav/content/MovieContentUI.jaxx | 57 + .../demo/feature/nav/content/MoviesContentUI.jaxx | 81 + .../feature/nav/tree/ActorsTreeNodeLoador.java | 78 + .../feature/nav/tree/MoviesTreeNodeLoador.java | 93 + .../feature/nav/tree/NavDemoTreeCellRenderer.java | 115 + .../demo/feature/nav/tree/NavDemoTreeHelper.java | 85 + .../demo/feature/nav/tree/NavDemoTreeNode.java | 46 + .../nav/treetable/ActorsTreeTableNodeLoador.java | 79 + .../nav/treetable/MoviesTreeTableNodeLoador.java | 94 + .../nav/treetable/NavDemoTreeTableHelper.java | 85 + .../nav/treetable/NavDemoTreeTableModel.java | 116 + .../nav/treetable/NavDemoTreeTableNode.java | 44 + .../validation/list/ListBeanValidationDemo.jaxx | 103 + .../validation/list/ListBeanValidationDemo.jcss | 0 .../list/ListBeanValidationDemoHandler.java | 187 + .../feature/validation/list/PeopleTableModel.java | 150 + .../simple/SimpleBeanValidationByListDemo.jaxx | 372 + .../simple/SimpleBeanValidationByTableDemo.jaxx | 381 + .../demo/feature/validation/simple/Validation.jcss | 0 .../org/nuiton/jaxx/demo/fun/CalculatorDemo.jaxx | 143 + .../nuiton}/jaxx/demo/fun/CalculatorDemo.jcss | 0 .../org/nuiton/jaxx/demo/fun/CalculatorEngine.java | 208 + .../java/org/nuiton/jaxx/demo/fun/CounterDemo.jaxx | 31 + .../org/nuiton/jaxx/demo/fun/LabelStyleDemo.jaxx | 121 + .../nuiton}/jaxx/demo/fun/LabelStyleDemo.jcss | 0 .../nuiton/jaxx/demo/tree/DemoCellRenderer.java | 106 + .../nuiton/jaxx/demo/tree/DemoDataProvider.java | 253 + .../java/org/nuiton/jaxx/demo/tree/DemoNode.java | 66 + .../org/nuiton/jaxx/demo/tree/DemoNodeLoador.java | 84 + .../org/nuiton/jaxx/demo/tree/DemoTreeHelper.java | 58 + jaxx-demo/src/main/resources/log4j.properties | 9 - .../demo/entities/Identity-error-validation.xml | 0 .../demo/entities/Identity-info-validation.xml | 0 .../demo/entities/Identity-warning-validation.xml | 0 .../jaxx/demo/entities/Model-error-validation.xml | 0 .../jaxx/demo/entities/Model-info-validation.xml | 0 .../demo/entities/Model-warning-validation.xml | 0 .../jaxx/demo/entities/People-error-validation.xml | 0 .../jaxx/demo/entities/People-info-validation.xml | 0 .../demo/entities/People-warning-validation.xml | 0 .../{ => org/nuiton}/jaxx/demo/images/Amethyst.jpg | Bin .../{ => org/nuiton}/jaxx/demo/images/Lynx.jpg | Bin .../{ => org/nuiton}/jaxx/demo/images/Tomato.jpg | Bin .../{ => org/nuiton}/jaxx/demo/images/ana.jpg | Bin .../{ => org/nuiton}/jaxx/demo/images/hector.jpg | Bin .../{ => org/nuiton}/jaxx/demo/images/jack.jpg | Bin .../{ => org/nuiton}/jaxx/demo/images/jim.jpg | Bin .../{ => org/nuiton}/jaxx/demo/images/joe.jpg | Bin .../{ => org/nuiton}/jaxx/demo/images/joker.jpg | Bin .../{ => org/nuiton}/jaxx/demo/images/nacho.jpg | Bin .../{ => org/nuiton}/jaxx/demo/images/nacho2.png | Bin .../nuiton}/jaxx/demo/images/pencil_black.gif | Bin .../java/jaxx/demo/BeanValidatorDetectorTest.java | 84 - .../jaxx/demo/BeanValidatorDetectorTest.java | 84 + .../nuiton/jaxx/plugin/GenerateHelpIdsMojo.java | 2 +- .../java/org/nuiton/jaxx/plugin/GenerateMojo.java | 42 +- .../java/org/nuiton/jaxx/plugin/Bug1124Test.java | 3 +- .../java/org/nuiton/jaxx/plugin/Bug1404Test.java | 4 +- .../java/org/nuiton/jaxx/plugin/Bug1750Test.java | 8 +- .../java/org/nuiton/jaxx/plugin/CompilerTest.java | 2 +- .../java/org/nuiton/jaxx/plugin/JaxxBaseTest.java | 12 +- .../src/test/resources/log4j.properties | 2 +- .../validator/ok/Validation.jaxx | 4 +- .../jaxx/plugin/lambdaTest/LambdaHandler.java | 4 +- .../src/main/java/jaxx/runtime/Base64Coder.java | 264 - .../java/jaxx/runtime/ComponentDescriptor.java | 70 - .../java/jaxx/runtime/DataBindingListener.java | 65 - .../jaxx/runtime/DataBindingUpdateListener.java | 65 - .../main/java/jaxx/runtime/FileChooserUtil.java | 359 - .../src/main/java/jaxx/runtime/JAXXAction.java | 42 - .../src/main/java/jaxx/runtime/JAXXBinding.java | 57 - .../src/main/java/jaxx/runtime/JAXXContext.java | 129 - .../src/main/java/jaxx/runtime/JAXXObject.java | 167 - .../java/jaxx/runtime/JAXXObjectDescriptor.java | 61 - .../src/main/java/jaxx/runtime/JAXXUtil.java | 664 -- .../src/main/java/jaxx/runtime/SwingUtil.java | 1531 --- .../jaxx/runtime/awt/visitor/BuildTreeVisitor.java | 69 - .../runtime/awt/visitor/ComponentTreeNode.java | 111 - .../awt/visitor/ComponentTreeNodeVisitor.java | 36 - .../awt/visitor/DebugComponentTreeNodeVisitor.java | 87 - .../awt/visitor/GetCompopentAtPointVisitor.java | 114 - .../main/java/jaxx/runtime/bean/BeanTypeAware.java | 41 - .../jaxx/runtime/binding/DefaultJAXXBinding.java | 162 - .../runtime/binding/SimpleJAXXObjectBinding.java | 81 - .../java/jaxx/runtime/context/DataContext.java | 448 - .../runtime/context/DefaultApplicationContext.java | 473 - .../jaxx/runtime/context/DefaultJAXXContext.java | 229 - .../jaxx/runtime/context/JAXXContextEntryDef.java | 138 - .../jaxx/runtime/context/JAXXInitialContext.java | 118 - .../main/java/jaxx/runtime/css/DataBinding.java | 49 - .../main/java/jaxx/runtime/css/Pseudoclasses.java | 202 - .../src/main/java/jaxx/runtime/css/Rule.java | 73 - .../src/main/java/jaxx/runtime/css/Selector.java | 119 - .../src/main/java/jaxx/runtime/css/Stylesheet.java | 63 - .../src/main/java/jaxx/runtime/spi/UIHandler.java | 38 - .../main/java/jaxx/runtime/swing/Application.java | 72 - .../java/jaxx/runtime/swing/BlockingLayerUI.java | 375 - .../java/jaxx/runtime/swing/BlockingLayerUI2.java | 241 - .../main/java/jaxx/runtime/swing/CardLayout2.java | 256 - .../java/jaxx/runtime/swing/CardLayout2Ext.java | 128 - .../java/jaxx/runtime/swing/ComponentMover.java | 380 - .../java/jaxx/runtime/swing/ComponentResizer.java | 475 - .../src/main/java/jaxx/runtime/swing/GBC.java | 132 - .../src/main/java/jaxx/runtime/swing/HBox.java | 116 - .../main/java/jaxx/runtime/swing/HBoxBeanInfo.java | 73 - .../main/java/jaxx/runtime/swing/HBoxLayout.java | 146 - .../src/main/java/jaxx/runtime/swing/Item.java | 250 - .../java/jaxx/runtime/swing/JAXXButtonGroup.java | 250 - .../main/java/jaxx/runtime/swing/JAXXComboBox.java | 312 - .../src/main/java/jaxx/runtime/swing/JAXXList.java | 414 - .../src/main/java/jaxx/runtime/swing/JAXXTab.java | 28 - .../java/jaxx/runtime/swing/JAXXToggleButton.java | 122 - .../src/main/java/jaxx/runtime/swing/JAXXTree.java | 278 - .../src/main/java/jaxx/runtime/swing/JTables.java | 117 - .../runtime/swing/OneClicListSelectionModel.java | 224 - .../src/main/java/jaxx/runtime/swing/Spacer.java | 29 - .../src/main/java/jaxx/runtime/swing/TabInfo.java | 231 - .../swing/TabInfoPropertyChangeListener.java | 67 - .../src/main/java/jaxx/runtime/swing/Table.java | 79 - .../src/main/java/jaxx/runtime/swing/VBox.java | 116 - .../main/java/jaxx/runtime/swing/VBoxBeanInfo.java | 73 - .../main/java/jaxx/runtime/swing/VBoxLayout.java | 146 - .../runtime/swing/application/ActionExecutor.java | 276 - .../runtime/swing/application/ActionWorker.java | 175 - .../swing/application/ApplicationRunner.java | 247 - .../runtime/swing/editor/BooleanCellEditor.java | 80 - .../jaxx/runtime/swing/editor/ClassCellEditor.java | 129 - .../jaxx/runtime/swing/editor/ColorCellEditor.java | 128 - .../java/jaxx/runtime/swing/editor/EnumEditor.java | 146 - .../jaxx/runtime/swing/editor/LocaleEditor.java | 71 - .../runtime/swing/editor/MyDefaultCellEditor.java | 124 - .../jaxx/runtime/swing/help/JAXXHelpBroker.java | 613 -- .../java/jaxx/runtime/swing/help/JAXXHelpUI.java | 41 - .../jaxx/runtime/swing/help/JAXXHelpUIHandler.java | 30 - .../model/AbstractGenericListSelectionModel.java | 273 - .../swing/model/AbstractSelectionListModel.java | 32 - .../jaxx/runtime/swing/model/ComboBoxModel2.java | 50 - .../swing/model/ComboBoxSelectionEvent.java | 69 - .../jaxx/runtime/swing/model/GenericListEvent.java | 42 - .../runtime/swing/model/GenericListListener.java | 38 - .../jaxx/runtime/swing/model/GenericListModel.java | 162 - .../swing/model/GenericListSelectionModel.java | 51 - .../swing/model/JaxxDefaultComboBoxModel.java | 219 - .../runtime/swing/model/JaxxDefaultListModel.java | 618 -- .../swing/model/JaxxFilterableComboBoxModel.java | 235 - .../swing/model/JaxxFilterableListModel.java | 259 - .../model/WillChangeSelectedItemListener.java | 41 - .../model/WillChangeSelectedItemVetoException.java | 58 - .../java/jaxx/runtime/swing/nav/NavBridge.java | 122 - .../jaxx/runtime/swing/nav/NavDataProvider.java | 43 - .../java/jaxx/runtime/swing/nav/NavHelper.java | 960 -- .../main/java/jaxx/runtime/swing/nav/NavNode.java | 220 - .../jaxx/runtime/swing/nav/NavNodeChildLoador.java | 167 - .../nav/tree/AbstractNavTreeCellRenderer.java | 125 - .../jaxx/runtime/swing/nav/tree/NavTreeBridge.java | 237 - .../jaxx/runtime/swing/nav/tree/NavTreeHelper.java | 182 - .../jaxx/runtime/swing/nav/tree/NavTreeNode.java | 425 - .../swing/nav/tree/NavTreeNodeChildLoador.java | 41 - .../swing/nav/treetable/NavTreeTableBridge.java | 294 - .../swing/nav/treetable/NavTreeTableHelper.java | 180 - .../swing/nav/treetable/NavTreeTableModel.java | 212 - .../swing/nav/treetable/NavTreeTableNode.java | 376 - .../nav/treetable/NavTreeTableNodeChildLoador.java | 39 - .../swing/renderer/BooleanCellRenderer.java | 108 - .../swing/renderer/ClassTableCellRenderer.java | 58 - .../runtime/swing/renderer/ColorCellRenderer.java | 50 - .../swing/renderer/DecoratorListCellRenderer.java | 80 - .../DecoratorProviderListCellRenderer.java | 75 - .../DecoratorProviderTableCellRenderer.java | 73 - .../swing/renderer/DecoratorTableCellRenderer.java | 87 - .../renderer/EmptyNumberTableCellRenderer.java | 61 - .../runtime/swing/renderer/EnumEditorRenderer.java | 53 - .../swing/renderer/EnumTableCellRenderer.java | 66 - .../FilteredDecoratorListCellRenderer.java | 135 - .../swing/renderer/I18nTableCellRenderer.java | 106 - .../swing/renderer/LocaleListCellRenderer.java | 146 - .../renderer/MultiDecoratorListCellRenderer.java | 87 - .../renderer/MultiDecoratorTableCelleRenderer.java | 97 - .../runtime/swing/session/JSplitPaneState.java | 97 - .../runtime/swing/session/JTabbedPaneState.java | 97 - .../jaxx/runtime/swing/session/JTableState.java | 155 - .../swing/session/JXTableSwingSessionState.java | 109 - .../java/jaxx/runtime/swing/session/State.java | 38 - .../jaxx/runtime/swing/session/SwingSession.java | 478 - .../jaxx/runtime/swing/session/WindowState.java | 202 - .../runtime/swing/wizard/BusyChangeListener.java | 113 - .../jaxx/runtime/swing/wizard/WizardModel.java | 306 - .../java/jaxx/runtime/swing/wizard/WizardStep.java | 41 - .../jaxx/runtime/swing/wizard/WizardStepUI.java | 35 - .../java/jaxx/runtime/swing/wizard/WizardUI.java | 82 - .../jaxx/runtime/swing/wizard/WizardUILancher.java | 250 - .../java/jaxx/runtime/swing/wizard/WizardUtil.java | 191 - .../runtime/swing/wizard/ext/WizardExtModel.java | 435 - .../runtime/swing/wizard/ext/WizardExtStep.java | 75 - .../swing/wizard/ext/WizardExtStepModel.java | 108 - .../jaxx/runtime/swing/wizard/ext/WizardExtUI.java | 57 - .../runtime/swing/wizard/ext/WizardExtUtil.java | 121 - .../jaxx/runtime/swing/wizard/ext/WizardState.java | 48 - .../java/org/nuiton/jaxx/runtime/Base64Coder.java | 264 + .../nuiton/jaxx/runtime/ComponentDescriptor.java | 70 + .../nuiton/jaxx/runtime/DataBindingListener.java | 65 + .../jaxx/runtime/DataBindingUpdateListener.java | 65 + .../org/nuiton/jaxx/runtime/FileChooserUtil.java | 358 + .../java/org/nuiton/jaxx/runtime/JAXXAction.java | 42 + .../java/org/nuiton/jaxx/runtime/JAXXBinding.java | 57 + .../java/org/nuiton/jaxx/runtime/JAXXContext.java | 129 + .../java/org/nuiton/jaxx/runtime/JAXXObject.java | 167 + .../nuiton/jaxx/runtime/JAXXObjectDescriptor.java | 61 + .../java/org/nuiton/jaxx/runtime/JAXXUtil.java | 664 ++ .../java/org/nuiton/jaxx/runtime/SwingUtil.java | 1531 +++ .../jaxx/runtime/awt/visitor/BuildTreeVisitor.java | 69 + .../runtime/awt/visitor/ComponentTreeNode.java | 111 + .../awt/visitor/ComponentTreeNodeVisitor.java | 36 + .../awt/visitor/DebugComponentTreeNodeVisitor.java | 87 + .../awt/visitor/GetCompopentAtPointVisitor.java | 114 + .../nuiton}/jaxx/runtime/awt/visitor/package.html | 0 .../nuiton/jaxx/runtime/bean/BeanTypeAware.java | 41 + .../jaxx/runtime/binding/DefaultJAXXBinding.java | 162 + .../runtime/binding/SimpleJAXXObjectBinding.java | 81 + .../nuiton/jaxx/runtime/context/DataContext.java | 448 + .../runtime/context/DefaultApplicationContext.java | 473 + .../jaxx/runtime/context/DefaultJAXXContext.java | 229 + .../jaxx/runtime/context/JAXXContextEntryDef.java | 138 + .../jaxx/runtime/context/JAXXInitialContext.java | 118 + .../org/nuiton/jaxx/runtime/css/DataBinding.java | 49 + .../org/nuiton/jaxx/runtime/css/Pseudoclasses.java | 202 + .../java/org/nuiton/jaxx/runtime/css/Rule.java | 73 + .../java/org/nuiton/jaxx/runtime/css/Selector.java | 119 + .../org/nuiton/jaxx/runtime/css/Stylesheet.java | 63 + .../org/nuiton/jaxx/runtime/spi/UIHandler.java | 38 + .../org/nuiton/jaxx/runtime/swing/Application.java | 72 + .../nuiton/jaxx/runtime/swing/BlockingLayerUI.java | 375 + .../jaxx/runtime/swing/BlockingLayerUI2.java | 241 + .../org/nuiton/jaxx/runtime/swing/CardLayout2.java | 256 + .../nuiton/jaxx/runtime/swing/CardLayout2Ext.java | 128 + .../nuiton/jaxx/runtime/swing/ComponentMover.java | 380 + .../jaxx/runtime/swing/ComponentResizer.java | 475 + .../java/org/nuiton/jaxx/runtime/swing/GBC.java | 132 + .../java/org/nuiton/jaxx/runtime/swing/HBox.java | 116 + .../nuiton/jaxx/runtime/swing/HBoxBeanInfo.java | 73 + .../org/nuiton/jaxx/runtime/swing/HBoxLayout.java | 146 + .../java/org/nuiton/jaxx/runtime/swing/Item.java | 250 + .../nuiton/jaxx/runtime/swing/JAXXButtonGroup.java | 250 + .../nuiton/jaxx/runtime/swing/JAXXComboBox.java | 312 + .../org/nuiton/jaxx/runtime/swing/JAXXList.java | 414 + .../org/nuiton/jaxx/runtime/swing/JAXXTab.java | 28 + .../jaxx/runtime/swing/JAXXToggleButton.java | 122 + .../org/nuiton/jaxx/runtime/swing/JAXXTree.java | 278 + .../org/nuiton/jaxx/runtime/swing/JTables.java | 117 + .../runtime/swing/OneClicListSelectionModel.java | 224 + .../java/org/nuiton/jaxx/runtime/swing/Spacer.java | 29 + .../org/nuiton/jaxx/runtime/swing/TabInfo.java | 231 + .../swing/TabInfoPropertyChangeListener.java | 67 + .../java/org/nuiton/jaxx/runtime/swing/Table.java | 79 + .../java/org/nuiton/jaxx/runtime/swing/VBox.java | 116 + .../nuiton/jaxx/runtime/swing/VBoxBeanInfo.java | 73 + .../org/nuiton/jaxx/runtime/swing/VBoxLayout.java | 146 + .../runtime/swing/application/ActionExecutor.java | 276 + .../runtime/swing/application/ActionWorker.java | 175 + .../swing/application/ApplicationRunner.java | 247 + .../runtime/swing/editor/BooleanCellEditor.java | 80 + .../jaxx/runtime/swing/editor/ClassCellEditor.java | 129 + .../jaxx/runtime/swing/editor/ColorCellEditor.java | 128 + .../jaxx/runtime/swing/editor/EnumEditor.java | 146 + .../jaxx/runtime/swing/editor/LocaleEditor.java | 71 + .../runtime/swing/editor/MyDefaultCellEditor.java | 124 + .../jaxx/runtime/swing/help/JAXXHelpBroker.java | 613 ++ .../nuiton/jaxx/runtime/swing/help/JAXXHelpUI.java | 41 + .../jaxx/runtime/swing/help/JAXXHelpUIHandler.java | 30 + .../model/AbstractGenericListSelectionModel.java | 273 + .../swing/model/AbstractSelectionListModel.java | 32 + .../jaxx/runtime/swing/model/ComboBoxModel2.java | 50 + .../swing/model/ComboBoxSelectionEvent.java | 69 + .../jaxx/runtime/swing/model/GenericListEvent.java | 42 + .../runtime/swing/model/GenericListListener.java | 38 + .../jaxx/runtime/swing/model/GenericListModel.java | 162 + .../swing/model/GenericListSelectionModel.java | 51 + .../swing/model/JaxxDefaultComboBoxModel.java | 219 + .../runtime/swing/model/JaxxDefaultListModel.java | 618 ++ .../swing/model/JaxxFilterableComboBoxModel.java | 235 + .../swing/model/JaxxFilterableListModel.java | 259 + .../model/WillChangeSelectedItemListener.java | 41 + .../model/WillChangeSelectedItemVetoException.java | 58 + .../nuiton/jaxx/runtime/swing/nav/NavBridge.java | 122 + .../jaxx/runtime/swing/nav/NavDataProvider.java | 43 + .../nuiton/jaxx/runtime/swing/nav/NavHelper.java | 960 ++ .../org/nuiton/jaxx/runtime/swing/nav/NavNode.java | 220 + .../jaxx/runtime/swing/nav/NavNodeChildLoador.java | 167 + .../nuiton}/jaxx/runtime/swing/nav/package.html | 0 .../nav/tree/AbstractNavTreeCellRenderer.java | 125 + .../jaxx/runtime/swing/nav/tree/NavTreeBridge.java | 237 + .../jaxx/runtime/swing/nav/tree/NavTreeHelper.java | 182 + .../jaxx/runtime/swing/nav/tree/NavTreeNode.java | 425 + .../swing/nav/tree/NavTreeNodeChildLoador.java | 41 + .../jaxx/runtime/swing/nav/tree/package.html | 0 .../swing/nav/treetable/NavTreeTableBridge.java | 294 + .../swing/nav/treetable/NavTreeTableHelper.java | 180 + .../swing/nav/treetable/NavTreeTableModel.java | 212 + .../swing/nav/treetable/NavTreeTableNode.java | 376 + .../nav/treetable/NavTreeTableNodeChildLoador.java | 39 + .../jaxx/runtime/swing/nav/treetable/package.html | 0 .../swing/renderer/BooleanCellRenderer.java | 108 + .../swing/renderer/ClassTableCellRenderer.java | 58 + .../runtime/swing/renderer/ColorCellRenderer.java | 50 + .../swing/renderer/DecoratorListCellRenderer.java | 80 + .../DecoratorProviderListCellRenderer.java | 75 + .../DecoratorProviderTableCellRenderer.java | 73 + .../swing/renderer/DecoratorTableCellRenderer.java | 87 + .../renderer/EmptyNumberTableCellRenderer.java | 61 + .../runtime/swing/renderer/EnumEditorRenderer.java | 53 + .../swing/renderer/EnumTableCellRenderer.java | 66 + .../FilteredDecoratorListCellRenderer.java | 135 + .../swing/renderer/I18nTableCellRenderer.java | 106 + .../swing/renderer/LocaleListCellRenderer.java | 146 + .../renderer/MultiDecoratorListCellRenderer.java | 87 + .../renderer/MultiDecoratorTableCelleRenderer.java | 97 + .../runtime/swing/session/JSplitPaneState.java | 97 + .../runtime/swing/session/JTabbedPaneState.java | 97 + .../jaxx/runtime/swing/session/JTableState.java | 154 + .../swing/session/JXTableSwingSessionState.java | 109 + .../nuiton/jaxx/runtime/swing/session/State.java | 38 + .../jaxx/runtime/swing/session/SwingSession.java | 478 + .../jaxx/runtime/swing/session/WindowState.java | 202 + .../runtime/swing/wizard/BusyChangeListener.java | 113 + .../jaxx/runtime/swing/wizard/WizardModel.java | 306 + .../jaxx/runtime/swing/wizard/WizardStep.java | 41 + .../jaxx/runtime/swing/wizard/WizardStepUI.java | 35 + .../nuiton/jaxx/runtime/swing/wizard/WizardUI.java | 82 + .../jaxx/runtime/swing/wizard/WizardUILancher.java | 250 + .../jaxx/runtime/swing/wizard/WizardUtil.java | 191 + .../runtime/swing/wizard/ext/WizardExtModel.java | 435 + .../runtime/swing/wizard/ext/WizardExtStep.java | 75 + .../swing/wizard/ext/WizardExtStepModel.java | 108 + .../jaxx/runtime/swing/wizard/ext/WizardExtUI.java | 57 + .../runtime/swing/wizard/ext/WizardExtUtil.java | 121 + .../jaxx/runtime/swing/wizard/ext/WizardState.java | 48 + .../jaxx/runtime/swing/wizard/ext/package.html | 0 .../nuiton}/jaxx/runtime/swing/wizard/package.html | 0 .../src/test/java/jaxx/runtime/UtilTest.java | 50 - .../context/DataContextEntryIteratorTest.java | 285 - .../context/DefaultApplicationContextTest.java | 221 - .../runtime/context/DefaultJAXXContextTest.java | 256 - .../java/org/nuiton/jaxx/runtime/UtilTest.java | 51 + .../context/DataContextEntryIteratorTest.java | 285 + .../context/DefaultApplicationContextTest.java | 221 + .../runtime/context/DefaultJAXXContextTest.java | 256 + jaxx-runtime/src/test/resources/log4j.properties | 2 +- jaxx-validator/pom.xml | 2 +- .../src/main/java/jaxx/runtime/JAXXValidator.java | 61 - .../SimpleBeanValidatorMessageTableModel.java | 269 - .../SimpleBeanValidatorMessageTableRenderer.java | 117 - .../validator/swing/SwingListValidator.java | 131 - .../swing/SwingListValidatorDataLocator.java | 77 - .../SwingListValidatorHighlightPredicate.java | 139 - .../validator/swing/SwingListValidatorMessage.java | 67 - .../swing/SwingListValidatorMessageTableModel.java | 275 - ...wingListValidatorMessageTableMouseListener.java | 149 - .../SwingListValidatorMessageTableRenderer.java | 132 - .../swing/SwingListValidatorMessageWidget.java | 294 - ...SwingListValidatorTableEditorModelListener.java | 149 - .../runtime/validator/swing/SwingValidator.java | 485 - .../validator/swing/SwingValidatorMessage.java | 65 - .../swing/SwingValidatorMessageListModel.java | 191 - .../SwingValidatorMessageListMouseListener.java | 90 - .../swing/SwingValidatorMessageListRenderer.java | 128 - .../swing/SwingValidatorMessageTableModel.java | 360 - .../SwingValidatorMessageTableMouseListener.java | 126 - .../swing/SwingValidatorMessageTableRenderer.java | 117 - .../swing/SwingValidatorMessageWidget.java | 279 - .../validator/swing/SwingValidatorUtil.java | 762 -- .../runtime/validator/swing/meta/Validator.java | 45 - .../validator/swing/meta/ValidatorField.java | 60 - .../swing/ui/AbstractBeanValidatorUI.java | 102 - .../validator/swing/ui/IconValidationUI.java | 109 - .../validator/swing/ui/ImageValidationUI.java | 98 - .../swing/ui/TranslucentValidationUI.java | 79 - .../swing/unified/UnifiedValidatorMessage.java | 198 - .../unified/UnifiedValidatorMessageTableModel.java | 473 - .../UnifiedValidatorMessageTableMouseListener.java | 158 - .../UnifiedValidatorMessageTableRenderer.java | 187 - .../swing/unified/UnifiedValidatorMessageUtil.java | 187 - .../unified/UnifiedValidatorMessageWidget.java | 319 - .../validator/swing/unified/package-info.java | 30 - .../org/nuiton/jaxx/validator/JAXXValidator.java | 61 + .../SimpleBeanValidatorMessageTableModel.java | 269 + .../SimpleBeanValidatorMessageTableRenderer.java | 117 + .../jaxx/validator/swing/SwingListValidator.java | 131 + .../swing/SwingListValidatorDataLocator.java | 77 + .../SwingListValidatorHighlightPredicate.java | 139 + .../validator/swing/SwingListValidatorMessage.java | 67 + .../swing/SwingListValidatorMessageTableModel.java | 275 + ...wingListValidatorMessageTableMouseListener.java | 149 + .../SwingListValidatorMessageTableRenderer.java | 132 + .../swing/SwingListValidatorMessageWidget.java | 294 + ...SwingListValidatorTableEditorModelListener.java | 149 + .../jaxx/validator/swing/SwingValidator.java | 485 + .../validator/swing/SwingValidatorMessage.java | 65 + .../swing/SwingValidatorMessageListModel.java | 191 + .../SwingValidatorMessageListMouseListener.java | 90 + .../swing/SwingValidatorMessageListRenderer.java | 128 + .../swing/SwingValidatorMessageTableModel.java | 360 + .../SwingValidatorMessageTableMouseListener.java | 126 + .../swing/SwingValidatorMessageTableRenderer.java | 117 + .../swing/SwingValidatorMessageWidget.java | 279 + .../jaxx/validator/swing/SwingValidatorUtil.java | 762 ++ .../jaxx/validator/swing/meta/Validator.java | 45 + .../jaxx/validator/swing/meta/ValidatorField.java | 60 + .../swing/ui/AbstractBeanValidatorUI.java | 102 + .../jaxx/validator/swing/ui/IconValidationUI.java | 108 + .../jaxx/validator/swing/ui/ImageValidationUI.java | 97 + .../swing/ui/TranslucentValidationUI.java | 78 + .../swing/unified/UnifiedValidatorMessage.java | 198 + .../unified/UnifiedValidatorMessageTableModel.java | 473 + .../UnifiedValidatorMessageTableMouseListener.java | 158 + .../UnifiedValidatorMessageTableRenderer.java | 187 + .../swing/unified/UnifiedValidatorMessageUtil.java | 187 + .../unified/UnifiedValidatorMessageWidget.java | 319 + .../jaxx/validator/swing/unified/package-info.java | 30 + .../nuiton/jaxx/widgets/about/AboutUIBuilder.java | 2 +- .../nuiton/jaxx/widgets/DecoratorPopupHandler.java | 2 +- .../jaxx/widgets/datetime/DateTimeEditor.jaxx | 2 +- .../widgets/datetime/DateTimeEditorHandler.java | 2 +- .../nuiton/jaxx/widgets/datetime/TimeEditor.jaxx | 2 +- .../jaxx/widgets/datetime/TimeEditorHandler.java | 2 +- .../datetime/session/DateTimeEditorState.java | 2 +- .../widgets/datetime/session/TimeEditorState.java | 2 +- .../AbsoluteDdCoordinateEditorHandler.java | 2 +- .../AbsoluteDmdCoordinateEditorHandler.java | 2 +- .../AbsoluteDmsCoordinateEditorHandler.java | 2 +- .../widgets/gis/absolute/CoordinatesEditor.jaxx | 2 +- .../gis/absolute/CoordinatesEditorHandler.java | 4 +- .../signed/SignedDdCoordinateEditorHandler.java | 2 +- .../signed/SignedDmdCoordinateEditorHandler.java | 2 +- .../signed/SignedDmsCoordinateEditorHandler.java | 2 +- .../absolute/AbsoluteDdCoordinateEditorTest.java | 2 +- .../absolute/AbsoluteDmsCoordinateEditorTest.java | 2 +- .../jaxx/widgets/number/NumberEditorHandler.java | 2 +- .../jaxx/widgets/select/FilterableDoubleList.jaxx | 2 +- .../select/FilterableDoubleListHandler.java | 12 +- .../widgets/select/FilterableDoubleListModel.java | 4 +- .../select/session/FilterableDoubleListState.java | 2 +- .../java/jaxx/runtime/swing/AboutPanelHandler.java | 189 - .../java/jaxx/runtime/swing/BaseActionPanel.java | 75 - .../main/java/jaxx/runtime/swing/CompoundIcon.java | 302 - .../jaxx/runtime/swing/ErrorDialogUIHandler.java | 95 - .../java/jaxx/runtime/swing/FontSizorHandler.java | 81 - .../jaxx/runtime/swing/HidorButtonHandler.java | 92 - .../jaxx/runtime/swing/JAXXRuntimeException.java | 48 - .../java/jaxx/runtime/swing/JAXXWidgetUtil.java | 61 - .../java/jaxx/runtime/swing/JSearchTextField.java | 76 - .../main/java/jaxx/runtime/swing/ListSelector.jaxx | 77 - .../java/jaxx/runtime/swing/ListSelectorModel.java | 185 - .../runtime/swing/MemoryStatusWidgetHandler.java | 98 - .../runtime/swing/StatusMessagePanelHandler.java | 124 - .../java/jaxx/runtime/swing/editor/FileEditor.jaxx | 111 - .../runtime/swing/editor/FileEditorHandler.java | 187 - .../java/jaxx/runtime/swing/editor/I18nEditor.jaxx | 144 - .../runtime/swing/editor/I18nEditorHandler.java | 246 - .../jaxx/runtime/swing/editor/KeyStrokeEditor.java | 80 - .../runtime/swing/editor/NumberEditorHandler.java | 623 -- .../swing/editor/SimpleTimeEditorHandler.java | 292 - .../swing/editor/SimpleTimeEditorModel.java | 109 - .../runtime/swing/editor/TimeEditorHandler.java | 329 - .../runtime/swing/editor/bean/BeanComboBox.jaxx | 156 - .../swing/editor/bean/BeanComboBoxHandler.java | 556 - .../runtime/swing/editor/bean/BeanDoubleList.jaxx | 164 - .../swing/editor/bean/BeanDoubleListHandler.java | 565 -- .../swing/editor/bean/BeanDoubleListModel.java | 350 - .../swing/editor/bean/BeanFilterableComboBox.jaxx | 160 - .../editor/bean/BeanFilterableComboBoxHandler.java | 736 -- .../runtime/swing/editor/bean/BeanListHeader.jaxx | 117 - .../swing/editor/bean/BeanListHeaderHandler.java | 291 - .../jaxx/runtime/swing/editor/bean/BeanUIUtil.java | 430 - .../runtime/swing/editor/cell/DateCellEditor.java | 53 - .../runtime/swing/editor/cell/FileCellEditor.java | 71 - .../swing/editor/cell/KeyStrokeCellEditor.java | 62 - .../swing/editor/cell/NumberCellEditor.java | 131 - .../runtime/swing/editor/gis/DmdCoordinate.java | 336 - .../swing/editor/gis/DmdCoordinateConverter.java | 143 - .../editor/gis/DmdCoordinateEditorHandler.java | 306 - .../swing/editor/gis/DmdCoordinateEditorModel.java | 122 - .../runtime/swing/editor/gis/DmsCoordinate.java | 364 - .../swing/editor/gis/DmsCoordinateConverter.java | 144 - .../editor/gis/DmsCoordinateEditorHandler.java | 317 - .../swing/editor/gis/DmsCoordinateEditorModel.java | 122 - .../editor/gis/MaskFormatterFromConverter.java | 75 - .../runtime/swing/list/ActionCheckListModel.java | 194 - .../java/jaxx/runtime/swing/list/CheckList.java | 144 - .../jaxx/runtime/swing/list/CheckListAction.java | 58 - .../jaxx/runtime/swing/list/CheckListEditor.java | 86 - .../jaxx/runtime/swing/list/CheckListModel.java | 75 - .../jaxx/runtime/swing/list/CheckListRenderer.java | 229 - .../runtime/swing/list/DefaultCheckListModel.java | 145 - .../swing/list/filter/CheckListFilterType.java | 54 - .../filter/DefaultFilterableCheckListModel.java | 84 - .../filter/FilterableActionCheckListModel.java | 49 - .../swing/list/filter/FilterableCheckList.java | 55 - .../list/filter/FilterableCheckListModel.java | 40 - .../jaxx/runtime/swing/log/JAXXLog4jAppender.java | 139 - .../jaxx/runtime/swing/log/JAXXLog4jHandler.java | 124 - .../runtime/swing/renderer/DateCellRenderer.java | 60 - .../runtime/swing/session/BeanDoubleListState.java | 90 - .../swing/session/BeanFilterableComboBoxState.java | 89 - .../swing/table/filter/AbstractTableFilter.java | 173 - .../swing/table/filter/FilterChangeListener.java | 38 - .../table/filter/FilterTableHeaderRenderer.java | 118 - .../runtime/swing/table/filter/JTableFilter.java | 134 - .../table/filter/TableAwareCheckListRenderer.java | 67 - .../runtime/swing/table/filter/TableFilter.java | 105 - .../swing/table/filter/TableFilterColumnPopup.java | 586 -- .../swing/table/filter/TableFilterState.java | 130 - .../swing/table/filter/TableRowFilterSupport.java | 170 - .../nuiton}/jaxx/runtime/swing/AboutPanel.jaxx | 0 .../jaxx/runtime/swing/AboutPanelHandler.java | 189 + .../nuiton/jaxx/runtime/swing/BaseActionPanel.java | 75 + .../nuiton}/jaxx/runtime/swing/ClockWidget.jaxx | 0 .../jaxx/runtime/swing/ComboToListSelector.jaxx | 0 .../nuiton/jaxx/runtime/swing/CompoundIcon.java | 302 + .../nuiton}/jaxx/runtime/swing/ErrorDialogUI.jaxx | 0 .../jaxx/runtime/swing/ErrorDialogUIHandler.java | 95 + .../nuiton}/jaxx/runtime/swing/FontSizor.jaxx | 0 .../jaxx/runtime/swing/FontSizorHandler.java | 81 + .../nuiton}/jaxx/runtime/swing/HidorButton.jaxx | 0 .../jaxx/runtime/swing/HidorButtonHandler.java | 92 + .../nuiton}/jaxx/runtime/swing/JAXXDatePicker.jaxx | 0 .../jaxx/runtime/swing/JAXXRuntimeException.java | 48 + .../nuiton/jaxx/runtime/swing/JAXXWidgetUtil.java | 61 + .../jaxx/runtime/swing/JSearchTextField.java | 74 + .../nuiton/jaxx/runtime/swing/ListSelector.jaxx | 77 + .../jaxx/runtime/swing/ListSelectorModel.java | 185 + .../jaxx/runtime/swing/ListToListSelector.jaxx | 0 .../jaxx/runtime/swing/MemoryStatusWidget.jaxx | 0 .../runtime/swing/MemoryStatusWidgetHandler.java | 98 + .../jaxx/runtime/swing/StatusMessagePanel.jaxx | 0 .../runtime/swing/StatusMessagePanelHandler.java | 124 + .../jaxx/runtime/swing/editor/FileEditor.jaxx | 111 + .../runtime/swing/editor/FileEditorHandler.java | 188 + .../jaxx/runtime/swing/editor/I18nEditor.jaxx | 144 + .../runtime/swing/editor/I18nEditorHandler.java | 246 + .../jaxx/runtime/swing/editor/KeyStrokeEditor.java | 80 + .../jaxx/runtime/swing/editor/NumberEditor.jaxx | 0 .../runtime/swing/editor/NumberEditorHandler.java | 623 ++ .../runtime/swing/editor/NumberEditorPopup.jcss | 0 .../runtime/swing/editor/SimpleTimeEditor.jaxx | 0 .../runtime/swing/editor/SimpleTimeEditor.jcss | 0 .../swing/editor/SimpleTimeEditorHandler.java | 292 + .../swing/editor/SimpleTimeEditorModel.java | 109 + .../jaxx/runtime/swing/editor/TimeEditor.jaxx | 0 .../jaxx/runtime/swing/editor/TimeEditor.jcss | 0 .../runtime/swing/editor/TimeEditorHandler.java | 329 + .../runtime/swing/editor/bean/BeanComboBox.jaxx | 156 + .../runtime/swing/editor/bean/BeanComboBox.jcss | 0 .../swing/editor/bean/BeanComboBoxHandler.java | 556 + .../runtime/swing/editor/bean/BeanDoubleList.jaxx | 164 + .../runtime/swing/editor/bean/BeanDoubleList.jcss | 0 .../swing/editor/bean/BeanDoubleListHandler.java | 565 ++ .../swing/editor/bean/BeanDoubleListModel.java | 350 + .../swing/editor/bean/BeanFilterableComboBox.jaxx | 160 + .../swing/editor/bean/BeanFilterableComboBox.jcss | 0 .../editor/bean/BeanFilterableComboBoxHandler.java | 736 ++ .../runtime/swing/editor/bean/BeanListHeader.jaxx | 117 + .../runtime/swing/editor/bean/BeanListHeader.jcss | 0 .../swing/editor/bean/BeanListHeaderHandler.java | 291 + .../jaxx/runtime/swing/editor/bean/BeanUIUtil.java | 428 + .../jaxx/runtime/swing/editor/bean/package.html | 0 .../runtime/swing/editor/cell/DateCellEditor.java | 53 + .../runtime/swing/editor/cell/FileCellEditor.java | 71 + .../swing/editor/cell/KeyStrokeCellEditor.java | 62 + .../swing/editor/cell/NumberCellEditor.java | 131 + .../runtime/swing/editor/gis/DmdCoordinate.java | 336 + .../swing/editor/gis/DmdCoordinateConverter.java | 143 + .../swing/editor/gis/DmdCoordinateEditor.jaxx | 0 .../swing/editor/gis/DmdCoordinateEditor.jcss | 0 .../editor/gis/DmdCoordinateEditorHandler.java | 306 + .../swing/editor/gis/DmdCoordinateEditorModel.java | 122 + .../runtime/swing/editor/gis/DmsCoordinate.java | 364 + .../swing/editor/gis/DmsCoordinateConverter.java | 144 + .../swing/editor/gis/DmsCoordinateEditor.jaxx | 0 .../swing/editor/gis/DmsCoordinateEditor.jcss | 0 .../editor/gis/DmsCoordinateEditorHandler.java | 317 + .../swing/editor/gis/DmsCoordinateEditorModel.java | 122 + .../editor/gis/MaskFormatterFromConverter.java | 75 + .../nuiton}/jaxx/runtime/swing/editor/package.html | 0 .../runtime/swing/list/ActionCheckListModel.java | 192 + .../nuiton/jaxx/runtime/swing/list/CheckList.java | 144 + .../jaxx/runtime/swing/list/CheckListAction.java | 58 + .../jaxx/runtime/swing/list/CheckListEditor.java | 86 + .../jaxx/runtime/swing/list/CheckListModel.java | 75 + .../jaxx/runtime/swing/list/CheckListRenderer.java | 229 + .../runtime/swing/list/DefaultCheckListModel.java | 142 + .../swing/list/filter/CheckListFilterType.java | 54 + .../filter/DefaultFilterableCheckListModel.java | 84 + .../filter/FilterableActionCheckListModel.java | 49 + .../swing/list/filter/FilterableCheckList.java | 55 + .../list/filter/FilterableCheckListModel.java | 40 + .../jaxx/runtime/swing/log/JAXXLog4jAppender.java | 139 + .../jaxx/runtime/swing/log/JAXXLog4jHandler.java | 124 + .../jaxx/runtime/swing/log/JAXXLog4jUI.jaxx | 0 .../nuiton}/jaxx/runtime/swing/package.html | 0 .../runtime/swing/renderer/DateCellRenderer.java | 60 + .../runtime/swing/session/BeanDoubleListState.java | 89 + .../swing/session/BeanFilterableComboBoxState.java | 89 + .../swing/table/filter/AbstractTableFilter.java | 173 + .../swing/table/filter/FilterChangeListener.java | 38 + .../table/filter/FilterTableHeaderRenderer.java | 118 + .../runtime/swing/table/filter/JTableFilter.java | 134 + .../table/filter/TableAwareCheckListRenderer.java | 66 + .../runtime/swing/table/filter/TableFilter.java | 105 + .../swing/table/filter/TableFilterColumnPopup.java | 581 ++ .../swing/table/filter/TableFilterState.java | 130 + .../swing/table/filter/TableRowFilterSupport.java | 170 + .../services/org.nuiton.converter.NuitonConverter | 4 +- .../editor/gis/DmdCoordinateConverterTest.java | 102 - .../swing/editor/gis/DmdCoordinateEditorTest.java | 212 - .../swing/editor/gis/DmdCoordinateTest.java | 136 - .../editor/gis/DmsCoordinateConverterTest.java | 105 - .../swing/editor/gis/DmsCoordinateEditorTest.java | 214 - .../swing/editor/gis/DmsCoordinateTest.java | 131 - .../editor/gis/DmdCoordinateConverterTest.java | 102 + .../swing/editor/gis/DmdCoordinateEditorTest.java | 212 + .../swing/editor/gis/DmdCoordinateTest.java | 136 + .../editor/gis/DmsCoordinateConverterTest.java | 105 + .../swing/editor/gis/DmsCoordinateEditorTest.java | 214 + .../swing/editor/gis/DmsCoordinateTest.java | 131 + jaxx-widgets/src/test/resources/log4j.properties | 3 +- src/site/rst/BeanValidator.rst | 8 +- src/site/rst/JAXXContext.rst | 4 +- src/site/rst/NavigationModel.rst | 4 +- src/site/rst/index.rst | 6 +- src/site/rst/old-compiler-doc/BeanValidator.rst | 6 +- src/site/rst/old-compiler-doc/JAXXContext.rst | 4 +- .../rst/old-compiler-doc/NavigationTreeModel.rst | 2 +- 1258 files changed, 107362 insertions(+), 107392 deletions(-) diff --git a/jaxx-application-swing/pom.xml b/jaxx-application-swing/pom.xml index 36c9750..7692e7c 100644 --- a/jaxx-application-swing/pom.xml +++ b/jaxx-application-swing/pom.xml @@ -40,7 +40,7 @@ <jaxx.addProjectClassPath>true</jaxx.addProjectClassPath> <jaxx.addSourcesToClassPath>true</jaxx.addSourcesToClassPath> <jaxx.defaultErrorUIFQN> - jaxx.runtime.validator.swing.ui.ImageValidationUI + org.nuiton.jaxx.validator.swing.ui.ImageValidationUI </jaxx.defaultErrorUIFQN> <!--<jaxx.useUIManagerForIcon>true</jaxx.useUIManagerForIcon>--> <jaxx.generateHelp>true</jaxx.generateHelp> diff --git a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/AbstractApplicationUIHandler.java b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/AbstractApplicationUIHandler.java index ab67428..f39860d 100644 --- a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/AbstractApplicationUIHandler.java +++ b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/AbstractApplicationUIHandler.java @@ -25,23 +25,23 @@ package org.nuiton.jaxx.application.swing; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Sets; -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.spi.UIHandler; -import jaxx.runtime.swing.JAXXWidgetUtil; -import jaxx.runtime.swing.editor.FileEditor; -import jaxx.runtime.swing.editor.NumberEditor; -import jaxx.runtime.swing.editor.SimpleTimeEditor; -import jaxx.runtime.swing.editor.bean.BeanComboBox; -import jaxx.runtime.swing.editor.bean.BeanDoubleList; -import jaxx.runtime.swing.editor.bean.BeanFilterableComboBox; -import jaxx.runtime.swing.editor.bean.BeanUIUtil; -import jaxx.runtime.swing.editor.cell.NumberCellEditor; -import jaxx.runtime.swing.editor.gis.DmdCoordinateEditor; -import jaxx.runtime.swing.editor.gis.DmsCoordinateEditor; -import jaxx.runtime.swing.renderer.DecoratorListCellRenderer; -import jaxx.runtime.swing.renderer.DecoratorTableCellRenderer; -import jaxx.runtime.validator.swing.SwingValidator; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.swing.JAXXWidgetUtil; +import org.nuiton.jaxx.runtime.swing.editor.FileEditor; +import org.nuiton.jaxx.runtime.swing.editor.NumberEditor; +import org.nuiton.jaxx.runtime.swing.editor.SimpleTimeEditor; +import org.nuiton.jaxx.runtime.swing.editor.bean.BeanComboBox; +import org.nuiton.jaxx.runtime.swing.editor.bean.BeanDoubleList; +import org.nuiton.jaxx.runtime.swing.editor.bean.BeanFilterableComboBox; +import org.nuiton.jaxx.runtime.swing.editor.bean.BeanUIUtil; +import org.nuiton.jaxx.runtime.swing.editor.cell.NumberCellEditor; +import org.nuiton.jaxx.runtime.swing.editor.gis.DmdCoordinateEditor; +import org.nuiton.jaxx.runtime.swing.editor.gis.DmsCoordinateEditor; +import org.nuiton.jaxx.runtime.swing.renderer.DecoratorListCellRenderer; +import org.nuiton.jaxx.runtime.swing.renderer.DecoratorTableCellRenderer; +import org.nuiton.jaxx.validator.swing.SwingValidator; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; diff --git a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/ApplicationUI.java b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/ApplicationUI.java index 545e132..2d08b9b 100644 --- a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/ApplicationUI.java +++ b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/ApplicationUI.java @@ -22,7 +22,7 @@ package org.nuiton.jaxx.application.swing; * #L% */ -import jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.JAXXObject; /** * Contract to place on each ui. diff --git a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/action/ApplicationActionUI.jaxx b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/action/ApplicationActionUI.jaxx index c3548cd..cf7eee1 100644 --- a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/action/ApplicationActionUI.jaxx +++ b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/action/ApplicationActionUI.jaxx @@ -28,7 +28,7 @@ org.nuiton.jaxx.application.swing.ApplicationUIContext org.nuiton.jaxx.application.swing.util.ApplicationUIUtil - jaxx.runtime.swing.BlockingLayerUI + org.nuiton.jaxx.runtime.swing.BlockingLayerUI javax.swing.border.EmptyBorder </import> diff --git a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/action/ApplicationActionUIHandler.java b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/action/ApplicationActionUIHandler.java index e2ed60a..48e4829 100644 --- a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/action/ApplicationActionUIHandler.java +++ b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/action/ApplicationActionUIHandler.java @@ -22,8 +22,8 @@ package org.nuiton.jaxx.application.swing.action; * #L% */ -import jaxx.runtime.SwingUtil; -import jaxx.runtime.validator.swing.SwingValidator; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.validator.swing.SwingValidator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.decorator.Decorator; diff --git a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/tab/CustomTab.java b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/tab/CustomTab.java index 81a0168..b1535d8 100644 --- a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/tab/CustomTab.java +++ b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/tab/CustomTab.java @@ -22,7 +22,7 @@ package org.nuiton.jaxx.application.swing.tab; * #L% */ -import jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.SwingUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.util.beans.BeanUtil; diff --git a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/table/AbstractApplicationTableModel.java b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/table/AbstractApplicationTableModel.java index d31398f..f6d4540 100644 --- a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/table/AbstractApplicationTableModel.java +++ b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/table/AbstractApplicationTableModel.java @@ -27,7 +27,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Sets; -import jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.SwingUtil; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.logging.Log; diff --git a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/table/ApplicationTableModelValidatorDataLocator.java b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/table/ApplicationTableModelValidatorDataLocator.java index aea16ce..cbea7fc 100644 --- a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/table/ApplicationTableModelValidatorDataLocator.java +++ b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/table/ApplicationTableModelValidatorDataLocator.java @@ -22,7 +22,7 @@ package org.nuiton.jaxx.application.swing.table; * #L% */ -import jaxx.runtime.validator.swing.SwingListValidatorDataLocator; +import org.nuiton.jaxx.validator.swing.SwingListValidatorDataLocator; import org.apache.commons.lang3.tuple.Pair; import javax.swing.table.TableModel; diff --git a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/util/ApplicationExceptionHandler.java b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/util/ApplicationExceptionHandler.java index b822a27..45dfdf4 100644 --- a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/util/ApplicationExceptionHandler.java +++ b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/util/ApplicationExceptionHandler.java @@ -22,7 +22,7 @@ package org.nuiton.jaxx.application.swing.util; * #L% */ -import jaxx.runtime.swing.JAXXRuntimeException; +import org.nuiton.jaxx.runtime.swing.JAXXRuntimeException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.jaxx.application.ApplicationTechnicalException; diff --git a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/util/ApplicationUIUtil.java b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/util/ApplicationUIUtil.java index d7793d9..147d320 100644 --- a/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/util/ApplicationUIUtil.java +++ b/jaxx-application-swing/src/main/java/org/nuiton/jaxx/application/swing/util/ApplicationUIUtil.java @@ -22,8 +22,8 @@ package org.nuiton.jaxx.application.swing.util; * #L% */ -import jaxx.runtime.JAXXObject; -import jaxx.runtime.swing.JTables; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.swing.JTables; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jdesktop.swingx.JXTable; diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/ClassMap.java b/jaxx-compiler/src/main/java/jaxx/compiler/ClassMap.java deleted file mode 100644 index ef67dba..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/ClassMap.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler; - -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; - -/** - * A Map implementation which uses Classes as keys. <code>ClassMap</code> differs from typical maps - * in that it takes subclasses into account; mapping a class to a value also maps all subclasses of - * that class to the value. - * - * A <code>get</code> operation will return the value associated with the class itself, or failing - * that, with its nearest ancestor for which there exists a mapping. - * - * @param <T> type of the class - */ -public class ClassMap<T> extends HashMap<ClassDescriptor, T> { - - private static final long serialVersionUID = 5149779660675529037L; - - /** - * Logger - */ - protected static final Log log = LogFactory.getLog(ClassMap.class); - - /** - * Keeps track of automatically-added Classes so we can distinguish them from user-added - * Classes. Unknown Classes are automatically added to the map during <code>get</code> - * calls to speed up subsequent requests, but they must be updated when the mappings - * for their superclasses are modified. - */ - private List<ClassDescriptor> autoKeys = new ArrayList<>(); - - /** - * Returns the value associated with the key <code>Class</code>. If the class itself does not have - * a mapping, its superclass will be checked, and so on until an ancestor class with a mapping is - * located. If none of the class' ancestors have a mapping, <code>null</code> is returned. - * - * @param key the class to check - * @return the mapping for the class - */ - @Override - public T get(Object key) { - T result = null; - ClassDescriptor c = (ClassDescriptor) key; - while (c != null) { - result = super.get(c); - if (result != null) { - break; - } - c = c.getSuperclass(); - } - - if (result == null && ((ClassDescriptor) key).isInterface()) { - result = get(ClassDescriptorHelper.getClassDescriptor(Object.class)); - } - - if (c != key && result != null) { // no mapping for the class itself, but found one for a superclass - put((ClassDescriptor) key, result); - autoKeys.add((ClassDescriptor) key); - } - return result; - } - - /** - * Associates a value with a class and all of its descendents. - * - * @param key the class to map - * @param value the value to map to the class - * @return the old value associated with the class - */ - @Override - public T put(ClassDescriptor key, T value) { - //if (!(key instanceof ClassDescriptor)) { - // throw new IllegalArgumentException("expected ClassDescriptor, got " + key); - //} - if (autoKeys.size() > 0) { // remove all automatic keys which descend from the class being modified - Iterator<ClassDescriptor> i = autoKeys.iterator(); - while (i.hasNext()) { - ClassDescriptor auto = i.next(); - if (key.isAssignableFrom(auto)) { - i.remove(); - remove(auto); - } - } - } - return super.put(key, value); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObject.java b/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObject.java deleted file mode 100644 index a60782b..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObject.java +++ /dev/null @@ -1,791 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler; - -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.reflect.MethodDescriptor; -import jaxx.compiler.tags.DefaultComponentHandler; -import jaxx.compiler.tags.TagHandler; -import jaxx.compiler.tags.TagManager; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.JAXXUtil; -import org.apache.commons.lang3.StringUtils; - -import java.awt.Container; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Represents an object in the <code>.java</code> file being generated during compilation. There is - * a <code>CompiledObject</code> for each class tag encountered, and certain tags may generate - * additional objects for various reasons. - */ -public class CompiledObject { - - /** The object's id. */ - private String id; - - /** Java code referring to the object. */ - private String javaCode; - - /** The object's class. */ - private ClassDescriptor objectClass; - - /** The style class. */ - private String styleClass; - - /** The container containing this CompiledObject. */ - private CompiledObject parent; - - /** - * true if this object overrides an object of the same id in a superclass - * of the object being compiled - */ - private boolean override; - - /** - * The type of the object without fqn if possible. - * - * This is used when casting on an overridden object and only available if - * {@link #override} is set to {@code true}. - */ - private String simpleType; - - /** - * Comma-separated Java code snippets representing the parameters that - * should be passed to the object's constructor. - */ - private String constructorParams; - - /** - * Java code snippet which performs basic initialization of the object (after it has already been constructed). - * Because CompiledObject initialization order cannot be guaranteed, it is not safe to refer to other - * CompiledObjects from initializationCode -- you must refer to them from additionCode instead. - */ - private StringBuilder initializationCode = new StringBuilder(); - - /** - * Java code snippet which completes setup by adding any child objects, or otherwise manipulates any refererenced - * objects. Because CompiledObject initialization order cannot be guaranteed, it is not safe to refer to other - * CompiledObjects from initializationCode -- you must refer to them from additionCode instead. - */ - private StringBuilder additionCode = new StringBuilder(); - - /** List of all registered event handlers. */ - private List<EventHandler> eventHandlers = new ArrayList<>(); - - /** All properties that have been applied to this CompiledObject. */ - private Map<String, String> properties = new HashMap<>(); - - /** generic types of the compiled object */ - private String[] genericTypes; - - /** - * a flag to indicate if javaBean full support must be support for this - * object by root object - */ - private boolean javaBean; - - /** code to initialize the bean (can be null) */ - private String javaBeanInitCode; - - /** the type of the override object (can be null if no overide) */ - private ClassDescriptor overrideType; - - /** the decorator */ - private CompiledObjectDecorator decorator; - - /** client properties */ - private Map<String, String> clientProperties; - - /** initializer of the object */ - private String initializer; - - public String getSimpleType() { - return simpleType; - } - - public class ChildRef { - - CompiledObject child; - - String constraints; - - String childJavaCode; - - private String delegateCode; - - public ChildRef(CompiledObject child, - String constraints, - String childJavaCode, - String delegateCode) { - this.child = child; - this.constraints = constraints; - this.childJavaCode = childJavaCode; - this.delegateCode = delegateCode; - } - - - public String getConstraints() { - return constraints; - } - - public String getDelegateCode() { - return delegateCode; - } - - public CompiledObject getChild() { - return child; - } - - public String getChildJavaCode() { - return childJavaCode; - } - - public void setChildJavaCode(String childJavaCode) { - this.childJavaCode = childJavaCode; - } - - public void addToAdditionCode(StringBuilder buffer, - boolean isRootObject) { - //TC-20091026 do not prefix if on root object - String prefix; - if (isRootObject) { - prefix = ""; - } else { - prefix = javaCode + delegateCode + "."; - } - if (constraints != null) { - buffer.append(prefix); - buffer.append("add("); - buffer.append(childJavaCode); - buffer.append(", "); - buffer.append(constraints); - buffer.append(");"); - } else { - buffer.append(prefix); - buffer.append("add("); - buffer.append(childJavaCode); - buffer.append(");"); - } - buffer.append(JAXXCompiler.getLineSeparator()); - } - } - - private List<ChildRef> childs; - - /** - * Creates a new <code>CompiledObject</code>. - * - * To be useful, the object should be registered with a - * <code>JAXXCompiler</code> using - * {@link JAXXCompiler#registerCompiledObject(CompiledObject)} . - * - * @param id the object's id - * @param objectClass the object's class - * @param compiler the current <code>JAXXCompiler</code> - * @throws NullPointerException if id or class is null - */ - public CompiledObject(String id, - ClassDescriptor objectClass, - JAXXCompiler compiler) { - this(id, objectClass, compiler, false); - } - - /** - * Creates a new <code>CompiledObject</code>. To be useful, the object should be registered with a - * <code>JAXXCompiler</code> using {@link JAXXCompiler#registerCompiledObject(CompiledObject)} . - * - * @param id the object's id - * @param objectClass the object's class - * @param compiler the current <code>JAXXCompiler</code> - * @param force <code>true</code> to force acceptance of invalid ids - * @throws NullPointerException if id or class is null - */ - public CompiledObject(String id, - ClassDescriptor objectClass, - JAXXCompiler compiler, - boolean force) { - this(id, id, objectClass, compiler, force); - } - - /** - * Creates a new <code>CompiledObject</code>. To be useful, the object should be registered with a - * <code>JAXXCompiler</code> using {@link JAXXCompiler#registerCompiledObject(CompiledObject)} . - * - * @param id the object's id - * @param javaCode Java code referring to the object - * @param objectClass the object's class - * @param force <code>true</code> to force acceptance of invalid ids - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if the id is not a valid Java identifier - * @throws NullPointerException if id or class is null - */ - public CompiledObject(String id, - String javaCode, - ClassDescriptor objectClass, - JAXXCompiler compiler, - boolean force) throws CompilerException { - if (!force) { - if (!isValidID(id)) { - compiler.reportError( - "the id '" + id + "' is not a valid Java identifier"); - } - } - this.id = id; - this.javaCode = javaCode; - - if (objectClass == null) { - throw new NullPointerException(); - } - this.objectClass = objectClass; - childs = new ArrayList<>(); - } - - public static boolean isValidID(String id) { - boolean valid = true; - if (id.length() == 0) { - valid = false; - } - if (valid) { - if (!Character.isJavaIdentifierStart(id.charAt(0))) { - valid = false; - } - if (valid) { - for (int i = 1; i < id.length(); i++) { - if (!Character.isJavaIdentifierPart(id.charAt(i))) { - valid = false; - break; - } - } - } - } - return valid; - } - - /** - * True if this object overrides an object in the superclass of the class - * being compiled. For this to be true, the class currently being compiled - * must be a subclass of another <code>JAXXObject</code> which has an - * identically-named object. - * - * @return <code>true</code> if this object is an override - * @see #setOverride(boolean) - */ - public boolean isOverride() { - return override; - } - - /** - * {@code true} when overrides an object in the superclass of the class - * being compiled AND type is also override. - * - * @return {@code true} if this object is an override AND override type - */ - public boolean isOverrideType() { - return isOverride() && !getObjectClass().equals(getOverrideType()); - } - - /** - * Sets whether this class overrides an identically-named object in the - * parent class. - * - * @param override <code>true</code> if this object is an override - * @see #isOverride - */ - public void setOverride(boolean override) { - this.override = override; - } - - /** - * Sets the simple type of the object. - * - * Used when castin an overridden object. - * - * @param simpleType the simple type to use (or the fqn if there is a - * conflict with already imported types of the compiler). - * @since 2.4 - */ - public void setSimpleType(String simpleType) { - this.simpleType = simpleType; - } - - /** - * Returns this object's CSS style class. - * - * @return the value of the <code>styleClass</code> attribute - */ - public String getStyleClass() { - return styleClass; - } - - /** - * Sets this object's CSS style class. - * - * @param styleClass the new style class - */ - public void setStyleClass(String styleClass) { - this.styleClass = styleClass; - } - - /** - * Returns this object's parent container. Non-visual components (and - * the root container) return <code>null</code>. - * - * @return the object's parent container - */ - public CompiledObject getParent() { - return parent; - } - - /** - * Sets this object's parent container. - * - * @param parent the parent container - * @throws IllegalArgumentException if parent is not a {@link Container} - */ - public void setParent(CompiledObject parent) throws IllegalArgumentException { - if (!ClassDescriptorHelper.getClassDescriptor(Container.class).isAssignableFrom(parent.getObjectClass())) { - throw new IllegalArgumentException("parent must descend from java.awt.Container"); - } - this.parent = parent; - } - - /** - * Returns the name of the method that should be generated in the compiled - * <code>.java</code> file - * in order to create this object. This is just a suggestion and may be - * ignored. - * - * @return the suggested name of the method which initializes this object - */ - public String getCreationMethodName() { - return "create" + StringUtils.capitalize(getId()); - } - - /** - * Returns the name of the method that should be generated in the compiled - * <code>.java</code> file in order to add children to this object. This - * is just a suggestion and may be ignored. - * - * @return the suggested name of the method which completes this object's setup - */ - public String getAdditionMethodName() { - return "addChildrenTo" + StringUtils.capitalize(getId()); - } - - /** - * Returns the type of this object. - * - * @return the class this <code>CompiledObject</code> represents - */ - public ClassDescriptor getObjectClass() { - return objectClass; - } - - /** - * Returns this object's id. Generally, a field with this name will be - * created in the compiled <code>.java</code> - * file in order to represent this object. - * - * @return the id used to refer to this object - */ - public String getId() { - return id; - } - - /** - * Returns Java code used to refer to this object in the compiled Java file. - * This is usually the same as its id. - * - * @return the Java code for this object - */ - public String getJavaCode() { - String result = javaCode; - if (isOverride()) { - // handle cases where object is overridden to be a different class - if (simpleType == null) { - - // means overridden but stil on the same type - result = javaCode; - } else { - result = "((" + simpleType + ") " + javaCode + ")"; -// result = "((" + JAXXCompiler.getCanonicalName(this) + ") " + javaCode + ")"; - } - } - return result; - } - - public String getJavaCodeForProperty(String property) { - if (!isOverride() || simpleType == null) { - return javaCode; - } - String result = "((" + simpleType + ") " + javaCode + ")"; -// String result = "((" + JAXXCompiler.getCanonicalName(this) + ") " + javaCode + ")"; -// String result = "((" + JAXXCompiler.getCanonicalName(getObjectClass()) + ") " + javaCode + ")"; - - String methodName = StringUtils.capitalize(property); - try { - MethodDescriptor methodDescriptor = overrideType.getMethodDescriptor("get" + methodName); - if (methodDescriptor != null) { - if (overrideType.getMethodDescriptor("set" + methodName, methodDescriptor.getReturnType()) != null) { - // handle cases where object is overridden to be a different class - result = javaCode; - } - } - } catch (NoSuchMethodException e) { - // lazy error, do nothing - } - return result; - } - - /** - * Returns a list of comma-separated Java code snippets that represent the - * parameters to pass to this object's constructor. - * - * @return the raw constructor params - * @see #setConstructorParams(String) - */ - public String getConstructorParams() { - return constructorParams; - } - - /** - * Sets the parameters to pass to this object's constructor. - * - * @param constructorParams comma-separated Java code snippets representing - * constructor params - * @see #getConstructorParams - */ - public void setConstructorParams(String constructorParams) { - this.constructorParams = constructorParams; - } - - public String getInitializer() { - return initializer; - } - - public void setInitializer(String initializer) { - this.initializer = initializer; - } - - /** - * Returns the code that performs basic initialization of this object, - * after it has already been constructed. - * This basic code should not reference any other - * <code>CompiledObjects</code> as they may not have been created yet. - * - * @param compiler compiler to use - * @return the code which initializes this object - */ - public String getInitializationCode(JAXXCompiler compiler) { - StringBuilder result = new StringBuilder(initializationCode.toString()); - for (Object eventHandler : eventHandlers) { - EventHandler handler = (EventHandler) eventHandler; - result.append(getInitializationCode(handler, compiler)); - } - return result.toString(); - } - - protected String getInitializationCode(EventHandler handler, JAXXCompiler compiler) { - MethodDescriptor addMethod = handler.getAddMethod(); - ClassDescriptor listenerClass = addMethod.getParameterTypes()[0]; - String type = compiler.getImportedType(listenerClass.getName()); - String prefix = compiler.getImportedType(JAXXUtil.class); - - //TC-20091026 use 'this' instead of root object javaCode - //TC-20091105 JAXXUtil.getEventListener is generic, no more need cast and use simple name - return getJavaCode() + '.' + addMethod.getName() + "(" + prefix + ".getEventListener(" + type + ".class, " + - TypeManager.getJavaCode(handler.getListenerMethod().getName()) + ", this, " + - TypeManager.getJavaCode(compiler.getEventHandlerMethodName(handler)) + "));" + JAXXCompiler.getLineSeparator(); - } - - /** - * Returns Java code to complete final setup on this object. This code may - * reference other <code>CompiledObjects</code>, as they are guaranteed to - * have all been created by this point. - * - * @return code which adds children and performs final setup - */ - public String getAdditionCode() { - return additionCode.toString(); - } - - /** - * Appends code to the initialization code block. A line separator is - * automatically appended to the end. - * - * @param code the code to add to the initialization block - * @see #getInitializationCode(JAXXCompiler) - */ - public void appendInitializationCode(String code) { - if (!code.isEmpty()) { - initializationCode.append(code); - initializationCode.append(JAXXCompiler.getLineSeparator()); - } - } - - /** - * Appends code to the addition code block. A line separator is - * automatically appended to the end. - * - * @param code the code to add to the addition block - * @see #getAdditionCode - */ - public void appendAdditionCode(String code) { - if (!code.isEmpty()) { - additionCode.append(code); - additionCode.append(JAXXCompiler.getLineSeparator()); - } - } - - /** - * Stores a property for this object. The only effect of calling this - * method is that the property will be returned by {@code getProperties()}. - * - * @param property the name of the property - * @param value the property's value - * @see #getProperties() - */ - public void addProperty(String property, String value) { - properties.put(property, value); - } - - public boolean hasClientProperties() { - return clientProperties != null && !clientProperties.isEmpty(); - } - - public void addClientProperty(String property, String value) { - getClientProperties().put(property, value); - } - - public String getClientProperty(String key) { - if (!hasClientProperties()) { - return null; - } - return clientProperties.get(key); - } - - public Map<String, String> getClientProperties() { - if (clientProperties == null) { - clientProperties = new HashMap<>(); - } - return clientProperties; - } - - /** - * Returns all properties which have been set for this object. - * - * @return a <code>Map</code> containing all properties defined for this object - * @see #addProperty(String, String) - */ - public Map<?, ?>/*<String, String>*/ getProperties() { - return properties; - } - - /** - * Adds an event listener to this object. The generated code will appear - * in the initialization block. - * - * @param eventId unique (per CompiledObject) identifier for the event handler - * @param addMethod the method which adds the event listener - * @param listenerMethod the method (in the listener class) which is called when the event is fired - * @param code the Java code for the listenerMethod's body - * @param compiler the current <code>JAXXCompiler</code> - * @see #getInitializationCode(EventHandler, JAXXCompiler) - */ - public void addEventHandler(String eventId, - MethodDescriptor addMethod, - MethodDescriptor listenerMethod, - String code, - JAXXCompiler compiler) { - EventHandler handler = new EventHandler( - getId() + "." + eventId, - getJavaCode(), - addMethod, - addMethod.getParameterTypes()[0], - listenerMethod, - code - ); - compiler.registerEventHandler(handler); - eventHandlers.add(handler); - - if (getJavaCode().contains(".")) { - // object lives in another JAXX file and consequently its initialization code won't be output - compiler.appendInitializerCode( - getInitializationCode(handler, compiler)); - } - } - - /** - * Adds a child component to this container. The child is added without - * layout constraints. - * - * @param child the component to add - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if this object is not a container - * @see #addChild(CompiledObject, String, JAXXCompiler) - */ - public void addChild(CompiledObject child, - JAXXCompiler compiler) throws CompilerException { - addChild(child, null, compiler); - } - - /** - * Adds a child component to this container. This variant allows the Java - * code for a layout constraints object to be specified. - * - * @param child the component to add - * @param constraints Java code for the layout constraints object - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if this object is not a container - * @see #addChild(CompiledObject, JAXXCompiler) - */ - public void addChild(CompiledObject child, - String constraints, - JAXXCompiler compiler) throws CompilerException { - try { - if (constraints != null) { - constraints = compiler.checkJavaCode(constraints); - } - } catch (CompilerException e) { - compiler.reportError( - "While parsing 'constraints' attribute: " + e.getMessage()); - } - - if (!child.isOverride()) { - TagHandler tagHandler = TagManager.getTagHandler(getObjectClass()); - if (tagHandler instanceof DefaultComponentHandler && - !((DefaultComponentHandler) tagHandler).isContainer()) { - compiler.reportError("component " + this + " may not have children"); - } - - String containerDelegate = ((DefaultComponentHandler) tagHandler).getContainerDelegate(); - String delegateCode = containerDelegate != null ? - "." + containerDelegate + "()" : - ""; - - child.setParent(this); - - ChildRef ref = newChildRef(child, constraints, delegateCode); - childs.add(ref); - } - } - - protected ChildRef newChildRef(CompiledObject child, String constraints, String delegateCode) { - return new ChildRef(child, - constraints, - child.getJavaCode(), - delegateCode - ); - } - - @Override - public String toString() { - return getObjectClass().getName() + "[id='" + id + "']"; - } - - public String getGenericTypes() { - if (getGenericTypesLength() == 0) { - // not using it - return ""; - } - String result = ""; - for (int i = 0, j = getGenericTypesLength(); i < j; i++) { - result += ", " + genericTypes[i]; - } - return "< " + result.substring(2) + " >"; - } - - public void setGenericTypes(String... genericTypes) { - if (genericTypes == null) { - this.genericTypes = null; - return; - } - this.genericTypes = new String[genericTypes.length]; - for (int i = 0, j = genericTypes.length; i < j; i++) { - this.genericTypes[i] = genericTypes[i].trim(); - } - } - - public boolean isJavaBean() { - return javaBean; - } - - public void setJavaBean(boolean javaBean) { - this.javaBean = javaBean; - } - - public ClassDescriptor getOverrideType() { - return overrideType; - } - - public void setOverrideType(ClassDescriptor overrideType) { - this.overrideType = overrideType; - } - - public String getJavaBeanInitCode() { - return javaBeanInitCode; - } - - public void setJavaBeanInitCode(String javaBeanInitCode) { - this.javaBeanInitCode = javaBeanInitCode; - } - - public List<ChildRef> getChilds() { - return childs; - } - - public CompiledObjectDecorator getDecorator() { - return decorator; - } - - public void setDecorator(CompiledObjectDecorator decorator) { - this.decorator = decorator; - } - - public void finalizeCompiler(JAXXCompiler compiler) { - - List<ChildRef> refList = getChilds(); - if (refList != null && !refList.isEmpty()) { - // compute additionCode for all childs - StringBuilder buffer = new StringBuilder(); - for (ChildRef childRef : refList) { - childRef.addToAdditionCode(buffer, - equals(compiler.getRootObject())); - } - additionCode = buffer.append(additionCode); - } - } - - public int getGenericTypesLength() { - return genericTypes == null ? 0 : genericTypes.length; - } - - public String getGetterName() { - return "get" + StringUtils.capitalize(id); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObjectDecorator.java b/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObjectDecorator.java deleted file mode 100644 index b9c2bd6..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObjectDecorator.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler; - -import jaxx.compiler.java.JavaFile; - -/** - * Contract of compiled object decorator at generation time. - * - * Note : The implementation of this class must be stateless. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.2 - */ -public interface CompiledObjectDecorator { - - /** - * @return the name of the decorator (match the content of a decorator - * attribute value in a JAXX file) - */ - String getName(); - - /** - * Obtain the setup code of the given {@code object} from the - * {@code compiler} to be inject in the generated method - * {@code $completeSetup}. - * - * @param compiler the compiler to use - * @param object the compiled object to treate - * @param javaFile the file to treate - * @return the code to inject in $completeSetup method in file - */ - String createCompleteSetupMethod(JAXXCompiler compiler, - CompiledObject object, - JavaFile javaFile); - - /** - * Create the initializer code for the given compiled {@code object} and - * inject it in the {@code code}. - * - * @param compiler the compiler to use - * @param root the root compiled object of the jaxx file - * @param object the compiled object to treate - * @param code where to store code to inject - * @param lastWasMethodCall {@code true} if last instruction call was a method call - * @return {@code true} if the last instruction was a method call - */ - boolean createInitializer(JAXXCompiler compiler, - CompiledObject root, - CompiledObject object, - StringBuilder code, - boolean lastWasMethodCall); - - /** - * Finalize the given compiled object before any generation in the {@code file}. - * - * @param compiler the compiler to use - * @param root the root compiled object of the jaxx file - * @param object the compiled object to treate - * @param javaFile the file to treate - * @param packageName the package name - * @param className the (simple ?) class name - * @param fullClassName the fully class name - * @throws ClassNotFoundException if a class is not found - */ - void finalizeCompiler(JAXXCompiler compiler, - CompiledObject root, - CompiledObject object, - JavaFile javaFile, - String packageName, - String className, - String fullClassName) throws ClassNotFoundException; - - /** - * Obtain the creation code of the given {@code object} from the {@code compiler} to inject in generate method - * {@code $initialize} or {@code createXXX} in not inline. - * - * @param compiler the compiler to use - * @param object the compiled object to treate - * @return the code to inject in $initialize (or in the createXXX in not inline) method to create the given object - * @throws CompilerException if any pb - */ - String getCreationCode(JAXXCompiler compiler, - CompiledObject object) throws CompilerException; -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/CompilerConfiguration.java b/jaxx-compiler/src/main/java/jaxx/compiler/CompilerConfiguration.java deleted file mode 100644 index 1028b2f..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/CompilerConfiguration.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler; - -import jaxx.compiler.finalizers.JAXXCompilerFinalizer; -import jaxx.compiler.spi.Initializer; -import jaxx.runtime.JAXXContext; -import jaxx.runtime.spi.UIHandler; - -import java.io.File; -import java.util.Map; - -/** - * Configuration of a compiler task. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.0 - */ -public interface CompilerConfiguration { - - /** - * Default css file extension. - * - * @since 2.28 - */ - String DEFAULT_CSS_EXTENSION = "css"; - - /** @return the class loader used by compilers */ - ClassLoader getClassLoader(); - - /** @return the type of compiler to use */ - Class<? extends JAXXCompiler> getCompilerClass(); - - /** @return the type of default decorator to use if none specified */ - Class<? extends CompiledObjectDecorator> getDefaultDecoratorClass(); - - /** @return the type of the default error UI to use for validation */ - Class<?> getDefaultErrorUI(); - - /** @return extra imports to add on all generated jaxx object */ - String[] getExtraImports(); - - /** - * @return the FQN of the help broker (can not directly a type since - * the help broker should (may?) be inside the sources. - */ - String getHelpBrokerFQN(); - - /** - * @return the FQN of the validator factory used to instanciate new validators. - * @since 2.6 - */ - String getValidatorFactoryFQN(); - - - /** @return the type of context to use in each generated jaxx object */ - Class<? extends JAXXContext> getJaxxContextClass(); - - /** - * Returns whether or not optimization should be performed. - * - * @return whether or not optimizations should be performed - */ - boolean getOptimize(); - - /** - * Returns whether or not should recurse in css for existing JAXX Object. - * - * <b>Note:</b> This functionnality was here at the beginning of the project - * but offers nothing very usefull, will be remove probably in JAXX 3.0. - * - * @return {@code true} if a css file with same name as jaxx file should - * be included in jaxx file if found. - * @since 2.0.2 - */ - boolean isAutoRecurseInCss(); - - /** - * Returns the target directory. - * - * @return the target directory - */ - File getTargetDirectory(); - - /** @return {@code true} if a logger must add on each generated jaxx object */ - boolean isAddLogger(); - - /** @return {@code true} if we are generating help */ - boolean isGenerateHelp(); - - /** @return {@code true} if we use the i18n system */ - boolean isI18nable(); - - /** @return {@code true} to generate optimized code */ - boolean isOptimize(); - - /** @return {@code true} if a profile pass must be done */ - boolean isProfile(); - - /** @return {@code true} if states must be reset after the compilation */ - boolean isResetAfterCompile(); - - /** @return {@code true} if UIManager is used to retrieve icons */ - boolean isUseUIManagerForIcon(); - - /** @return {@code true} if compiler is verbose */ - boolean isVerbose(); - - /** - * @return {@code true} to trace the Class descriptor loading. - * @since 2.4 - */ - boolean isShowClassDescriptorLoading(); - - /** - * @return {@code true} to detect and add {@link UIHandler} if found in class-path. - * @since 2.6 - */ - boolean isAddAutoHandlerUI(); - - /** - * @param addAutoHandlerUI new value of the state - * @since 2.6 - */ - void setAddAutoHandlerUI(boolean addAutoHandlerUI); - - /** - * @return {@code true} to generate missing ids and style classes in the CSS files - * @since 2.29 - */ - boolean isGenerateMissingIdsAndStyleClassesInCss(); - - /** - * @param generateMissingIdsAndStyleClassesInCss new value of the state - * @since 2.29 - */ - void setGenerateMissingIdsAndStyleClassesInCss(boolean generateMissingIdsAndStyleClassesInCss); - - /** @return the encoding to use to write files */ - String getEncoding(); - - Map<String, CompiledObjectDecorator> getDecorators(); - - Map<String, JAXXCompilerFinalizer> getFinalizers(); - - Map<String, Initializer> getInitializers(); - - /** - * @return the optional common css to inject in all JaxxCompiler. - * @since 2.13 - */ - File getCommonCss(); - - /** - * @return the extension of css files (by default use {@link #DEFAULT_CSS_EXTENSION} as before). - * @since 2.28 - */ - String getCssExtension(); -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/CompilerException.java b/jaxx-compiler/src/main/java/jaxx/compiler/CompilerException.java deleted file mode 100644 index 8619361..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/CompilerException.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler; - -/** Thrown by the compiler when an error occurs. */ -public class CompilerException extends RuntimeException { - - private static final long serialVersionUID = -9099889519671482440L; - - /** Creates a new <code>ParseException</code>. */ - public CompilerException() { - } - - /** - * Creates a new <code>ParseException</code> with the specified detail message. - * - * @param msg the exception's detail message - */ - public CompilerException(String msg) { - super(msg); - } - - /** - * Creates a new <code>ParseException</code> with the specified cause. - * - * @param initCause the exception's initCause - */ - public CompilerException(Throwable initCause) { - super(initCause); - } - - /** - * Creates a new <code>ParseException</code> with the specified detail message and cause. - * - * @param msg the exception's detail message - * @param initCause the exception's initCause - */ - public CompilerException(String msg, Throwable initCause) { - super(msg, initCause); - } - -// @Override -// public void printStackTrace() { -// super.printStackTrace(); -// System.err.println("CompilerException printed from:"); -// Thread.dumpStack(); -// } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/DefaultCompilerConfiguration.java b/jaxx-compiler/src/main/java/jaxx/compiler/DefaultCompilerConfiguration.java deleted file mode 100644 index 52ca240..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/DefaultCompilerConfiguration.java +++ /dev/null @@ -1,373 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler; - -import jaxx.compiler.finalizers.JAXXCompilerFinalizer; -import jaxx.compiler.spi.Initializer; -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.spi.UIHandler; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.UIManager; -import java.io.File; -import java.util.Map; -import java.util.ServiceLoader; -import java.util.TreeMap; - -/** Options of the {@link JAXXCompiler} and {@link JAXXEngine}. */ -public class DefaultCompilerConfiguration implements CompilerConfiguration { - - /** Logger. */ - private static final Log log = - LogFactory.getLog(DefaultCompilerConfiguration.class); - - /** where to generate */ - private File targetDirectory; - - /** flag to optimize generated code */ - private boolean optimize; - - /** verbose flag */ - private boolean verbose; - - /** to do a profile pass after generation */ - private boolean profile; - - /** a flag to enable or disable i18n generation */ - private boolean i18nable; - - /** a flag to add or not logger on generated jaxx files */ - private boolean addLogger; - - /** a flag to not reset compiler after a compile */ - private boolean resetAfterCompile; - - /** - * the name of implementation of {@link JAXXContext} - * to be used on {@link JAXXObject}. - */ - protected Class<? extends JAXXContext> jaxxContextClass; - - /** list of fqn of class to import for all generated jaxx files */ - protected String[] extraImports; - - /** default error ui */ - private Class<?> defaultErrorUI; - - /** class loader to use in compiler */ - private ClassLoader classLoader = getClass().getClassLoader(); - - /** the compiler class to use */ - private Class<? extends JAXXCompiler> compilerClass; - - /** - * the default compiled object decorator to use if none specifed via - * decorator attribute - */ - private Class<? extends CompiledObjectDecorator> defaultDecoratorClass; - - /** a flag to use {@link UIManager} to retreave icons. */ - private boolean useUIManagerForIcon; - - /** a flag to generate javax help for any */ - private boolean generateHelp; - - /** - * Fully qualified name of help broker, can not use a class here - * since this class should be in sources (so not yet compiled) - */ - private String helpBrokerFQN; - - /** - * Fully qualified name of validator factory. - * - * @since 2.6 - */ - private String validatorFactoryFQN; - - /** Encoding to use to write files */ - private String encoding; - - private boolean autoRecurseInCss; - - /** decorators available in engine */ - protected Map<String, CompiledObjectDecorator> decorators; - - /** finalizers available in engine */ - protected Map<String, JAXXCompilerFinalizer> finalizers; - - /** initializes availables */ - protected Map<String, Initializer> initializers; - - /** - * To trace class descriptor loading. - * - * @since 2.4 - */ - private boolean showClassDescriptorLoading; - - /** - * To detect {@link UIHandler} if found. - * - * @since 2.6 - */ - private boolean addAutoHandlerUI; - - /** - * To generate missing ids and style classes in the CSS files - * - * @since 2.29 - */ - private boolean generateMissingIdsAndStyleClassesInCss; - - /** - * Optional common css. - * - * @since 2.13 - */ - private File commonCss; - - @Override - public File getTargetDirectory() { - return targetDirectory; - } - - @Override - public boolean getOptimize() { - return optimize; - } - - @Override - public boolean isVerbose() { - return verbose; - } - - @Override - public boolean isShowClassDescriptorLoading() { - return showClassDescriptorLoading; - } - - @Override - public boolean isAddAutoHandlerUI() { - return addAutoHandlerUI; - } - - @Override - public void setAddAutoHandlerUI(boolean addAutoHandlerUI) { - this.addAutoHandlerUI = addAutoHandlerUI; - } - - @Override - public boolean isGenerateMissingIdsAndStyleClassesInCss() { - return generateMissingIdsAndStyleClassesInCss; - } - - @Override - public void setGenerateMissingIdsAndStyleClassesInCss(boolean generateMissingIdsAndStyleClassesInCss) { - this.generateMissingIdsAndStyleClassesInCss = generateMissingIdsAndStyleClassesInCss; - } - - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - @Override - public boolean isI18nable() { - return i18nable; - } - - @Override - public boolean isUseUIManagerForIcon() { - return useUIManagerForIcon; - } - - @Override - public boolean isAddLogger() { - return addLogger; - } - - @Override - public Class<? extends JAXXContext> getJaxxContextClass() { - return jaxxContextClass; - } - - @Override - public String[] getExtraImports() { - return extraImports; - } - - @Override - public boolean isResetAfterCompile() { - return resetAfterCompile; - } - - @Override - public boolean isOptimize() { - return optimize; - } - - @Override - public Class<?> getDefaultErrorUI() { - return defaultErrorUI; - } - - @Override - public ClassLoader getClassLoader() { - return classLoader; - } - - @Override - public Class<? extends JAXXCompiler> getCompilerClass() { - return compilerClass; - } - - @Override - public Class<? extends CompiledObjectDecorator> getDefaultDecoratorClass() { - return defaultDecoratorClass; - } - - @Override - public boolean isProfile() { - return profile; - } - - @Override - public boolean isGenerateHelp() { - return generateHelp; - } - - @Override - public String getHelpBrokerFQN() { - return helpBrokerFQN; - } - - @Override - public String getValidatorFactoryFQN() { - return validatorFactoryFQN; - } - - @Override - public String getEncoding() { - return encoding; - } - - @Override - public Map<String, CompiledObjectDecorator> getDecorators() { - if (decorators == null) { - decorators = new TreeMap<>(); - ClassLoader classloader = - Thread.currentThread().getContextClassLoader(); - if (log.isInfoEnabled()) { - log.info("with cl " + classloader); - } - - // load decorators - ServiceLoader<CompiledObjectDecorator> services = - ServiceLoader.load(CompiledObjectDecorator.class, - classloader); - for (CompiledObjectDecorator decorator : services) { - if (log.isInfoEnabled()) { - log.info("detected " + decorator); - } - decorators.put(decorator.getName(), decorator); - } - } - return decorators; - } - - @Override - public Map<String, JAXXCompilerFinalizer> getFinalizers() { - if (finalizers == null) { - finalizers = new TreeMap<>(); - - ClassLoader classloader = - Thread.currentThread().getContextClassLoader(); - if (log.isInfoEnabled()) { - log.info("with cl " + classloader); - } - - ServiceLoader<JAXXCompilerFinalizer> services = - ServiceLoader.load(JAXXCompilerFinalizer.class, - classloader); - for (JAXXCompilerFinalizer finalizer : services) { - if (log.isInfoEnabled()) { - log.info("detected " + finalizer); - } - finalizers.put(finalizer.getClass().getName(), finalizer); - } - } - return finalizers; - } - - @Override - public Map<String, Initializer> getInitializers() { - if (initializers == null) { - initializers = new TreeMap<>(); - ClassLoader classloader = - Thread.currentThread().getContextClassLoader(); - if (log.isInfoEnabled()) { - log.info("with cl " + classloader); - } - - ServiceLoader<Initializer> loader = - ServiceLoader.load(Initializer.class, classloader); - - for (Initializer initializer : loader) { - if (log.isInfoEnabled()) { - log.info("detected " + initializer); - } - initializers.put(initializer.getClass().getName(), initializer); - } - } - return initializers; - } - - @Override - public File getCommonCss() { - return commonCss; - } - - @Override - public String getCssExtension() { - return DEFAULT_CSS_EXTENSION; - } - - public void setCommonCss(File commonCss) { - this.commonCss = commonCss; - } - - @Override - public boolean isAutoRecurseInCss() { - return autoRecurseInCss; - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString( - this, ToStringStyle.MULTI_LINE_STYLE); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/EventHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/EventHandler.java deleted file mode 100644 index 5fe8bf6..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/EventHandler.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler; - -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.MethodDescriptor; - -public class EventHandler { - - private String eventId; - - private String objectCode; - - private ClassDescriptor listenerClass; - - private MethodDescriptor addMethod; - - private MethodDescriptor listenerMethod; - - private String javaCode; - - public EventHandler(String eventId, - String objectCode, - MethodDescriptor addMethod, - ClassDescriptor listenerClass, - MethodDescriptor listenerMethod, - String javaCode) { - this.eventId = eventId; - this.objectCode = objectCode; - this.addMethod = addMethod; - this.listenerClass = listenerClass; - this.listenerMethod = listenerMethod; - this.javaCode = javaCode; - } - - public String getEventId() { - return eventId; - } - - public String getObjectCode() { - return objectCode; - } - - public MethodDescriptor getAddMethod() { - return addMethod; - } - - public ClassDescriptor getListenerClass() { - return listenerClass; - } - - public MethodDescriptor getListenerMethod() { - return listenerMethod; - } - - public String getJavaCode() { - return javaCode; - } - - @Override - public String toString() { - return "EventHandler[" + eventId + ", " + - listenerClass.getName() + ", " + - objectCode + ", " + javaCode + "]"; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/I18nHelper.java b/jaxx-compiler/src/main/java/jaxx/compiler/I18nHelper.java deleted file mode 100644 index 930923f..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/I18nHelper.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler; - -import jaxx.runtime.SwingUtil; -import org.apache.commons.lang3.CharUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.i18n.I18n; - -import java.util.Arrays; -import java.util.List; - -/** - * I18n methods to add {@link I18n#t(String, Object...)} method on some attributes. - * - * Make sure to set an i18nable compiler to have his {@link CompilerConfiguration#isI18nable()} returning true. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class I18nHelper { - - protected static final Log log = LogFactory.getLog(I18nHelper.class); - - public static final List<String> I18N_ATTRIBUTES = Arrays.asList("text", "title", "toolTipText"); - - /** - * Test if we have an active i18n attribute (says an i18n attribute on a i18neable compiler). - * - * @param attributeName name of attribute to test - * @param compiler current used compiler (contains options) - * @return <code>true</code> if wa have an active i18n attribute, <code>false</code> otherwise. - */ - public static boolean isI18nableAttribute(String attributeName, JAXXCompiler compiler) { - return compiler.getConfiguration().isI18nable() && isI18nAttribute(attributeName); - } - - /** - * Test if we have an i18n attribute. - * - * @param attributeName name of attribute to test - * @return <code>true</code> if wa have an active i18n attribute, <code>false</code> otherwise. - */ - public static boolean isI18nAttribute(String attributeName) { - return I18N_ATTRIBUTES.contains(attributeName); - } - - /** - * Add the i18n on a attribute. - * - * Note: <b>Be ware : </b> no test is done here to ensure we are on a i18neable attribute for an i18nable compiler. - * - * Make sure with the method {@link I18nHelper#isI18nableAttribute(String, JAXXCompiler)} returns - * <code>true</code> before using this method. - * - * @param widgetId the id of the widget - * @param attributeName the name of the attribute - * @param attributeValueCode the value code of the attribute value - * @param compiler the current used compile - * @return the surrender i18n call if attribute name is match the - * attributeValueCode otherwise - */ - public static String addI18nInvocation(String widgetId, String attributeName, String attributeValueCode, JAXXCompiler compiler) { - - if (log.isDebugEnabled()) { - log.debug(" try i18n support for [" + widgetId + ":" + attributeName + "] : " + attributeValueCode); - } - boolean doWarn = false; - int indexOf = attributeValueCode.indexOf("t("); - if (indexOf > -1 && !attributeValueCode.contains(",")) { - if (indexOf == 0) { - doWarn = true; - } else { - - // make sure that the previous character is not alphabetical (means yet another method than t()) - char charBefore = attributeValueCode.charAt(indexOf - 1); - if (CharUtils.isAsciiAlphanumeric(charBefore)) { - - doWarn = false; - } else { - - //TODO tchemit-2014-08-24 Maybe could we do better ? - doWarn = true; - } - } - } - if (doWarn) { - compiler.reportWarning("\n\tjaxx supports i18n, no need to add explicit call to I18n.t for attribute '" + attributeName + "' in component '" + widgetId + "' : [" + attributeValueCode + "]"); - } else { - compiler.addImport("static " + I18n.class.getName() + ".t"); - attributeValueCode = "t(" + attributeValueCode + ")"; - } - - return attributeValueCode; - } - - /** - * Box a i18n key with code to be used as a i18n mnemonic. - * - * Note: <b>Be ware : </b> no test is done here to ensure we are on a - * i18neable attribute for an i18nable compiler. - * - * @param object the object to use - * @param attributeName the name of the attribute - * @param attributeValueCode the value code of the attribute value - * @param compiler the current used compile - * @return the surrender i18n call if attribute name is match the - * attributeValueCode otherwise - * @since 2.6.11 - */ - public static String addI18nMnemonicInvocation(CompiledObject object, - String attributeName, - String attributeValueCode, - JAXXCompiler compiler) { - String stringValue = I18nHelper.addI18nInvocation( - object.getId(), - attributeName, - attributeValueCode, - compiler); - compiler.addImport(SwingUtil.class.getName()); - return "{" + SwingUtil.class.getSimpleName() + - ".getFirstCharAt(" + stringValue + ",'Z')}"; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/IDHelper.java b/jaxx-compiler/src/main/java/jaxx/compiler/IDHelper.java deleted file mode 100644 index 8b1b0ce..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/IDHelper.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; - -/** - * A usefull class to generate Ids. - * - * Created: 27 nov. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - */ -public class IDHelper { - /** - * Logger - */ - protected static final Log log = LogFactory.getLog(IDHelper.class); - - /** - * Counter by type - */ - protected final Map<String, Integer> autoGenIds = new TreeMap<>(); - - /** - * Maps of uniqued id for objects used in compiler - */ - protected final Map<Object, String> uniqueIds = new HashMap<>(); - - /** - * Optimized Counter - */ - protected int optimizedAutogenId = 0; - - /** - * Flag to use optimized id - */ - protected final boolean optimize; - - public IDHelper(boolean optimize) { - this.optimize = optimize; - } - - public String nextId(String name) { - - if (optimize) { - return "$" + Integer.toString(optimizedAutogenId++, 36); - } - - Integer integer = autoGenIds.get(name); - - if (integer == null) { - integer = 0; - } - name = name.substring(name.lastIndexOf(".") + 1); - String result = "$" + name + integer; - autoGenIds.put(name, ++integer); - if (log.isTraceEnabled()) { - log.trace("new id = " + result); - } - return result; - } - - public void revertId(String name) { - if (optimize) { - optimizedAutogenId--; - } else { - name = name.substring(name.lastIndexOf(".") + 1); - Integer integer = autoGenIds.get(name); - if (integer != null) { - autoGenIds.put(name, --integer); - } - } - } - - public String getUniqueId(Object object) { - String result = uniqueIds.get(object); - if (result == null) { - result = "$u" + uniqueIds.size(); - uniqueIds.put(object, result); - } - if (log.isTraceEnabled()) { - log.trace("new uniqueid = " + result); - } - return result; - } - - public void clear() { - autoGenIds.clear(); - uniqueIds.clear(); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompiler.java b/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompiler.java deleted file mode 100644 index b12e9a1..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompiler.java +++ /dev/null @@ -1,2139 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler; - -import jaxx.compiler.binding.DataBindingHelper; -import jaxx.compiler.css.StylesheetHelper; -import jaxx.compiler.finalizers.JAXXCompilerFinalizer; -import jaxx.compiler.java.JavaElementFactory; -import jaxx.compiler.java.JavaField; -import jaxx.compiler.java.JavaFile; -import jaxx.compiler.java.JavaFileGenerator; -import jaxx.compiler.java.JavaMethod; -import jaxx.compiler.java.parser.ParseException; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.reflect.FieldDescriptor; -import jaxx.compiler.reflect.MethodDescriptor; -import jaxx.compiler.script.ScriptManager; -import jaxx.compiler.tags.DefaultObjectHandler; -import jaxx.compiler.tags.TagHandler; -import jaxx.compiler.tags.TagManager; -import jaxx.runtime.ComponentDescriptor; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.JAXXObjectDescriptor; -import jaxx.runtime.css.Rule; -import jaxx.runtime.css.Stylesheet; -import jaxx.runtime.spi.UIHandler; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.eugene.java.JavaGeneratorUtil; -import org.nuiton.eugene.java.extension.ImportsManager; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import org.xml.sax.helpers.AttributesImpl; -import org.xml.sax.helpers.XMLFilterImpl; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import javax.xml.transform.ErrorListener; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMResult; -import javax.xml.transform.sax.SAXSource; -import java.awt.BorderLayout; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Modifier; -import java.net.URL; -import java.net.URLDecoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Stack; - -/** - * Compiles a given {@link #jaxxFile} into a {@link #javaFile}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.0.0 - */ -public class JAXXCompiler { - - /** Logger */ - protected static final Log log = LogFactory.getLog(JAXXCompiler.class); - - /** - * True to throw exceptions when we encounter unresolvable classes, - * false to ignore. - * - * This is currently set to false until JAXX has full support for - * inner classes (including enumerations), because currently they don't - * always resolve (but will generally run without error anyway). - */ - public static boolean STRICT_CHECKS; - - - public static final String JAXX_NAMESPACE = - "http://www.jaxxframework.org/"; - - public static final String JAXX_INTERNAL_NAMESPACE = - "http://www.jaxxframework.org/internal"; - - /** Maximum length of an inlinable creation method. */ - public static final int INLINE_THRESHOLD = 300; - - /** Line separator cached value */ - protected static String lineSeparator = - System.getProperty("line.separator", "\n"); - - public static final String BORDER_LAYOUT_PREFIX = BorderLayout.class.getSimpleName() + "."; - - /** The unique object handler used in first pass */ - protected final DefaultObjectHandler firstPassClassTagHandler; - - /*------------------------------------------------------------------------*/ - /*-- compiler fields -----------------------------------------------------*/ - /*------------------------------------------------------------------------*/ - - /** flag to detect if an error occurs while compiling jaxx file */ - protected boolean failed; - - /** Object corresponding to the root tag in the document. */ - protected CompiledObject root; - - /** Contains strings of the form "javax.swing." */ - protected Set<String> importedPackages; - - /** Contains strings of the form "javax.swing.Timer" */ - protected Set<String> importedClasses; - - /** Keeps track of open components (components still having children added). */ - protected Stack<CompiledObject> openComponents; - - /** to generate ids */ - protected final IDHelper idHelper; - - /** Binding Util */ - protected final DataBindingHelper bindingHelper; - - /** table of symbols for this compiler */ - protected SymbolTable symbolTable; - - /** - * Base directory used for path resolution (normally the directory in - * which the .jaxx file resides). - */ - protected File baseDir; - - /** jaxx file being compiled. */ - protected File src; - - /** Parsed XML of src file. */ - protected Document document; - - /** Name of class being compiled. */ - protected String outputClassName; - - /** script manager */ - protected ScriptManager scriptManager; - - /** - * Combination of all stylesheets registered using - * {@link #registerStylesheet(Stylesheet)}. - */ - protected Stylesheet stylesheet; - - /** Contains all attributes defined inline on class tags. */ - protected List<Rule> inlineStyles; - - /** - * Maps objects (expressed in Java code) to event listener classes - * (e.g. MouseListener) to Lists of EventHandlers. The final list - * contains all event handlers of a particular type attached to a - * particular object (again, as represented by a Java expression). - */ - protected Map<String, Map<ClassDescriptor, List<EventHandler>>> eventHandlers; - - /** Map of event handler method names used in compiler */ - protected Map<EventHandler, String> eventHandlerMethodNames; - - /** - * ClassLoader which searches the user-specified class path in - * addition to the normal class path - */ - protected ClassLoader classLoader; - - /** - * A list of Runnables which will be run after the first compilation pass. - * - * This is primarily used to trigger the creation of CompiledObjects, - * which cannot be created during the first pass and must be created - * in document order. - */ - protected List<Runnable> initializers; - - /** - * extra interfaces which can by passed to root object via the - * 'implements' attribute - */ - private String[] extraInterfaces; - - /** a flag to generate a abstract class */ - private boolean abstractClass; - - /** the possible generic type of the class */ - private String genericType; - - /** the possible generic type of the super class */ - private String superGenericType; - - /** Extra code to be added to the instance initializer. */ - protected StringBuilder initializer; - - /** Extra code to be added at the end of the instance initializer. */ - protected StringBuilder lateInitializer; - - /** Extra code to be added to the class body. */ - protected StringBuilder bodyCode; - - /** true if a main() method has been declared in a script */ - protected boolean mainDeclared; - - /** the file to be generated */ - protected JavaFile javaFile; - - /** Used for error reporting purposes, so we can report the right line number. */ - protected Stack<Element> tagsBeingCompiled; - - /** Used for error reporting purposes, so we can report the right source file. */ - protected Stack<File> sourceFiles; - - /** - * Maps object ID strings to the objects themselves. - * - * These are created during the second compilation pass. - */ - protected Map<String, CompiledObject> objects; - - /** - * Maps objects to their ID strings. - * - * These are created during the second compilation pass. - */ - protected Map<CompiledObject, String> ids; - - /** default decodator to use if none specified */ - protected CompiledObjectDecorator defaultDecorator; - - /** - * engine which references this compiler - * (can be null if compiler is standalone) - */ - protected final JAXXEngine engine; - - protected final CompilerConfiguration defaultConfiguration = - new DefaultCompilerConfiguration(); - - protected final JAXXCompilerFile jaxxFile; - - /** - * Flag to know if jaxx file ident css was found, otherwise add it - * at the end of the second compile pass. - * - * @since 2.0.2 - */ - protected boolean identCssFound; - - /** - * A flag to know if SwingUtil msut be imported. - * - * @since 2.4 - * @deprecated since 2.4.1, will be removed in version 3.0, it is not a good - * idea to do special treatment for a particular class, to use SwingUtil, - * do like for other class : import it! - */ - @Deprecated - protected boolean needSwingUtil; - - public static final String[] EMPTY_STRING_ARRAY = new String[0]; - - public JAXXCompiler() { - this(null, null, null); - } - - /** - * Creates a new JAXXCompiler. - * - * @param engine engine which use the compiler (could be null if not attach to any engine) - * @param jaxxFile the file to compile - * @param defaultImports list of default imports to add to java files - */ - public JAXXCompiler(JAXXEngine engine, - JAXXCompilerFile jaxxFile, - List<String> defaultImports) { - this.engine = engine; - this.jaxxFile = jaxxFile; - - ids = new LinkedHashMap<>(); - objects = new LinkedHashMap<>(); - bodyCode = new StringBuilder(); - lateInitializer = new StringBuilder(); - initializer = new StringBuilder(); - tagsBeingCompiled = new Stack<>(); - initializers = new ArrayList<>(); - eventHandlerMethodNames = new HashMap<>(); - eventHandlers = - new HashMap<>(); - inlineStyles = new ArrayList<>(); - scriptManager = new ScriptManager(this); - symbolTable = new SymbolTable(); - openComponents = new Stack<>(); - importedPackages = new HashSet<>(); - importedClasses = new HashSet<>(); - sourceFiles = new Stack<>(); - if (jaxxFile == null) { - src = null; - baseDir = null; - outputClassName = null; - } else { - src = jaxxFile.getJaxxFile(); - baseDir = src.getParentFile(); - outputClassName = jaxxFile.getClassName(); - sourceFiles.push(src); - addImport(outputClassName.substring( - 0, outputClassName.lastIndexOf(".") + 1) + "*"); - } - - firstPassClassTagHandler = new DefaultObjectHandler( - ClassDescriptorHelper.getClassDescriptor(Object.class) - ); - bindingHelper = new DataBindingHelper(this); - - if (defaultImports != null) { - for (String defaultImport : defaultImports) { - addDefaultImport(defaultImport); - } - } - - if (engine != null) { - CompilerConfiguration configuration = engine.getConfiguration(); - // add extra imports from configuration - if (configuration.getExtraImports() != null) { - for (String extraImport : configuration.getExtraImports()) { - addImport(extraImport); - } - } - defaultDecorator = engine.getDecorator( - configuration.getDefaultDecoratorClass()); - if (defaultDecorator == null) { - throw new IllegalArgumentException( - "could not find default decorator : " + - configuration.getDefaultDecoratorClass() - ); - } - idHelper = new IDHelper(configuration.isOptimize()); - } else { - idHelper = new IDHelper(false); - } - } - - /*------------------------------------------------------------------------*/ - /*-- Initializer methods -------------------------------------------------*/ - /*------------------------------------------------------------------------*/ - - public void runInitializers() { - for (Runnable runnable : initializers) { - if (log.isDebugEnabled()) { - log.debug(runnable); - } - try { - runnable.run(); - } catch (Exception e) { - //TC - 20081018 report error and quit - reportError(e.getMessage()); - return; - } - } - initializers.clear(); - } - - /** - * Registers a <code>Runnable</code> which will be executed after the first - * compilation pass is complete. - * - * @param r runnable to register - */ - public void registerInitializer(Runnable r) { - initializers.add(r); - } - - /*------------------------------------------------------------------------*/ - /*-- Compile methods -----------------------------------------------------*/ - /*------------------------------------------------------------------------*/ - - public void compileFirstPass(final Element tag) throws IOException { - tagsBeingCompiled.push(tag); - - String namespace = tag.getNamespaceURI(); - String fullClassName; - String localName = tag.getLocalName(); - boolean namespacePrefix = tag.getPrefix() != null; - // resolve class tags into fully-qualified class name - if (namespace != null && namespace.endsWith("*")) { - String packageName = namespace.substring(0, namespace.length() - 1); - if (localName.startsWith(packageName)) { - // class name is fully-qualified already - fullClassName = TagManager.resolveClassName(localName, this); - } else { - // namespace not included in class name, probably need the - // namespace to resolve - fullClassName = TagManager.resolveClassName( - packageName + localName, this); - if (fullClassName == null && !namespacePrefix) { - // it was just a default namespace, try again without - // using the namespace - fullClassName = TagManager.resolveClassName(localName, this); - } - } - } else { - fullClassName = TagManager.resolveClassName(localName, this); - } - - if (fullClassName != null) { - // we are definitely dealing with a class tag - addDependencyClass(fullClassName); - namespace = fullClassName.substring( - 0, fullClassName.lastIndexOf(".") + 1) + "*"; - if (symbolTable.getSuperclassName() == null) { - symbolTable.setSuperclassName(fullClassName); - } - String id = tag.getAttribute(DefaultObjectHandler.ID_ATTRIBUTE); - MethodDescriptor methodDescriptor; - if (!id.isEmpty()) { - symbolTable.getClassTagIds().put(id, fullClassName); - if (tag.getAttributeNode(DefaultObjectHandler.JAVA_BEAN_ATTRIBUTE) != null) { - // add java bean support for this property - String capitalizeName = StringUtils.capitalize(id); - // add method - - methodDescriptor = new MethodDescriptor( - "get" + capitalizeName, - Modifier.PUBLIC, - fullClassName, - EMPTY_STRING_ARRAY, - getClassLoader() - ); - symbolTable.getScriptMethods().add(methodDescriptor); - if (Boolean.class.getName().equals(fullClassName)) { - methodDescriptor = new MethodDescriptor( - "is" + capitalizeName, - Modifier.PUBLIC, - fullClassName, - EMPTY_STRING_ARRAY, - getClassLoader() - ); - symbolTable.getScriptMethods().add(methodDescriptor); - } - methodDescriptor = new MethodDescriptor( - "set" + capitalizeName, - Modifier.PUBLIC, - JAXXCompilerFinalizer.TYPE_VOID, - new String[]{fullClassName}, - getClassLoader() - ); - symbolTable.getScriptMethods().add(methodDescriptor); - } else { - // add simple get support - String capitalizeName = StringUtils.capitalize(id); - // add method - methodDescriptor = new MethodDescriptor( - "get" + capitalizeName, - Modifier.PUBLIC, - fullClassName, - EMPTY_STRING_ARRAY, - getClassLoader() - ); - symbolTable.getScriptMethods().add(methodDescriptor); - } - } - String interfacesStr = - tag.getAttribute(DefaultObjectHandler.IMPLEMENTS_ATTRIBUTE); - if (!interfacesStr.isEmpty()) { - // there is some interfaces to deal with - - - try { - String[] interfaces = - JavaGeneratorUtil.splitFqnList(interfacesStr, ','); - if (log.isDebugEnabled()) { - log.debug("detect interfaces : " + - Arrays.toString(interfaces)); - } - symbolTable.setInterfaces(interfaces); - } catch (Exception e) { - // the syntax is not valid (missed one >) - throw new CompilerException( - "Syntax error of interfaces " + - interfacesStr); - } -// StringTokenizer stk = new StringTokenizer(interfacesStr, ","); -// List<String> tmp = new ArrayList<String>(); -// while (stk.hasMoreTokens()) { -// String c = stk.nextToken(); -// if (c.contains("<") && !c.contains(">")) { -// // deal with a generic interface with more than one -// // parameter -// boolean done = false; -// while (stk.hasMoreTokens()) { -// -// String next = stk.nextToken(); -// if (!next.contains(">")) { -// // still a parameter of the generic type -// continue; -// } -// // ok find the ending token -// done = true; -// break; -// } -// if (!done) { -// // the syntax is not valid (missed one >) -// throw new CompilerException( -// "Syntax error of interfaces " + -// interfacesStr); -// } -// //c = c.substring(0, c.indexOf("<")); -// } -// tmp.add(c.trim()); -// } -// String[] interfaces = tmp.toArray(new String[tmp.size()]); -// if (log.isDebugEnabled()) { -// log.debug("detect interfaces : " + -// Arrays.toString(interfaces)); -// } -// symbolTable.setInterfaces(interfaces); - } - - } - // during the first pass, we can't create ClassDescriptors for JAXX - // files because they may not have been processed yet (and we can't - // wait until they have been processed because of circular - // dependencies). - // So we don't do any processing during the first pass which requires - // having a ClassDescriptor; here we determine whether we have a class - // tag or not (class tag namespaces end in "*") and use a generic - // handler if so. - // The real handler is used during the second pass. - TagHandler handler = namespace != null && namespace.endsWith("*") ? - firstPassClassTagHandler : - TagManager.getTagHandler(tag.getNamespaceURI(), - localName, - namespacePrefix, - this - ); - if (!firstPassClassTagHandler.equals(handler) && - handler instanceof DefaultObjectHandler) { - fullClassName = - ((DefaultObjectHandler) handler).getBeanClass().getName(); - handler = firstPassClassTagHandler; - } - if (firstPassClassTagHandler.equals(handler)) { - final String finalClassName = fullClassName; - - // register an initializer which will create the - // CompiledObject after pass 1 - - registerInitializer(new Runnable() { - - @Override - public void run() { - DefaultObjectHandler handler = - (DefaultObjectHandler) TagManager.getTagHandler( - null, - finalClassName, - JAXXCompiler.this - ); - if (handler == null) { - throw new CompilerException( - "Internal error: missing TagHandler for '" + - finalClassName + "'"); - } - handler.registerCompiledObject(tag, JAXXCompiler.this); - } - }); - } - if (handler == null) { - reportError("Could not find a Java class corresponding to: <" + - tag.getTagName() + ">"); - failed = true; - } else { - try { - handler.compileFirstPass(tag, this); - } catch (CompilerException e) { - reportError(e); - } - } - - Element finished = tagsBeingCompiled.pop(); - if (finished != tag) { - throw new IllegalStateException( - "internal error: just finished compiling " + tag + - ", but top of tagsBeingCompiled stack is " + finished); - } - } - - public void compileSecondPass(Element tag) throws IOException { - tagsBeingCompiled.push(tag); - - TagHandler handler = TagManager.getTagHandler( - tag.getNamespaceURI(), - tag.getLocalName(), - tag.getPrefix() != null, - this - ); - - if (handler == null) { - reportError("Could not find a Java class corresponding to: <" + - tag.getTagName() + ">"); - failed = true; - } else { - handler.compileSecondPass(tag, this); - } - - Element finished = tagsBeingCompiled.pop(); - if (!tag.equals(finished)) { - throw new RuntimeException( - "internal error: just finished compiling " + tag + - ", but top of tagsBeingCompiled stack is " + finished); - } - } - - public void compileFirstPass() throws IOException { - InputStream in = new FileInputStream(src); - try { - document = parseDocument(in); - - Element documentElement = document.getDocumentElement(); - - boolean addAutoHandlerUI = - getEngine().getConfiguration().isAddAutoHandlerUI(); - - String uiHandlerFullClassName; - - if (addAutoHandlerUI) { - - // try to find the - - uiHandlerFullClassName = getOutputClassName() + "Handler"; - ClassDescriptor uiHandlerClass = null; - try { - uiHandlerClass = ClassDescriptorHelper.getClassDescriptor(uiHandlerFullClassName, getClassLoader()); - if (uiHandlerClass != null && !ClassDescriptorHelper.isAssignableFrom(uiHandlerClass, UIHandler.class)) { - String isAbstractValue = documentElement.getAttribute("abstract"); - boolean isAbstract = isAbstractValue != null && "true".equals(isAbstractValue); - if (!isAbstract) { - reportWarning( - "Found a handler " + uiHandlerFullClassName - + " which does not implements " + UIHandler.class.getName()); - } - uiHandlerClass = null; - } - - } catch (ClassNotFoundException e) { - // not found - } - - if (uiHandlerClass == null) { - uiHandlerFullClassName = null; - } - } else { - - uiHandlerFullClassName = documentElement.getAttribute( - DefaultObjectHandler.HANDLER_ATTRIBUTE); - if (StringUtils.isNotBlank(uiHandlerFullClassName)) { - - // get his class descriptor - ClassDescriptor uiHandlerClass = null; - try { - uiHandlerClass = ClassDescriptorHelper.getClassDescriptor(uiHandlerFullClassName, getClassLoader()); - - // check if implements UIHandler - if (uiHandlerClass != null && !ClassDescriptorHelper.isAssignableFrom(uiHandlerClass, UIHandler.class)) { - reportError( - "Found a handler " + uiHandlerFullClassName - + " which does not implements " + UIHandler.class.getName()); - uiHandlerClass = null; - } - } catch (ClassNotFoundException e) { - reportError("Could not find type " + uiHandlerFullClassName); - } - if (uiHandlerClass == null) { - uiHandlerFullClassName = null; - } - } - } - - if (uiHandlerFullClassName != null) { - - setUiHandler(uiHandlerFullClassName); - } - - compileFirstPass(documentElement); - } catch (SAXParseException e) { - reportError(e.getLineNumber(), "Invalid XML: " + e.getMessage()); - } catch (SAXException e) { - reportError(null, "Error parsing XML document: " + e); - } finally { - in.close(); - } - } - - public void compileSecondPass() throws IOException { - if (!tagsBeingCompiled.isEmpty()) { - throw new RuntimeException( - "Internal error: starting pass two, but tagsBeingCompiled" + - " is not empty: " + tagsBeingCompiled); - } - - if (isUseHandler()) { - - String handler = getUiHandler(); - - boolean addField = true; - try { - - boolean superclassIsJAXXObject = isSuperClassAware(JAXXObject.class); - - if (superclassIsJAXXObject) { - - CompiledObject rootObject = getRootObject(); - ClassDescriptor rootObjectClass = rootObject.getObjectClass(); - // test if there is a super handler - try { - rootObjectClass.getDeclaredFieldDescriptor("handler"); - addField = false; - } catch (NoSuchFieldException e) { - - // no field handler found - } - } - - } catch (ClassNotFoundException e) { - throw new RuntimeException("Coul not find class ",e); - } - - JavaField field = JavaElementFactory.newField( - Modifier.PROTECTED, - handler, - DefaultObjectHandler.HANDLER_ATTRIBUTE, - !addField, - null); - - if (addField) { - - javaFile.addField(field, false); - - } else { - - // override getter - javaFile.addOverrideGetterMethod(field.getName(), - Modifier.PUBLIC, - field.getType(), - true); - } - - } - compileSecondPass(document.getDocumentElement()); - } - - /*------------------------------------------------------------------------*/ - /*-- CompiledObject methods ----------------------------------------------*/ - /*------------------------------------------------------------------------*/ - - public void openComponent(CompiledObject component) throws CompilerException { - openComponent(component, null); - } - - public void openComponent(CompiledObject component, - String constraints) throws CompilerException { - if (constraints != null) { - - // try to add the constraints class in imports - if (constraints.startsWith(BORDER_LAYOUT_PREFIX)) { - addImport(BorderLayout.class.getName()); - } - } - CompiledObject parent = getOpenComponent(); - openInvisibleComponent(component); - if (parent != null && !component.isOverride()) { - parent.addChild(component, constraints, this); - } - } - - public void openInvisibleComponent(CompiledObject component) { - if (!ids.containsKey(component)) { - registerCompiledObject(component); - } - openComponents.push(component); - } - - public CompiledObject getOpenComponent() { - if (openComponents.isEmpty()) { - return null; - } - return openComponents.peek(); - } - - public void closeComponent(CompiledObject component) { - if (component == null) { - throw new NullPointerException("can not close a null component"); - } - if (!component.equals(openComponents.pop())) { - throw new IllegalArgumentException( - "can only close the topmost open object"); - } - } - - public void registerCompiledObject(CompiledObject object) { -// assert engine.symbolTables.values().contains(symbolTable) : -// "attempting to register CompiledObject before pass 1 is complete"; - if (root == null) { - root = object; - } - - String id = object.getId(); - if (ids.containsKey(object)) { - reportError("object '" + object + - "' is already registered with id '" + - ids.get(object) + "', cannot re-register as '" + id + - "'" - ); - } - if (objects.containsKey(id) && !(objects.get(id) instanceof Element)) { - reportError("id '" + id + "' is already registered to component " + objects.get(id)); - } - objects.put(id, object); - ids.put(object, id); - if (object.getDecorator() == null) { - // use default decorator - object.setDecorator(defaultDecorator); - } - } - - public CompiledObject getCompiledObject(String id) { - runInitializers(); -// assert engine.symbolTables.values().contains(symbolTable) : -// "attempting to retrieve CompiledObject before pass 1 is complete"; - return objects.get(id); - } - - public boolean inlineCreation(CompiledObject object) { - return object.getId().startsWith("$") && - object.getInitializationCode(this).length() < INLINE_THRESHOLD; - } - - public void checkOverride(CompiledObject object) throws CompilerException { - String fieldName = object.getId(); - if (fieldName.startsWith("$")) { - return; - } - ClassDescriptor ancestor = root.getObjectClass(); - if (object.getObjectClass().equals(ancestor)) { - return; - } - while (ancestor != null) { - try { - FieldDescriptor f = - ancestor.getDeclaredFieldDescriptor(fieldName); - if (!f.getType().isAssignableFrom(object.getObjectClass())) { - reportError( - "attempting to redefine superclass member '" + - fieldName + "' as incompatible type (was " + - f.getType() + ", redefined as " + - object.getObjectClass() + ")" - ); - } - object.setOverride(true); - object.setOverrideType(f.getType()); - if (!getCanonicalName(f.getType()).equals(getCanonicalName(object))) { - - // types are not the same - String simpleType = - getImportedType(getCanonicalName(object)); - if (log.isDebugEnabled()) { - log.debug("Simple type for " + object.getId() - + " : " + getCanonicalName(object) + - " against : " + - getCanonicalName(f.getType())); - } - object.setSimpleType(simpleType); - } - break; - } catch (NoSuchFieldException e) { - if (log.isDebugEnabled()) { - log.debug(">>>>> could not find declared field [" + fieldName + "] in " + ancestor.getName()); - } - ancestor = ancestor.getSuperclass(); - } - } - } - - /*------------------------------------------------------------------------*/ - /*-- DataBinding methods -------------------------------------------------*/ - /*------------------------------------------------------------------------*/ - - public DataBindingHelper getBindingHelper() { - return bindingHelper; - } - - public void registerEventHandler(EventHandler handler) { - String objectCode = handler.getObjectCode(); - Map<ClassDescriptor, List<EventHandler>> listeners = - eventHandlers.get(objectCode); - if (listeners == null) { - listeners = new HashMap<>(); - eventHandlers.put(objectCode, listeners); - } - ClassDescriptor listenerClass = handler.getListenerClass(); - List<EventHandler> handlerList = listeners.get(listenerClass); - if (handlerList == null) { - handlerList = new ArrayList<>(); - listeners.put(listenerClass, handlerList); - } - handlerList.add(handler); - } - - public String getEventHandlerMethodName(EventHandler handler) { - String result = eventHandlerMethodNames.get(handler); - if (result == null) { - if (getConfiguration().isOptimize()) { - result = "$ev" + eventHandlerMethodNames.size(); - } else { - //TC-20090309 must get the goal property from the event id - // to make possible inheritance - String id = handler.getEventId().substring( - 0, handler.getEventId().indexOf(".")); - - result = "do" + StringUtils.capitalize(handler.getListenerMethod().getName()) + "__on__" + id; - //TC-20091105 : check the method name is available - // using css can have multi methods with result name (see priority) - if (eventHandlerMethodNames.containsValue(result)) { - int index = 0; - String result2; - do { - result2 = result + "_" + index++; - - } while (eventHandlerMethodNames.containsValue(result2)); - result = result2; - } - } - eventHandlerMethodNames.put(handler, result); - } - return result; - } - - /*------------------------------------------------------------------------*/ - /*-- Script methods ------------------------------------------------------*/ - /*------------------------------------------------------------------------*/ - - public void addScriptField(FieldDescriptor field) { - symbolTable.getScriptFields().add(field); - } - - public void addScriptMethod(MethodDescriptor method) { - if (method.getName().equals("main") && - method.getParameterTypes().length == 1 && - method.getParameterTypes()[0].getName().equals("[Ljava.lang.String;")) { - setMainDeclared(true); - } - symbolTable.getScriptMethods().add(method); - } - - public void registerScript(String script) throws CompilerException { - registerScript(script, null); - } - - public void registerScript(String script, - File sourceFile) throws CompilerException { - if (sourceFile != null) { - sourceFiles.push(sourceFile); - } - script = script.trim(); - if (!"".equals(script) && !script.endsWith("}") && - !script.endsWith(";")) { - script += ";"; - } - scriptManager.registerScript(script); - - if (sourceFile != null) { - File pop = sourceFiles.pop(); - if (!sourceFile.equals(pop)) { - throw new RuntimeException( - "leaving registerScript(), but " + sourceFile + - " was not the top entry on the stack (found " + pop - + " instead)"); - } - } - } - - public String preprocessScript(String script) throws CompilerException { - return scriptManager.preprocessScript(script); - } - - /*------------------------------------------------------------------------*/ - /*-- StyleSheet methods --------------------------------------------------*/ - /*------------------------------------------------------------------------*/ - - public boolean isIdentCssFound() { - return identCssFound; - } - - public void registerStyleSheetFile(File styleFile, boolean warnAutoCssImport) throws IOException { - if (!identCssFound) { - - // detects if the given css file is ident to jaxx file - File identCssFile = jaxxFile.getCssFile(); - - if (styleFile.equals(identCssFile) && identCssFile.exists()) { - - // ok found ident css file - identCssFound = true; - - if (warnAutoCssImport) { - - reportWarning("The css file " + styleFile + " can be automaticly imported since it is named as his jaxx file."); - - } - - } - - } - String content = loadFile(styleFile); - getSourceFiles().push(styleFile); - try { - Stylesheet style = StylesheetHelper.processStylesheet(content); - registerStylesheet(style); - } catch (CompilerException e) { - String message= "Css file content is not valid :" + styleFile; - if (e instanceof jaxx.compiler.css.parser.ParseException) { - jaxx.compiler.css.parser.ParseException parseException = (jaxx.compiler.css.parser.ParseException) e; - - message += " (line: " + parseException.getLine() + " - col:" + parseException.getColumn() + ") "; - } - reportError(message, e); - } finally { - - // whatever could be result, must pop this source file - getSourceFiles().pop(); - } - } - - public void applyStylesheets() { - for (Object o : new ArrayList<>(objects.values())) { - CompiledObject object = (CompiledObject) o; - DefaultObjectHandler tagHandler = - TagManager.getTagHandler(object.getObjectClass()); - if (log.isDebugEnabled()) { - log.debug("will apply css on object " + object.getId() + - " from handler " + tagHandler); - } - tagHandler.applyStylesheets(object, this); - } - } - - public void registerStylesheet(Stylesheet stylesheet) { - if (this.stylesheet == null) { - this.stylesheet = stylesheet; - } else { - this.stylesheet.add(stylesheet.getRules()); - } - } - - public void addInlineStyle(CompiledObject object, - String propertyName, - boolean dataBinding) { - Rule style = StylesheetHelper.inlineAttribute( - object, - propertyName, - dataBinding - ); - inlineStyles.add(style); - } - - /*------------------------------------------------------------------------*/ - /*-- Report methods ------------------------------------------------------*/ - /*------------------------------------------------------------------------*/ - - public void reportWarning(String warning) { - Element currentTag = null; - if (!tagsBeingCompiled.isEmpty()) { - currentTag = tagsBeingCompiled.peek(); - } - reportWarning(currentTag, warning, 0); - } - - public void reportWarning(Element tag, String warning, int lineOffset) { - String lineNumber = null; - if (tag != null) { - String lineAttr = - tag.getAttributeNS(JAXX_INTERNAL_NAMESPACE, "line"); - if (lineAttr.length() > 0) { - lineNumber = lineAttr; - } - } - File srcFile = sourceFiles.peek(); - try { - srcFile = srcFile.getCanonicalFile(); - } catch (IOException e) { - // ignore ? - } - StringBuilder buffer = new StringBuilder(); - buffer.append(srcFile); - if (lineNumber != null) { - buffer.append(":"); - buffer.append(sourceFiles.size() == 1 ? - Integer.parseInt(lineNumber) + lineOffset : - lineOffset + 1 - ); - } - buffer.append(getLineSeparator()).append(warning.trim()); - if (engine != null) { - engine.addWarning(buffer.toString()); - } else { - System.err.println(buffer.toString()); - } - } - - public void reportError(String error) { - Element currentTag = null; - if (!tagsBeingCompiled.isEmpty()) { - currentTag = tagsBeingCompiled.peek(); - } - reportError(currentTag, error); - } - - public void reportError(CompilerException ex) { - reportError(null, ex); - } - - public void reportError(String extraMessage, CompilerException ex) { - String message = ex.getMessage(); - if (UnsupportedAttributeException.class.equals(ex.getClass()) || - UnsupportedTagException.class.equals(ex.getClass())) { - String exceptionName = ex.getClass().getName(); - message = exceptionName.substring( - exceptionName.lastIndexOf(".") + 1) + ": " + message; - } - int lineOffset; - if (ex instanceof ParseException) { - lineOffset = Math.max(0, ((ParseException) ex).getLine() - 1); - } else { - lineOffset = 0; - } - Element currentTag = null; - if (!tagsBeingCompiled.isEmpty()) { - currentTag = tagsBeingCompiled.peek(); - } - reportError(currentTag, extraMessage != null ? - extraMessage + message : - message, lineOffset - ); - } - - public void reportError(Element tag, String error) { - reportError(tag, error, 0); - } - - public void reportError(Element tag, String error, int lineOffset) { - int lineNumber = 0; - if (tag != null) { - String lineAttr = - tag.getAttributeNS(JAXX_INTERNAL_NAMESPACE, "line"); - if (lineAttr.length() > 0) { - lineNumber = Integer.parseInt(lineAttr); - } - } - lineNumber = Math.max(lineNumber, 1) + lineOffset; - reportError(lineNumber, error); - } - - public void reportError(int lineNumber, String error) { - File errorFile = sourceFiles.isEmpty() ? null : sourceFiles.peek(); - try { - if (errorFile != null) { - errorFile = errorFile.getCanonicalFile(); - } - } catch (IOException e) { - // ignore ? - } - StringBuilder buffer = new StringBuilder(); - buffer.append(errorFile != null ? errorFile.getPath() : - "<unknown source>"); - if (lineNumber > 0) { - buffer.append(":").append(lineNumber); - } - buffer.append(getLineSeparator()).append(": ").append(error); - if (engine != null) { - engine.addError(buffer.toString()); - } else { - System.err.println(buffer.toString()); - } - failed = true; - } - - /*------------------------------------------------------------------------*/ - /*-- Getter methods ------------------------------------------------------*/ - /*------------------------------------------------------------------------*/ - - public Map<String, CompiledObject> getObjects() { - return objects; - } - - public Map<String, Map<ClassDescriptor, List<EventHandler>>> getEventHandlers() { - return eventHandlers; - } - - public CompilerConfiguration getConfiguration() { - JAXXEngine engine = getEngine(); - if (engine == null) { - return defaultConfiguration; - } - return engine.getConfiguration(); - } - - public String getOutputClassName() { - return outputClassName; - } - - public File getBaseDir() { - return baseDir; - } - - public Set<String> getImportedClasses() { - return importedClasses; - } - - public Set<String> getImportedPackages() { - return importedPackages; - } - - public Iterator<CompiledObject> getObjectCreationOrder() { - return objects.values().iterator(); - } - - public CompiledObject getRootObject() { - return root; - } - - public Stack<File> getSourceFiles() { - return sourceFiles; - } - - public ScriptManager getScriptManager() { - return scriptManager; - } - - public SymbolTable getSymbolTable() { - return symbolTable; - } - - public Stylesheet getStylesheet() { - Stylesheet merged = new Stylesheet(); - if (stylesheet != null) { - merged.add(stylesheet.getRules()); - } - merged.add(inlineStyles.toArray(new Rule[inlineStyles.size()])); - return merged; - } - - public FieldDescriptor[] getScriptFields() { - List<FieldDescriptor> scriptFields = symbolTable.getScriptFields(); - return scriptFields.toArray( - new FieldDescriptor[scriptFields.size()]); - } - - public FieldDescriptor getScriptField(String fieldName) { - for (FieldDescriptor f : symbolTable.getScriptFields()) { - if (fieldName.equals(f.getName())) { - return f; - } - } - return null; - } - - public MethodDescriptor[] getScriptMethods() { - List<MethodDescriptor> scriptMethods = symbolTable.getScriptMethods(); - return scriptMethods.toArray( - new MethodDescriptor[scriptMethods.size()]); - } - - public MethodDescriptor getScriptMethod(String methodName) { - for (MethodDescriptor m : symbolTable.getScriptMethods()) { - if (methodName.equals(m.getName())) { - return m; - } - } - return null; - } - - public boolean isFailed() { - return failed; - } - - public IDHelper getIdHelper() { - return idHelper; - } - - /** - * Returns a <code>ClassLoader</code> which searches the user-specified - * class path in addition to the normal system class path. - * - * @return <code>ClassLoader</code> to use while resolving class references - */ - public ClassLoader getClassLoader() { - if (classLoader == null) { - CompilerConfiguration configuration = getConfiguration(); - if (configuration.getClassLoader() != null) { - classLoader = configuration.getClassLoader(); - } else { - throw new NullPointerException( - "compiler configuration requires a classLoader! :\n" + - configuration); - } - } - - return classLoader; - } - - /** - * Checks if the super class of the mirrored javaFile is aware of the - * iven {@code type}. - * - * <strong>Note:</strong> If no super-class exist, then returns - * {@code false}. - * - * @param type the type to check against super class - * @return {@code true} if super class exists and is assignable against the - * given type, {@code false} otherwise - * @throws ClassNotFoundException if could not find class descriptor for - * super-class - */ - public boolean isSuperClassAware(Class<?> type) throws ClassNotFoundException { - ClassDescriptor superClass = root.getObjectClass(); - if (superClass == null) { - - // no super class, not awre of anything - return false; - } - - return ClassDescriptorHelper.isAssignableFrom(superClass, - type); - } - - public JAXXObjectDescriptor getJAXXObjectDescriptor() { - runInitializers(); - CompiledObject[] components = new ArrayList<>( - objects.values()).toArray(new CompiledObject[objects.size()]); - - assert initializers.isEmpty() : - "there are pending initializers remaining"; - assert root != null : "root object has not been defined"; - assert Arrays.asList(components).contains(root) : - "root object is not registered"; - ComponentDescriptor[] descriptors = - new ComponentDescriptor[components.length]; - // as we print, sort the array so that component's parents are always - // before the components themselves - for (int i = 0; i < components.length; i++) { - CompiledObject parent = components[i].getParent(); - while (parent != null) { - boolean found = false; - for (int j = i + 1; j < components.length; j++) { - // found parent after component, swap them - if (components[j] == parent) { - components[j] = components[i]; - components[i] = parent; - found = true; - break; - } - } - if (!found) { - break; - } - parent = components[i].getParent(); - } - int parentIndex = -1; - if (parent != null) { - for (int j = 0; j < i; j++) { - if (components[j].equals(parent)) { - parentIndex = j; - break; - } - } - } - descriptors[i] = new ComponentDescriptor( - components[i].getId(), - components[i] == root ? outputClassName : components[i].getObjectClass().getName(), - components[i].getStyleClass(), - parentIndex != -1 ? descriptors[parentIndex] : null); - } - - Stylesheet css = getStylesheet(); - if (css == null) { - css = new Stylesheet(); - } - - return new JAXXObjectDescriptor(descriptors, css); - } - - /*------------------------------------------------------------------------*/ - /*-- Buffer --------------------------------------------------------------*/ - /*------------------------------------------------------------------------*/ - - public StringBuilder getInitializer() { - return initializer; - } - - public StringBuilder getLateInitializer() { - return lateInitializer; - } - - public StringBuilder getBodyCode() { - return bodyCode; - } - - - public boolean isMainDeclared() { - return mainDeclared; - } - - public void setMainDeclared(boolean mainDeclared) { - this.mainDeclared = mainDeclared; - } - - public void appendInitializerCode(String code) { - initializer.append(code); - } - - public void appendBodyCode(String code) { - bodyCode.append(code); - } - - public void appendLateInitializer(String code) { - lateInitializer.append(code); - } - - public boolean hasMethod(String methodName) { - for (JavaMethod method : getJavaFile().getMethods()) { - if (methodName.equals(method.getName())) { - return true; - } - } - return false; - } - - /*------------------------------------------------------------------------*/ - /*-- Other methods -------------------------------------------------------*/ - /*------------------------------------------------------------------------*/ - - public void addImport(Class<?> clazz) { - addImport(clazz.getName()); - } - - public void addImport(String text) { - if (text.endsWith("*")) { - importedPackages.add(text.substring(0, text.length() - 1)); - } else { - importedClasses.add(text); - } - - if (!text.equals("*")) { - getJavaFile().addImport(text); - } - } - - protected void addDefaultImport(String text) { - if (text.endsWith("*")) { - importedPackages.add(text.substring(0, text.length() - 1)); - } else { - importedClasses.add(text); - } - } - - public void addDependencyClass(String className) { - - if (engine.containsJaxxFileClassName(className)) { - - // already registred in engine - return; - } - - // register the jaxx file into the engine - - URL jaxxURL = ClassDescriptorHelper.getURL(getClassLoader(), className, "jaxx"); - - if (jaxxURL == null) { - - // not a jaxx file, can quit now - return; - } - - if (!engine.isCompileFirstPassTask()) { - throw new IllegalStateException( - "Internal error: adding dependency class " + - className + " during second compilation pass"); - } - - //FIXME tchemit 20100518 Must unify this with ClassDescriptorHelper to use the less costless resource - if (jaxxURL.toString().startsWith("file:")) { - File jaxxFile = URLtoFile(jaxxURL); - try { - jaxxFile = jaxxFile.getCanonicalFile(); - } catch (IOException ex) { - // ignore ? (at least log it...) - log.error(ex); - } - String jaxxFileName = - className.substring(className.lastIndexOf(".") + 1) + - ".jaxx"; - - assert jaxxFile.getName().equalsIgnoreCase(jaxxFileName) : - "expecting file name to match " + - className + ", but found " + jaxxFile.getName(); - if (jaxxFile.getName().equals(jaxxFileName)) { - engine.addFileToCompile(jaxxFile, className); - } - } - } - - /** - * Loads the given file and returns its content. - * - * <b>Note:</b> If any errors encounters, then report an error in the - * compiler and returns an empty string. - * - * @param file the file to load - * @return the content of the file or empty string if something was wrong - */ - public String loadFile(File file) { - if (!file.exists()) { - reportError("Could not found file " + file); - return ""; - } - try { - FileReader in = new FileReader(file); - try { - StringWriter styleBuffer = new StringWriter(); - char[] readBuffer = new char[2048]; - int c; - while ((c = in.read(readBuffer)) > 0) { - styleBuffer.write(readBuffer, 0, c); - } - return styleBuffer.toString(); - } finally { - in.close(); - } - } catch (IOException e) { - reportError("Could not read file " + file + " for reason " + - e.getMessage()); - return ""; - } - } - - /** - * Verifies that a snippet of Java code parses correctly. - * - * A warning is generated if the string has enclosing curly braces. - * - * @param javaCode the Java code snippet to test - * @return a "cooked" version of the string which has enclosing curly - * braces removed. - * @throws CompilerException if the code cannot be parsed - */ - public String checkJavaCode(String javaCode) { - javaCode = scriptManager.trimScript(javaCode); - scriptManager.checkParse(javaCode); - return javaCode; - } - - /** - * Check that a reference exists in symbol table on second compil pass - * - * @param tag the current tag - * @param reference the required reference - * @param strict flag to report an error if reference was not found - * @param attribute (if not null reference the attribute where is defined - * the reference) - * @return <code>true</code> if reference was found, <code>false</code> - * otherwise and add an error in compiler - */ - public boolean checkReference(Element tag, - String reference, - boolean strict, - String attribute) { - String component = getSymbolTable().getClassTagIds().get(reference); - if (component == null) { - if (strict) { - String msg; - if (attribute != null) { - msg = "tag '" + tag.getLocalName() + - "' could not find the reference '" + reference + - "' on attribute [" + attribute + "]"; - } else { - msg = "tag '" + tag.getLocalName() + - "' could not find the reference '" + reference + "'"; - } - reportError(msg); - } - return false; - } - return true; - } - - public String getAutoId(String name) { - return idHelper.nextId(name); - } - - public String getUniqueId(Object object) { - return idHelper.getUniqueId(object); - } - - public void setExtraInterfaces(String[] extraInterfaces) { - this.extraInterfaces = extraInterfaces; - } - - public String[] getExtraInterfaces() { - return extraInterfaces; - } - - public boolean isAbstractClass() { - return abstractClass; - } - - public void setAbstractClass(boolean abstractClass) { - this.abstractClass = abstractClass; - } - - public String getGenericType() { - return genericType; - } - - public void setGenericType(String genericType) { - this.genericType = genericType; - } - - public String getSuperGenericType() { - return superGenericType; - } - - public void setSuperGenericType(String superGenericType) { - this.superGenericType = superGenericType; - } - - public void addSimpleField(JavaField javaField) { - getJavaFile().addSimpleField(javaField); - } - - public JavaFile getJavaFile() { - if (javaFile == null) { - String outputClassName = getOutputClassName(); - if (outputClassName == null) { - javaFile = JavaElementFactory.newFile(0, ""); - } else { - int dotPos = outputClassName.lastIndexOf("."); - String packageName = dotPos != -1 ? - outputClassName.substring(0, dotPos) : null; - String simpleClassName = outputClassName.substring(dotPos + 1); - - javaFile = JavaElementFactory.newFile( - Modifier.PUBLIC, - packageName + "." + simpleClassName); - } - } - return javaFile; - } - - public void preFinalizeCompiler() throws Exception { - - } - - public void finalizeCompiler() throws Exception { - - int dotPos = getOutputClassName().lastIndexOf("."); - String packageName = dotPos != -1 ? - getOutputClassName().substring(0, dotPos) : null; - String simpleClassName = getOutputClassName().substring(dotPos + 1); - CompiledObject compiledObject = getRootObject(); - - String genericType = getGenericType(); - if (StringUtils.isNotEmpty(genericType)) { - - // add the generic type to the root object - - // generictype can be on form E extends XXX - //keep only the first thing... - StringBuilder sb = new StringBuilder(); - String[] allTypes = JavaGeneratorUtil.splitFqnList(genericType, ','); - for (String type : allTypes) { - int anExtends = type.indexOf("extends"); - if (anExtends > -1) { - type = type.substring(0, anExtends - 1).trim(); - } - sb.append(", ").append(type); - } - String finalType; - if (allTypes.length > 0) { - finalType = sb.substring(2); - } else { - finalType = sb.toString(); - } - compiledObject.setGenericTypes(finalType); - } - // finalize all objects via their decorator - - for (CompiledObject object : getObjects().values()) { - CompiledObjectDecorator decorator = object.getDecorator(); - decorator.finalizeCompiler(this, - root, - object, - javaFile, - packageName, - simpleClassName, - getOutputClassName()); - } - - // obtain list of finalizers to apply - - List<JAXXCompilerFinalizer> realFinalizers = - new ArrayList<>(); - for (JAXXCompilerFinalizer finalizer : - getConfiguration().getFinalizers().values()) { - if (finalizer.accept(this)) { - realFinalizers.add(finalizer); - } - } - - // call the finalizers finalizeCompiler method - - for (JAXXCompilerFinalizer finalizer : realFinalizers) { - // check if finalizer can be apply of this compiler - if (finalizer.accept(this)) { - finalizer.finalizeCompiler(compiledObject, - this, - javaFile, - packageName, - simpleClassName - ); - } - } - - // call the compiled objects finalizeCompiler method - - for (CompiledObject object : getObjects().values()) { - object.finalizeCompiler(this); - } - - // compile bindings - - getBindingHelper().finalizeBindings(); - - // call the finalizers prepareJavaFile method - - for (JAXXCompilerFinalizer finalizer : realFinalizers) { - finalizer.prepareJavaFile(compiledObject, - this, - javaFile, - packageName, - simpleClassName - ); - } - } - - public void generate(JavaFileGenerator generator) throws IOException { - File dest; - String fqn = getOutputClassName(); - if (getConfiguration().getTargetDirectory() != null) { - dest = new File(getConfiguration().getTargetDirectory(), - fqn.replace('.', File.separatorChar) + ".java" - ); - } else { - dest = new File(getBaseDir(), - fqn.substring(fqn.lastIndexOf(".") + 1) + ".java" - ); - } - - // make sure directory exists - File parentFile = dest.getParentFile(); - if (parentFile == null) { - throw new IOException("No parent file for " + dest); - } - if (!parentFile.exists() && !parentFile.mkdirs()) { - throw new IOException("Could not create directory " + parentFile); - } - if (dest.exists() && !dest.setLastModified(System.currentTimeMillis())) { - log.warn("could not touch file " + dest); - } - PrintWriter out = new PrintWriter(new FileWriter(dest)); - try { - generator.generateFile(javaFile, out); - } finally { - out.close(); - } - } - - /** - * Returns the system line separator string. - * - * @return the string used to separate lines - */ - public static String getLineSeparator() { - return lineSeparator; - } - - // 1.5 adds getCanonicalName; unfortunately we can't depend on 1.5 features yet - - public static String getCanonicalName(Class<?> clazz) { - if (clazz.isArray()) { - String canonicalName = getCanonicalName(clazz.getComponentType()); - if (canonicalName != null) { - return canonicalName + "[]"; - } - return null; - } - return clazz.getName().replace('$', '.'); - } - - public static String getCanonicalName(ClassDescriptor clazz) { - if (clazz.isArray()) { - String canonicalName = getCanonicalName(clazz.getComponentType()); - if (canonicalName != null) { - return canonicalName + "[]"; - } - return null; - } - return clazz.getName().replace('$', '.'); - } - - public static String getCanonicalName(CompiledObject compiled) { - ClassDescriptor clazz = compiled.getObjectClass(); - if (clazz.isArray()) { - String canonicalName = getCanonicalName(clazz.getComponentType()); - if (canonicalName != null) { - if (compiled.getGenericTypesLength() > 0) { - canonicalName += compiled.getGenericTypes(); - } - return canonicalName + "[]"; - } - return null; - } - - String canonicalName = clazz.getName().replace('$', '.'); - if (compiled.getGenericTypesLength() > 0) { - canonicalName += compiled.getGenericTypes(); - } - return canonicalName; - } - - /** - * Escapes a string using standard Java escape sequences, generally in - * preparation to including it in a string literal in a compiled Java file. - * - * @param raw the raw string to be escape - * @return a string in which all 'dangerous' characters have been replaced - * by equivalent Java escape sequences - */ - public static String escapeJavaString(String raw) { - StringBuilder out = new StringBuilder(raw); - for (int i = 0; i < out.length(); i++) { - char c = out.charAt(i); - if (c == '\\' || c == '"') { - out.insert(i, '\\'); - i++; - } else if (c == '\n') { - out.replace(i, i + 1, "\\n"); - i++; - } else if (c == '\r') { - out.replace(i, i + 1, "\\r"); - i++; - } else if (c < 32 || c > 127) { - String value = Integer.toString((int) c, 16); - while (value.length() < 4) { - value = "0" + value; - } - out.replace(i, i + 1, "\\u" + value); - i += 5; - } - } - return out.toString(); - } - - public static File URLtoFile(URL url) { - return URLtoFile(url.toString()); - } - - public static File URLtoFile(String urlString) { - if (!urlString.startsWith("file:")) { - throw new IllegalArgumentException("url must start with 'file:'"); - } - urlString = urlString.substring("file:".length()); - if (urlString.startsWith("/") && - System.getProperty("os.name").startsWith("Windows")) { - urlString = urlString.substring(1); - } - try { - return new File(URLDecoder.decode( - urlString.replace('/', File.separatorChar), "utf-8")); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - - public static SAXParser getSAXParser() { - try { - SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setNamespaceAware(true); - SAXParser parser; - parser = factory.newSAXParser(); - return parser; - } catch (SAXException e) { - throw new RuntimeException(e); - } catch (ParserConfigurationException e) { - throw new RuntimeException(e); - } - } - - public static Document parseDocument(InputStream in) throws IOException, SAXException { - try { - TransformerFactory factory = TransformerFactory.newInstance(); - Transformer transformer = factory.newTransformer(); - transformer.setErrorListener(new ErrorListener() { - - @Override - public void warning( - TransformerException ex) throws TransformerException { - throw ex; - } - - @Override - public void error( - TransformerException ex) throws TransformerException { - throw ex; - } - - @Override - public void fatalError( - TransformerException ex) throws TransformerException { - throw ex; - } - }); - - DOMResult result = new DOMResult(); - transformer.transform( - new SAXSource(new XMLFilterImpl(getSAXParser().getXMLReader()) { - - Locator locator; - - @Override - public void setDocumentLocator(Locator locator) { - this.locator = locator; - } - - @Override - public void startElement(String uri, - String localName, - String qName, - Attributes atts) throws SAXException { - AttributesImpl resultAtts = new AttributesImpl(atts); - resultAtts.addAttribute( - JAXX_INTERNAL_NAMESPACE, - "line", - "internal:line", - "CDATA", - String.valueOf(locator.getLineNumber()) - ); - getContentHandler().startElement(uri, - localName, - qName, - resultAtts - ); - } - }, new InputSource(in)), result); - return (Document) result.getNode(); - } catch (TransformerConfigurationException e) { - throw new RuntimeException(e); - } catch (TransformerException e) { - Throwable ex = e; - while (ex.getCause() != null) { - ex = ex.getCause(); - } - if (ex instanceof IOException) { - throw (IOException) ex; - } - if (ex instanceof SAXException) { - throw (SAXException) ex; - } - if (ex instanceof RuntimeException) { - throw (RuntimeException) ex; - } - throw new RuntimeException(ex); - } - } - - public JAXXEngine getEngine() { - return engine; - } - - public void clear() { - idHelper.clear(); - bindingHelper.clear(); - objects.clear(); - ids.clear(); - if (symbolTable != null) { - symbolTable.clear(); - } - } - -// public void setIdentCssFound(boolean identCssFound) { -// this.identCssFound = identCssFound; -// } - - public void setClassLoader(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - /** - * Try to import the given type into the underlying java file of this compiler. - * - * If import can not be done, will then returns the fully qualified name of - * the type. - * - * @param type the type to simplify - * @return the simplify type or the fqn if type could not be imported for the underlying java file. - * @since 2.4.1 - */ - public String getImportedType(Class<?> type) { - return getJavaFile().getImportedType(type); - } - - /** - * Try to import the given type into the underlying java file of this compiler. - * - * If import can not be done, will then returns the fully qualified name of - * the type. - * - * @param type the fqn of the type to simplify - * @return the simplify type or the fqn if type could not be imported for the underlying java file. - * @since 2.4.1 - */ - public String getImportedType(String type) { - return getJavaFile().getImportedType(type); - } - - public String getImportedTypeForSimpleName(String type) { - String suffix = "." + type; - String result = null; - for (String importedClass : getImportedClasses()) { - if (importedClass.endsWith(suffix)) { - result = importedClass; - break; - } - } - return result; - } - - /** - * @return the javafile import manager - * @since 2.4 - * @deprecated since 2.4.1, will be removed in version 3.0 : do not want - * to expose eugene export manager in rest of api, this is purpose of - * JavaFile only - */ - @Deprecated - public ImportsManager getImportManager() { - return getJavaFile().getImportManager(); - } - - /** - * @since 2.4 - * @deprecated since 2.4.1, will be removed in version 3.0, has no effect do not use it... - */ - @Deprecated - public boolean isNeedSwingUtil() { - return needSwingUtil; - } - - /** - * @since 2.4 - * @deprecated since 2.4.1, will be removed in version 3.0, has no effect do not use it... - */ - @Deprecated - public void setNeedSwingUtil(boolean needSwingUtil) { - this.needSwingUtil = needSwingUtil; - } - - public boolean containsScriptField(String fieldName) { - FieldDescriptor[] scriptFields = getScriptFields(); - for (FieldDescriptor f : scriptFields) { - if (fieldName.equals(f.getName())) { - return true; - } - } - return false; - } - - protected String uiHandler; - - public String getUiHandler() { - return uiHandler; - } - - public void setUiHandler(String uiHandler) { - this.uiHandler = uiHandler; - } - - public boolean isUseHandler() { - return StringUtils.isNotBlank(uiHandler); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompilerFile.java b/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompilerFile.java deleted file mode 100644 index d622a22..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompilerFile.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.util.FileUtil; - -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; - -/** - * Represents a file to be treated by the {@link JAXXCompiler}. - * - * It contains informations about jaxx file, ident css, class name,... - * - * <b>Note:</b> This class will be more used in next version (will have the - * compiler it-self, symbols table,...). - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class JAXXCompilerFile { - - /** Logger */ - private static final Log log = LogFactory.getLog(JAXXCompilerFile.class); - - /** root directory of the source roots. */ - protected final File basedir; - - /** relative path from {@link #basedir} to {@link #jaxxFile}. */ - private final String relativePath; - - /** location of the jaxx file */ - protected File jaxxFile; - - /** location of the ident css file */ - protected File cssFile; - - /** full qualified name of the jaxx file class */ - protected String className; - - /** compiler associated to the file */ - protected JAXXCompiler compiler; - - /** - * Css file extension. - * - * @see CompilerConfiguration#getCssExtension() - */ - protected final String cssExtension; - - public JAXXCompilerFile(File basedir, File jaxxFile, String cssExtension) { - this.basedir = basedir; - this.jaxxFile = jaxxFile; - this.cssExtension = cssExtension; - String absolutePath = jaxxFile.getAbsolutePath(); - String baseAbsolutePath = basedir.getAbsolutePath(); - if (!absolutePath.startsWith(baseAbsolutePath)) { - throw new IllegalStateException( - "Jaxx file " + jaxxFile + " is not in basedir " + basedir); - } - - relativePath = absolutePath.substring(baseAbsolutePath.length() + 1); - if (log.isDebugEnabled()) { - log.debug("relativePath = " + relativePath); - } - } - - public JAXXCompilerFile(File jaxxFile, String className, String cssExtension) { - - this.jaxxFile = jaxxFile; - this.className = className; - this.cssExtension = cssExtension; - - String extension = FileUtil.extension(jaxxFile); - String[] paths = className.split("\\."); - File basedir = jaxxFile; - for (int i = paths.length - 1; i > -1; i--) { - if (basedir == null) { - throw new IllegalStateException("Could not find base dir for " + jaxxFile + " according to fqn " + className); - } - - String path = paths[i]; - if (basedir.equals(jaxxFile)) { - // first in loop - path += "." + extension; - } - - // check path = base filename - if (!path.equals(basedir.getName())) { - throw new IllegalStateException("Should have found directory " + path + ", but was " + basedir.getName()); - } - - basedir = basedir.getParentFile(); - } - - if (log.isDebugEnabled()) { - log.debug("basedir = " + basedir); - } - - // must guess the base directory and relative path - - String relativePath = jaxxFile.getAbsolutePath().substring(basedir.getAbsolutePath().length() + 1); - - if (log.isDebugEnabled()) { - log.debug("relative path = " + relativePath); - } - - this.basedir = basedir; - this.relativePath = relativePath; - } - - public File getBasedir() { - return basedir; - } - - public String getRelativePath() { - return relativePath; - } - - public JAXXCompiler getCompiler() { - return compiler; - } - -// public SymbolTable getSymbolTable() { -// return compiler==null?null:compiler.getSymbolTable(); -// } - - public File getJaxxFile() { - if (jaxxFile == null) { - jaxxFile = new File(basedir, relativePath); - } - return jaxxFile; - } - - public URL getJAXXFileURL() { - File file = getJaxxFile(); - try { - return file.toURI().toURL(); - } catch (MalformedURLException e) { - throw new IllegalStateException("Url of the jaxx file is malformed... " + file); - } - } - - public File getCssFile() { - if (cssFile == null) { - File file = getJaxxFile(); - String extension = FileUtil.extension(file); - String fileName = file.getName(); - int length = fileName.length() - extension.length(); - String identCssFilename = fileName.substring(0, length) + cssExtension; - cssFile = new File(file.getParentFile(), identCssFilename); - } - return cssFile; - } - - public String getClassName() { - if (className == null) { - - className = relativePath.substring(0, relativePath.lastIndexOf(".")); - className = className.replace(File.separatorChar, '.'); - className = className.replace('/', '.'); - className = className.replace('\\', '.'); - className = className.replace(':', '.'); - - } - return className; - } - - public void clear() { - if (compiler != null) { - compiler.clear(); - } - } - -// public void setSymbolTable(SymbolTable symbolTable) { -// this.symbolTable = symbolTable; -// } - - public void setCompiler(JAXXCompiler compiler) { - this.compiler = compiler; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/JAXXEngine.java b/jaxx-compiler/src/main/java/jaxx/compiler/JAXXEngine.java deleted file mode 100644 index 634137f..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/JAXXEngine.java +++ /dev/null @@ -1,484 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler; - -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tasks.CompileFirstPassTask; -import jaxx.compiler.tasks.CompileSecondPassTask; -import jaxx.compiler.tasks.FinalizeTask; -import jaxx.compiler.tasks.GenerateConstructorsTask; -import jaxx.compiler.tasks.GenerateMissingRulesTask; -import jaxx.compiler.tasks.GenerateTask; -import jaxx.compiler.tasks.InitTask; -import jaxx.compiler.tasks.JAXXEngineTask; -import jaxx.compiler.tasks.ProfileTask; -import jaxx.compiler.tasks.StyleSheetTask; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.util.StringUtil; - -import java.io.File; -import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -/** - * The engine to compile jaxx files. - * - * The method {@link #run()} launch the compilation of files. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.0 was previously JAXXCompilerLaunchor - */ -public class JAXXEngine { - - /** Logger */ - private static final Log log = LogFactory.getLog(JAXXEngine.class); - - /** configuration of the launchor and underlines compilers */ - protected final CompilerConfiguration configuration; - - /** original list of files to compile (says the detected modfied files) */ - protected final JAXXCompilerFile[] incomingFiles; - - /** Files to compile */ - protected final List<JAXXCompilerFile> compilingFiles; - - /** Warnings detected while running. */ - protected final List<String> warnings; - - /** Errors detected while running. */ - protected final List<String> errors; - - /** tasks to launch */ - protected JAXXEngineTask[] tasks; - - /** current pass of the engine */ - protected JAXXEngineTask currentTask; - - /** profile attached to the engine (can be null) */ - protected JAXXProfile profiler; - - protected JAXXEngine(CompilerConfiguration configuration, - File base, - String... relativePaths) { - - if (configuration == null) { - - // use a default configuration - configuration = new DefaultCompilerConfiguration(); - } - - this.configuration = configuration; - warnings = new ArrayList<>(); - errors = new ArrayList<>(); - compilingFiles = new ArrayList<>(); - - if (configuration.isShowClassDescriptorLoading()) { - ClassDescriptorHelper.setShowLoading(true); - } - // add all default files to compile - for (String relativePath : relativePaths) { - JAXXCompilerFile compilerFile = - new JAXXCompilerFile(base, new File(base, relativePath), configuration.getCssExtension()); - addFileToCompile(compilerFile); - } - - // fix once for all incoming files to compile - incomingFiles = compilingFiles.toArray( - new JAXXCompilerFile[compilingFiles.size()]); - } - - public JAXXEngineTask[] getTasks() { - if (tasks == null) { - List<JAXXEngineTask> tasks = new ArrayList<>(); - - tasks.add(new InitTask()); - tasks.add(new CompileFirstPassTask()); - tasks.add(new CompileSecondPassTask()); - tasks.add(new StyleSheetTask()); - tasks.add(new FinalizeTask()); - tasks.add(new GenerateConstructorsTask()); - tasks.add(new GenerateTask()); - - if (getConfiguration().isGenerateMissingIdsAndStyleClassesInCss()) { - tasks.add(new GenerateMissingRulesTask()); - } - - if (getConfiguration().isProfile()) { - tasks.add(new ProfileTask()); - } - - this.tasks = tasks.toArray(new JAXXEngineTask[tasks.size()]); - } - return tasks; - } - - /** @return the errors of the engine */ - public List<String> getErrors() { - return errors; - } - - /** @return the warnings of the engine */ - public List<String> getWarnings() { - return warnings; - } - - public JAXXProfile getProfiler() { - if (profiler == null && getConfiguration().isProfile()) { - profiler = new JAXXProfile(); - } - return profiler; - } - - public CompilerConfiguration getConfiguration() { - return configuration; - } - - public JAXXCompilerFile[] getIncomingFiles() { - return incomingFiles; - } - -// public JAXXCompilerFile[] getCompilingFiles() { -// return compilingFiles.toArray( -// new JAXXCompilerFile[compilingFiles.size()]); -// } - - public JAXXCompilerFile[] getFilesToCompile() { - List<JAXXCompilerFile> files = new ArrayList<>(); - for (JAXXCompilerFile file : compilingFiles) { - if (file.getCompiler() == null) { - files.add(file); - } - } - return files.toArray(new JAXXCompilerFile[files.size()]); - } - - public JAXXCompilerFile[] getCompiledFiles() { - List<JAXXCompilerFile> files = new ArrayList<>(); - for (JAXXCompilerFile file : compilingFiles) { - if (file.getCompiler() != null) { - files.add(file); - } - } - // always send a copy to be safe. - return files.toArray(new JAXXCompilerFile[files.size()]); - } - - public boolean containsJaxxFileClassName(String className) { - for (JAXXCompilerFile file : compilingFiles) { - if (className.equals(file.getClassName())) { - return true; - } - } - return false; - } - - public boolean isCompileFirstPassTask() { - return currentTask != null && - CompileFirstPassTask.TASK_NAME.equals(currentTask.getName()); - } - - /** Resets all state in preparation for a new compilation session. */ - protected void reset(boolean cleanReports) { - for (JAXXCompilerFile compilerFile : compilingFiles) { - compilerFile.clear(); - } - compilingFiles.clear(); - if (profiler != null) { - profiler.clear(); - profiler = null; - } - if (cleanReports) { - clearReports(); - } - - ClassDescriptorHelper.setShowLoading(false); - } - - public void clearReports() { - getWarnings().clear(); - getErrors().clear(); - } - - public String getVersion() { - return "2.4"; - } - - /** - * Obtain the jaxx compiler of the given class name. - * - * @param className the name of the class to use - * @return the compiler instance which is processing the specified JAXX class. - * Each class is compiled by a different compiler instance. - */ - public JAXXCompilerFile getJAXXCompilerFile(String className) { - for (JAXXCompilerFile compilingFile : compilingFiles) { - if (className.equals(compilingFile.getClassName())) { - return compilingFile; - } - } - return null; - } - - /** - * Obtain the jaxx compiler of the given class name. - * - * @param className the name of the class to use - * @return the compiler instance which is processing the specified JAXX class. - * Each class is compiled by a different compiler instance. - */ - public JAXXCompiler getJAXXCompiler(String className) { - JAXXCompilerFile compilerFile = getJAXXCompilerFile(className); - if (compilerFile == null) { - return null; - } - return compilerFile.getCompiler(); - } - - /** - * Obtain the symbo table for the given class name. - * - * @param className the name of the class to use - * @return the symbol table for the specified JAXX class. - * Must be called during the second compiler pass. - * Returns <code>null</code> if no such symbol table could be found. - */ - public SymbolTable getSymbolTable(String className) { - JAXXCompiler compiler = getJAXXCompiler(className); - if (compiler == null) { - return null; - } - return compiler.getSymbolTable(); - } - - /** - * Obtain the decorator of the given name. - * - * @param name the name of the decorator - * @return the decorator found. - * @throws IllegalArgumentException if decorator not found for the given name. - */ - public CompiledObjectDecorator getDecorator(String name) - throws IllegalArgumentException { - Map<String, CompiledObjectDecorator> decorators = - getConfiguration().getDecorators(); - CompiledObjectDecorator decorator = decorators.get(name); - if (decorator == null) { - throw new IllegalArgumentException( - "could not find decorator with key " + name + - " (known decorators : " + decorators.keySet() + ")"); - } - return decorator; - } - - /** - * Obtain the decorator of the given type. - * - * @param type the type of the decorator (syas his fqn) - * @return the decorator found - */ - public CompiledObjectDecorator getDecorator(Class<?> type) { - Map<String, CompiledObjectDecorator> decorators = - getConfiguration().getDecorators(); - for (CompiledObjectDecorator decorator : decorators.values()) { - if (decorator.getClass().equals(type)) { - return decorator; - } - } - return null; - } - - /** - * Add a warning to the engine. - * - * @param warning the warning to add - */ - public void addWarning(String warning) { - warnings.add(warning); - } - - /** - * Add an error to the engine. - * - * @param error the error to add - */ - public void addError(String error) { - errors.add(error); - } - - /** - * Compiled a set of files. - * - * @return {@code -1} if errors appears, the number of generated files - * otherwise. - */ - public int run() { - try { - boolean success = true; - - for (JAXXEngineTask task : getTasks()) { - if (!success) { - // stop as soon as a engine phase failed - break; - } - - currentTask = task; - long t0 = System.nanoTime(); - if (isVerbose()) { - log.info("Start task '" + task.getName() + "' on " + - compilingFiles.size() + " file(s)"); - } - success = task.perform(this); - if (isVerbose()) { - log.info("task '" + task.getName() + "' done in " + - StringUtil.convertTime(System.nanoTime() - t0) - ); - } - } - return success ? compilingFiles.size() : -1; - - //FIXME : deal better the exception treatment... - } catch (CompilerException e) { - log.error(e.getMessage(), e); - return -1; - } catch (Throwable e) { - log.error(e.getMessage(), e); - return -1; - } finally { - if (configuration.isResetAfterCompile()) { - reset(false); - } - } - } - - /** - * Adds a {@code file} to be compiled. - * - * @param file the {@link JAXXCompilerFile} to add. - */ - public void addFileToCompile(JAXXCompilerFile file) { - - if (isVerbose()) { - log.info("register jaxx file " + file.getJaxxFile()); - } - compilingFiles.add(file); - } - - /** - * Adds a {@link JAXXCompilerFile} given the jaxx file and the - * corresponding class fully qualified name. - * - * @param jaxxFile the jaxx file location - * @param jaxxClassName the fully qualified name of the jaxx class - */ - public void addFileToCompile(File jaxxFile, String jaxxClassName) { - - if (log.isDebugEnabled()) { - log.debug("file = " + jaxxFile + ", fqn = " + jaxxClassName); - } - - JAXXCompilerFile file = new JAXXCompilerFile(jaxxFile, jaxxClassName, configuration.getCssExtension()); - addFileToCompile(file); - } - - /** - * Create a new compiler and attach it to the given {@code jaxxFile}. - * - * @param jaxxFile the definition of jaxx file to compile - * @return the new compiler - * @throws Exception if any pb while creating of compiler - */ - public JAXXCompiler newCompiler(JAXXCompilerFile jaxxFile) throws Exception { - - Class<?> compilerClass = - getConfiguration().getCompilerClass(); - - if (compilerClass == null) { - throw new NullPointerException( - "Configuration compilerClass is null"); - } - - Constructor<?> cons = compilerClass.getConstructor( - JAXXEngine.class, - JAXXCompilerFile.class, - List.class - ); - - /* - Arrays.asList( - "java.awt.*", - "java.awt.event.*", - "java.io.*", - "java.lang.*", - "java.util.*", - "javax.swing.*", - "javax.swing.border.*", - "javax.swing.event.*", - "jaxx.runtime.*", - "jaxx.runtime.swing.*", - "static org.nuiton.i18n.I18n.t", - "static jaxx.runtime.SwingUtil.createImageIcon" - ) - */ - JAXXCompiler jaxxCompiler = (JAXXCompiler) cons.newInstance( - this, - jaxxFile, - Arrays.asList( - "java.awt.*", -// "java.awt.event.*", -// "java.io.*", - "java.lang.*", -// "java.util.*", - "javax.swing.*", - "javax.swing.border.*", -// "javax.swing.event.*", -// "jaxx.runtime.*", - "jaxx.runtime.swing.*" - ) - ); - jaxxFile.setCompiler(jaxxCompiler); - return jaxxCompiler; - } - - public boolean isVerbose() { - return getConfiguration().isVerbose(); - } - - /** - * Add a profile time for the given compiler and key. - * - * Note: if {@link #profiler} is {@code null}, do nothing - * - * @param compiler the compiler to profile - * @param key the key of profiling - */ - public void addProfileTime(JAXXCompiler compiler, String key) { - JAXXProfile profiler = getProfiler(); - if (profiler != null) { - profiler.addTime(compiler, key); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/JAXXFactory.java b/jaxx-compiler/src/main/java/jaxx/compiler/JAXXFactory.java deleted file mode 100644 index 9bb73d8..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/JAXXFactory.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler; - -import jaxx.compiler.spi.Initializer; -import jaxx.compiler.tags.TagManager; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.File; -import java.util.ServiceLoader; - -/** - * Factory of {@link JAXXCompiler} and {@link JAXXEngine}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class JAXXFactory { - - /** Logger */ - private static final Log log = LogFactory.getLog(JAXXFactory.class); - - /** shared instance of engine. */ - protected static JAXXEngine engine; - - /** shared instance of configuration * */ - protected static CompilerConfiguration configuration; - - protected JAXXFactory() { - // no instance - } - - public static void setConfiguration(CompilerConfiguration configuration) { - JAXXFactory.configuration = configuration; - } - - /** - * Create a new empty launchor and set it as current launchor accessible - * via method {@link #getEngine()}. - * - * @return the new instanciated launchor - */ - public static JAXXEngine newDummyEngine() { - return newEngine(null); - } - - /** - * Create a new launchor and set it as current launchor accessible via - * method {@link #getEngine()}. - * - * The launchor will be prepared to run a set of files, expressed as paths - * relative to a base directory. - * The class names of the compiled files are derived from the relative path - * strings (e.g. "example/Foo.jaxx" compiles into a class named - * "example.Foo"). - * - * @param basedir the directory against which to resolve relative paths - * @param relativePaths a list of relative paths to .jaxx files being compiled - * @return the new instanciated launchor - */ - public static JAXXEngine newEngine(File basedir, String... relativePaths) { - checkConfiguration(); - if (engine != null) { - engine.reset(true); - } - engine = new JAXXEngine(configuration, basedir, relativePaths); - return engine; - } - - /** - * Creates a dummy Compiler for use in unit testing or dettached use of an - * engine. - * - * @param classLoader class loader to use - * @return the compiler - */ - public static JAXXCompiler newDummyCompiler(ClassLoader classLoader) { - JAXXCompiler compiler = new JAXXCompiler(); - if (classLoader != null) { - compiler.setClassLoader(classLoader); - } - return compiler; - } - - /** - * @return the current launchor - * @throws NullPointerException if no launchor was registred via a - * <code>newEngine-like</code> method. - */ - public static JAXXEngine getEngine() throws NullPointerException { - checkConfiguration(); - checkEngine(); - return engine; - } - - /** - * @return {@code true} if there is an engine registred, {@code false} otherwise. - */ - public static boolean isEngineRegistred() { - return engine != null; - } - - /** - * Load the {@link Initializer} services found via the{@link ServiceLoader} - * mecanism. - */ - public static void initFactory() { - - // must have a configuration - checkConfiguration(); - - TagManager.reset(); - - boolean verbose = configuration.isVerbose(); - for (Initializer initializer : - configuration.getInitializers().values()) { - if (verbose) { - log.info("load initializer " + initializer); - } - initializer.initialize(); - } - - } - - protected static void checkConfiguration() throws NullPointerException { - if (configuration == null) { - throw new NullPointerException("No configuration was registred."); - } - } - - protected static void checkEngine() throws NullPointerException { - if (engine == null) { - throw new NullPointerException("No engine was registred."); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/JAXXProfile.java b/jaxx-compiler/src/main/java/jaxx/compiler/JAXXProfile.java deleted file mode 100644 index 2c729b6..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/JAXXProfile.java +++ /dev/null @@ -1,386 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler; - -import jaxx.compiler.tasks.CompileFirstPassTask; -import jaxx.compiler.tasks.CompileSecondPassTask; -import jaxx.compiler.tasks.FinalizeTask; -import jaxx.compiler.tasks.GenerateTask; -import jaxx.compiler.tasks.StyleSheetTask; -import org.nuiton.util.StringUtil; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.SortedMap; -import java.util.TreeMap; - -/** - * Pour profiler les temps d'execution pendant une compilation. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.3 - */ -public class JAXXProfile { - - void clear() { - entries.clear(); - compilers.clear(); - } - - protected class CompilerEntry { - - JAXXCompiler compiler; - - SortedMap<String, Long> times; - - public CompilerEntry(JAXXCompiler compiler) { - this.compiler = compiler; - times = new TreeMap<>(); - } - } - - public static class ProfileResult { - - long min, max, average, total; - - Map<JAXXCompiler, Long> delta; - - List<Long> times; - - ProfileResult(Map<JAXXCompiler, Long> delta) { - this.delta = delta; - times = new ArrayList<>(delta.values()); - Collections.sort(times); - min = times.get(0); - max = times.get(times.size() - 1); - total = 0; - average = 0; - for (Long t : times) { - total += t; - } - average = total / times.size(); - } - - public long getTime(JAXXCompiler compiler) { - for (Entry<JAXXCompiler, Long> entry : delta.entrySet()) { - if (entry.getKey().equals(compiler)) { - return entry.getValue(); - } - } - throw new IllegalArgumentException("could not find time for compiler " + compiler); - } - - public void clear() { - times.clear(); - delta.clear(); - } - - public JAXXCompiler getCompiler(Long l) { - for (Entry<JAXXCompiler, Long> entry : delta.entrySet()) { - if (entry.getValue().equals(l)) { - return entry.getKey(); - } - } - throw new IllegalArgumentException("could not find compiler for time " + l); - } - } - - SortedMap<Integer, CompilerEntry> entries; - - List<JAXXCompiler> compilers; - - public JAXXProfile() { - compilers = new ArrayList<>(); - entries = new TreeMap<>(); - } - - public void addTime(JAXXCompiler compiler, String key) { - CompilerEntry e = getEntry(compiler); - e.times.put(key, System.nanoTime()); - } - - public Map<JAXXCompiler, Long> getDelta(String keyOne, String keyTwo) { - Map<JAXXCompiler, Long> result = new HashMap<>(); - for (Map.Entry<Integer, CompilerEntry> e : entries.entrySet()) { - JAXXCompiler c = getCompiler(e.getKey()); - CompilerEntry entry = e.getValue(); - Long t0 = entry.times.get(keyOne); - Long t1 = entry.times.get(keyTwo); - if (t0 == null) { - throw new NullPointerException( - "could not find time for " + keyOne + - " on compiler " + c.getOutputClassName()); - } - if (t1 == null) { - throw new NullPointerException( - "could not find time for " + keyTwo + - " on compiler " + c.getOutputClassName()); - } - long delta = t1 - t0; - result.put(c, delta); - } - return result; - } - - public ProfileResult newProfileResult(String name) { - ProfileResult result; - Map<JAXXCompiler, Long> delta = - getDelta(name + "_start", name + "_end"); - result = new ProfileResult(delta); - return result; - } - - public ProfileResult newProfileResult(ProfileResult... toCumul) { - ProfileResult result; - Map<JAXXCompiler, Long> delta = new HashMap<>(); - for (JAXXCompiler c : compilers) { - long total = 0; - for (ProfileResult cumul : toCumul) { - long time = cumul.getTime(c); - total += time; - } - delta.put(c, total); - } - result = new ProfileResult(delta); - return result; - } - - public StringBuilder computeProfileReport() { - - StringBuilder buffer = new StringBuilder(); - - if (compilers.isEmpty()) { - return buffer.append("no jaxx file treated, no profile report"); - } - - // compute max size of the fqn of a compiled file - int maxLength = 0; - for (JAXXCompiler compiler : compilers) { - int l = compiler.getOutputClassName().length(); - if (l > maxLength) { - maxLength = l; - } - } - - ProfileResult cfp = newProfileResult(CompileFirstPassTask.TASK_NAME); - ProfileResult csp = newProfileResult(CompileSecondPassTask.TASK_NAME); - ProfileResult ssp = newProfileResult(StyleSheetTask.TASK_NAME); - ProfileResult fp = newProfileResult(FinalizeTask.TASK_NAME); - ProfileResult gp = newProfileResult(GenerateTask.TASK_NAME); - ProfileResult total = newProfileResult(cfp, csp, ssp, fp, gp); - - String reportPattern = "\n|%1$-" + maxLength + - "s|%2$15s|%3$15s|%4$15s|%5$15s|%6$15s|%7$15s|"; - - char[] tmpC = new char[maxLength]; - Arrays.fill(tmpC, '-'); - String line = String.format(reportPattern, - new String(tmpC), - "---------------", - "---------------", - "---------------", - "---------------", - "---------------", - "---------------"); - - buffer.append(line); - - buffer.append(String.format(reportPattern, - "(files / stats) \\ passes", - "compile round 1", - "compile round 2", - "stylesheet", - "finalize", - "generation", - "all passes") - ); - - buffer.append(line); - - // affiche les temps de tous les fichiers en temp total croissant - for (Long l : total.times) { - JAXXCompiler c = total.getCompiler(l); - printReportLine(buffer, - reportPattern, - c.getOutputClassName(), - cfp.getTime(c), - csp.getTime(c), - ssp.getTime(c), - fp.getTime(c), - gp.getTime(c), - total.getTime(c) - ); - } - - buffer.append(line); - - if (compilers.size() > 1) { - printReportLine(buffer, - reportPattern, - "total (" + compilers.size() + " files)", - cfp.total, - csp.total, - ssp.total, - fp.total, - gp.total, - total.total - ); - - buffer.append(line); - - printReportLine2(buffer, - reportPattern, - "min", - cfp.min, - csp.min, - ssp.min, - fp.min, - gp.min, - total.min - ); - printReportLine2(buffer, - reportPattern, - "max", - cfp.max, - csp.max, - ssp.max, - fp.max, - gp.max, - total.max - ); - printReportLine(buffer, - reportPattern, - "average", - cfp.average, - csp.average, - ssp.average, - fp.average, - gp.average, - total.average - ); - buffer.append(line); - } - cfp.clear(); - csp.clear(); - ssp.clear(); - gp.clear(); - total.clear(); - - return buffer; - } - - public static final String TIME_PATTERN = "%1$9s - %2$2d%%"; - - protected void printReportLine(StringBuilder buffer, - String reportPattern, - String label, - long firstPassCounter, - long secondPassCounter, - long cssCounter, - long finalizeCounter, - long generatorCounter, - long totalCounter) { - - float percentCFP = (float) firstPassCounter / totalCounter * 100; - float percentCSP = (float) secondPassCounter / totalCounter * 100; - float percentCSSP = (float) cssCounter / totalCounter * 100; - float percentFP = (float) finalizeCounter / totalCounter * 100; - float percentGP = (float) generatorCounter / totalCounter * 100; - - String strCFP = String.format(TIME_PATTERN, - StringUtil.convertTime(firstPassCounter), - (int) percentCFP - ); - String strCSP = String.format(TIME_PATTERN, - StringUtil.convertTime(secondPassCounter), - (int) percentCSP - ); - String strCSSP = String.format(TIME_PATTERN, - StringUtil.convertTime(cssCounter), - (int) percentCSSP - ); - String strFP = String.format(TIME_PATTERN, - StringUtil.convertTime(finalizeCounter), - (int) percentFP - ); - String strGP = String.format(TIME_PATTERN, - StringUtil.convertTime(generatorCounter), - (int) percentGP - ); - - buffer.append(String.format(reportPattern, - label, - strCFP, - strCSP, - strCSSP, - strFP, - strGP, - StringUtil.convertTime(totalCounter)) - ); - } - - protected void printReportLine2(StringBuilder buffer, - String reportPattern, - String label, - long firstPassCounter, - long secondPassCounter, - long cssCounter, - long finalizeCounter, - long generatorCounter, - long totalCounter) { - buffer.append(String.format(reportPattern, - label, - StringUtil.convertTime(firstPassCounter), - StringUtil.convertTime(secondPassCounter), - StringUtil.convertTime(cssCounter), - StringUtil.convertTime(finalizeCounter), - StringUtil.convertTime(generatorCounter), - StringUtil.convertTime(totalCounter)) - ); - } - - protected CompilerEntry getEntry(JAXXCompiler compiler) { - int key = compiler.getOutputClassName().hashCode(); - CompilerEntry result = entries.get(key); - if (result == null) { - result = new CompilerEntry(compiler); - entries.put(key, result); - compilers.add(compiler); - } - return result; - } - - protected JAXXCompiler getCompiler(int hasCode) { - for (JAXXCompiler c : compilers) { - if (hasCode == c.getOutputClassName().hashCode()) { - return c; - } - } - return null; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/SymbolTable.java b/jaxx-compiler/src/main/java/jaxx/compiler/SymbolTable.java deleted file mode 100644 index 26e0fa1..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/SymbolTable.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler; - -import jaxx.compiler.reflect.FieldDescriptor; -import jaxx.compiler.reflect.MethodDescriptor; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** Symbol table constructed during the first pass of compilation. */ -public class SymbolTable { - - private String superclass; - // maps ID strings to class names -- we can't map directly to CompiledObjects, because we - // can't create those until after the first pass - - private Map<String, String> ids = new HashMap<>(); - - private List<FieldDescriptor> scriptFields = new ArrayList<>(); - - private List<MethodDescriptor> scriptMethods = new ArrayList<>(); - - private String[] interfaces; - - /** @return the fully-qualified name of the superclass of the class described by this symbol table. */ - public String getSuperclassName() { - return superclass; - } - - public String[] getInterfaces() { - return interfaces; - } - - public void setSuperclassName(String superclass) { - this.superclass = superclass; - } - - /** - * @return a map of IDs to class names. Each entry in the map corresponds to a class tag with an - * <code>id</code> attribute. The <code>id</code> is the key, and the fully-qualified class name - * of the tag is the value. - */ - public Map<String, String> getClassTagIds() { - return ids; - } - - /** @return a list of <code>FieldDescriptors</code> for fields defined in <script> tags. */ - public List<FieldDescriptor> getScriptFields() { - return scriptFields; - } - - /** @return a list of <code>MethodDescriptors</code> for methods defined in <script> tags. */ - public List<MethodDescriptor> getScriptMethods() { - return scriptMethods; - } - - public void setInterfaces(String[] interfaces) { - this.interfaces = interfaces; - } - - public void clear() { - ids.clear(); - scriptFields.clear(); - scriptMethods.clear(); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/UnsupportedAttributeException.java b/jaxx-compiler/src/main/java/jaxx/compiler/UnsupportedAttributeException.java deleted file mode 100644 index 3799bc2..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/UnsupportedAttributeException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler; - -/** - * Thrown by <code>TagHandler</code> when an unsupported attribute is encountered. - * - * @see jaxx.compiler.tags.TagHandler - */ -public class UnsupportedAttributeException extends CompilerException { - - private static final long serialVersionUID = -6919583037172920343L; - - /** Creates a new <code>UnsupportedAttributeException</code>. */ - public UnsupportedAttributeException() { - } - - /** - * Creates a new <code>UnsupportedAttributeException</code> with the specified detail message. - * - * @param msg the exception's detail message - */ - public UnsupportedAttributeException(String msg) { - super(msg); - } - - /** - * Creates a new <code>UnsupportedAttributeException</code> with the specified cause. - * - * @param initCause the exception's initCause - */ - public UnsupportedAttributeException(Throwable initCause) { - super(initCause); - } - - /** - * Creates a new <code>UnsupportedAttributeException</code> with the specified detail message and cause. - * - * @param msg the exception's detail message - * @param initCause the exception's initCause - */ - public UnsupportedAttributeException(String msg, Throwable initCause) { - super(msg, initCause); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/UnsupportedTagException.java b/jaxx-compiler/src/main/java/jaxx/compiler/UnsupportedTagException.java deleted file mode 100644 index 7287b76..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/UnsupportedTagException.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler; - -/** Thrown by the compiler when an unregistered tag is encountered. */ -public class UnsupportedTagException extends CompilerException { - private static final long serialVersionUID = 3199732135804426699L; - - /** Creates a new <code>UnsupportedTagException</code>. */ - public UnsupportedTagException() { - } - - - /** - * Creates a new <code>UnsupportedTagException</code> with the specified detail message. - * - * @param msg the exception's detail message - */ - public UnsupportedTagException(String msg) { - super(msg); - } - - - /** - * Creates a new <code>UnsupportedTagException</code> with the specified cause. - * - * @param initCause the exception's initCause - */ - public UnsupportedTagException(Throwable initCause) { - super(initCause); - } - - - /** - * Creates a new <code>UnsupportedTagException</code> with the specified detail message and cause. - * - * @param msg the exception's detail message - * @param initCause the exception's initCause - */ - public UnsupportedTagException(String msg, Throwable initCause) { - super(msg, initCause); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/beans/BeanInfoUtil.java b/jaxx-compiler/src/main/java/jaxx/compiler/beans/BeanInfoUtil.java deleted file mode 100644 index c674be5..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/beans/BeanInfoUtil.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.beans; - -import java.beans.Introspector; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** @author Tony Chemit - chemit@codelutin.com */ -public class BeanInfoUtil { - - public static String[] originalBeanInfoSearchPath; - - public static void addJaxxBeanInfoPath(String... packageNames) { - - String[] searchPath = Introspector.getBeanInfoSearchPath(); - if (originalBeanInfoSearchPath == null) { - originalBeanInfoSearchPath = searchPath; - } - List<String> listSearchPath = new ArrayList<>(Arrays.asList(searchPath)); - for (String packageName : packageNames) { - if (!listSearchPath.contains(packageName)) { - listSearchPath.add(packageName); - } - } - - Introspector.setBeanInfoSearchPath(listSearchPath.toArray(new String[listSearchPath.size()])); - } - - public static void reset() { - if (originalBeanInfoSearchPath != null) { - Introspector.setBeanInfoSearchPath(originalBeanInfoSearchPath); - originalBeanInfoSearchPath = null; - } - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXBeanDescriptor.java b/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXBeanDescriptor.java deleted file mode 100644 index abfc829..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXBeanDescriptor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.beans; - -import jaxx.compiler.reflect.ClassDescriptor; - -/** - * Mirrors the class <code>java.beans.BeanDescriptor</code>. JAXX uses its own introspector rather than the built-in - * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, - * not just <code>java.lang.Class</code>. - */ -public class JAXXBeanDescriptor extends JAXXFeatureDescriptor { - - public JAXXBeanDescriptor(ClassDescriptor beanClass) { - super(beanClass, beanClass.getName()); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXBeanInfo.java b/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXBeanInfo.java deleted file mode 100644 index 0023a01..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXBeanInfo.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.beans; - -import jaxx.compiler.reflect.ClassDescriptor; - -/** - * Mirrors the class <code>java.beans.BeanInfo</code>. JAXX uses its own introspector rather than the built-in - * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, - * not just <code>java.lang.Class</code>. - */ -public class JAXXBeanInfo { - - private JAXXBeanDescriptor beanDescriptor; - - private JAXXPropertyDescriptor[] propertyDescriptors; - - private JAXXEventSetDescriptor[] eventSetDescriptors; - - public JAXXBeanInfo(JAXXBeanDescriptor beanDescriptor, - JAXXPropertyDescriptor[] propertyDescriptors, - JAXXEventSetDescriptor[] eventSetDescriptors) { - this.beanDescriptor = beanDescriptor; - this.propertyDescriptors = propertyDescriptors; - this.eventSetDescriptors = eventSetDescriptors; - } - - public JAXXBeanDescriptor getJAXXBeanDescriptor() { - return beanDescriptor; - } - - public JAXXPropertyDescriptor[] getJAXXPropertyDescriptors() { - return propertyDescriptors; - } - - public JAXXEventSetDescriptor[] getJAXXEventSetDescriptors() { - return eventSetDescriptors; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXEventSetDescriptor.java b/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXEventSetDescriptor.java deleted file mode 100644 index a76be0f..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXEventSetDescriptor.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.beans; - -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.MethodDescriptor; - -/** - * Mirrors the class <code>java.beans.EventSetDescriptor</code>. JAXX uses its own introspector rather than the built-in - * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, - * not just <code>java.lang.Class</code>. - */ -public class JAXXEventSetDescriptor extends JAXXFeatureDescriptor { - - private MethodDescriptor addListenerMethod; - - private MethodDescriptor removeListenerMethod; - - private MethodDescriptor[] listenerMethods; - - public JAXXEventSetDescriptor(ClassDescriptor classDescriptor, String name, MethodDescriptor addListenerMethod, - MethodDescriptor removeListenerMethod, MethodDescriptor[] listenerMethods) { - super(classDescriptor, name); - this.addListenerMethod = addListenerMethod; - this.removeListenerMethod = removeListenerMethod; - this.listenerMethods = listenerMethods; - } - - public MethodDescriptor getAddListenerMethod() { - return addListenerMethod; - } - - public MethodDescriptor getRemoveListenerMethod() { - return removeListenerMethod; - } - - public MethodDescriptor[] getListenerMethods() { - return listenerMethods; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXFeatureDescriptor.java b/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXFeatureDescriptor.java deleted file mode 100644 index 873bf22..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXFeatureDescriptor.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.beans; - -import jaxx.compiler.reflect.ClassDescriptor; - -import java.util.HashMap; -import java.util.Map; - -/** - * Mirrors the class <code>java.beans.FeatureDescriptor</code>. JAXX uses its own introspector rather than the built-in - * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, - * not just <code>java.lang.Class</code>. - */ -public class JAXXFeatureDescriptor { - - private String name; - - private Map<String, Object> values; - - private ClassDescriptor classDescriptor; - - JAXXFeatureDescriptor(ClassDescriptor classDescriptor, String name) { - if (name == null || classDescriptor == null) { - throw new NullPointerException(); - } - this.name = name; - this.classDescriptor = classDescriptor; - } - - public String getName() { - return name; - } - - public ClassDescriptor getClassDescriptor() { - return classDescriptor; - } - - public Object getValue(String key) { - return values != null ? values.get(key) : null; - } - - public void setValue(String key, Object value) { - if (values == null) { - values = new HashMap<>(); - } - values.put(key, value); - } - - public static String capitalize(String name) { - if (name.length() == 0) { - return name; - } - return Character.toUpperCase(name.charAt(0)) + name.substring(1); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXIntrospector.java b/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXIntrospector.java deleted file mode 100644 index c7634aa..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXIntrospector.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.beans; - -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.reflect.MethodDescriptor; - -import java.beans.BeanDescriptor; -import java.beans.BeanInfo; -import java.beans.Introspector; -import java.beans.PropertyChangeListener; -import java.beans.PropertyDescriptor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Enumeration; -import java.util.EventListener; -import java.util.HashMap; -import java.util.Map; - -/** - * Performs introspection on a <code>ClassDescriptor</code>. Ideally, I could just have copied Sun's Introspector - * and changed a few things, but the licensing terms are incompatible. This implementation is incomplete -- it only - * bothers to report info that JAXX actually checks. It also relaxes some of Introspector's rules a bit, but I - * don't believe it results in any meaningful incompatibilities. - * - * JAXX uses its own introspector rather than the built-in - * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, - * not just <code>java.lang.Class</code>. - */ -public class JAXXIntrospector { - - private ClassDescriptor classDescriptor; - - private Map<String, JAXXPropertyDescriptor> propertyDescriptors = new HashMap<>(); - - private Map<String, JAXXEventSetDescriptor> eventSetDescriptors = new HashMap<>(); - - private JAXXIntrospector(ClassDescriptor classDescriptor) { - this.classDescriptor = classDescriptor; - } - - /** - * Returns the <code>JAXXBeanInfo</code> for a given class. - * - * @param classDescriptor the class to introspect - * @return the <code>JAXXBeanInfo</code> for the bean class - */ - public static JAXXBeanInfo getJAXXBeanInfo(ClassDescriptor classDescriptor) { - JAXXIntrospector introspector = new JAXXIntrospector(classDescriptor); - return introspector.createBeanInfo(); - } - - private JAXXBeanInfo createBeanInfo() { - ClassDescriptor explicitInfoClass = classDescriptor; - BeanInfo explicitBeanInfo = null; - while (explicitInfoClass != null) { - explicitBeanInfo = getExplicitBeanInfo(explicitInfoClass); - if (explicitBeanInfo != null) { - break; - } - explicitInfoClass = explicitInfoClass.getSuperclass(); - } - - if (explicitBeanInfo != null) { - PropertyDescriptor[] explicitProperties = explicitBeanInfo.getPropertyDescriptors(); - for (PropertyDescriptor explicitProperty : explicitProperties) { - Class<?> type = explicitProperty.getPropertyType(); - Method readMethod = explicitProperty.getReadMethod(); - Method writeMethod = explicitProperty.getWriteMethod(); - try { - ClassDescriptor typeDescriptor = ClassDescriptorHelper.getClassDescriptor(type.getName(), type.getClassLoader()); - JAXXPropertyDescriptor propertyDescriptor = new JAXXPropertyDescriptor(classDescriptor, explicitProperty.getName(), - readMethod != null ? classDescriptor.getMethodDescriptor(readMethod.getName()) : null, - writeMethod != null ? classDescriptor.getMethodDescriptor(writeMethod.getName(), typeDescriptor) : null); - propertyDescriptor.setBound(explicitProperty.isBound()); - Enumeration<String> attributeNames = explicitProperty.attributeNames(); - while (attributeNames.hasMoreElements()) { - String name = attributeNames.nextElement(); - propertyDescriptor.setValue(name, explicitProperty.getValue(name)); - } - propertyDescriptors.put(propertyDescriptor.getName(), propertyDescriptor); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Internal error: Could not find ClassDescriptor corresponding to Java " + type, e); - } catch (NoSuchMethodException e) { - throw new RuntimeException("Internal error: Could not find expected MethodDescriptor in " + classDescriptor, e); - } - } - } - - // if the class broadcasts PropertyChangeEvent, assume all properties are bound (java.beans.Introspector - // does the same) - boolean propertyChangeSource; - try { - classDescriptor.getMethodDescriptor("addPropertyChangeListener", ClassDescriptorHelper.getClassDescriptor(PropertyChangeListener.class)); - propertyChangeSource = true; - } catch (NoSuchMethodException e) { - propertyChangeSource = false; - } - - MethodDescriptor[] methods = classDescriptor.getMethodDescriptors(); - for (MethodDescriptor method : methods) { - String name = method.getName(); - if (name.startsWith("get") && name.length() > 3 && Character.isUpperCase(name.charAt(3)) && method.getParameterTypes().length == 0) { - String propertyName = Introspector.decapitalize(name.substring(3)); - if (!propertyDescriptors.containsKey(propertyName)) { - propertyDescriptors.put(propertyName, new JAXXPropertyDescriptor(classDescriptor, propertyName, method, null, propertyChangeSource)); - } - } else if (name.startsWith("is") && name.length() > 2 && Character.isUpperCase(name.charAt(2)) && method.getParameterTypes().length == 0) { - String propertyName = Introspector.decapitalize(name.substring(2)); - if (!propertyDescriptors.containsKey(propertyName)) { - propertyDescriptors.put(propertyName, new JAXXPropertyDescriptor(classDescriptor, propertyName, method, null, propertyChangeSource)); - } - } else if (name.startsWith("set") && name.length() > 3 && Character.isUpperCase(name.charAt(3)) && method.getParameterTypes().length == 1) { - String propertyName = Introspector.decapitalize(name.substring(3)); - if (!propertyDescriptors.containsKey(propertyName)) { - propertyDescriptors.put(propertyName, new JAXXPropertyDescriptor(classDescriptor, propertyName, null, method, propertyChangeSource)); - } - } else if (name.startsWith("add") && name.length() > 3 && Character.isUpperCase(name.charAt(3))) { - ClassDescriptor[] parameters = method.getParameterTypes(); - if (parameters.length != 1 || !ClassDescriptorHelper.getClassDescriptor(EventListener.class).isAssignableFrom(parameters[0])) { - continue; // not an event listener method - } - try { - String eventSetName = method.getName().substring(3); - MethodDescriptor remove = classDescriptor.getMethodDescriptor("remove" + eventSetName, parameters); - eventSetDescriptors.put(eventSetName, new JAXXEventSetDescriptor(classDescriptor, eventSetName, method, remove, parameters[0].getMethodDescriptors())); - } catch (NoSuchMethodException e) { - // no matching remove method, not a valid event - } - } - } - - JAXXBeanDescriptor beanDescriptor = new JAXXBeanDescriptor(classDescriptor); - if (explicitBeanInfo != null) { - BeanDescriptor explicitBeanDescriptor = explicitBeanInfo.getBeanDescriptor(); - if (explicitBeanDescriptor != null) { - Enumeration<String> attributeNames = - explicitBeanDescriptor.attributeNames(); - while (attributeNames.hasMoreElements()) { - String name = attributeNames.nextElement(); - beanDescriptor.setValue(name, explicitBeanDescriptor.getValue(name)); - } - } - } - - return new JAXXBeanInfo(beanDescriptor, - propertyDescriptors.values().toArray(new JAXXPropertyDescriptor[propertyDescriptors.size()]), - eventSetDescriptors.values().toArray(new JAXXEventSetDescriptor[eventSetDescriptors.size()])); - } - - private static BeanInfo getExplicitBeanInfo(ClassDescriptor classDescriptor) { - try { - Class<?> beanClass = Class.forName(classDescriptor.getName(), true, classDescriptor.getClassLoader()); // see if there is a class by that name in this package - Method findExplicitBeanInfo = Introspector.class.getDeclaredMethod("findExplicitBeanInfo", new Class[]{Class.class}); - findExplicitBeanInfo.setAccessible(true); - return (BeanInfo) findExplicitBeanInfo.invoke(null, beanClass); - } catch (ClassNotFoundException e) { - return null; // happens for uncompiled classes - } catch (NoClassDefFoundError e) { - return null; // wrong case, etc. - } catch (NoSuchMethodException e) { - throw new RuntimeException("Error: could not find method 'findExplicitBeanInfo' in java.beans.Introspector. You are most likely running a version of Java against which JAXX has not been tested."); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXPropertyDescriptor.java b/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXPropertyDescriptor.java deleted file mode 100644 index a632ba2..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXPropertyDescriptor.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.beans; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.MethodDescriptor; - -/** - * Mirrors the class <code>java.beans.PropertyDescriptor</code>. JAXX uses its own introspector rather than the built-in - * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, - * not just <code>java.lang.Class</code>. - */ -public class JAXXPropertyDescriptor extends JAXXFeatureDescriptor { - - private ClassDescriptor propertyType; - - private MethodDescriptor readMethod; - - private MethodDescriptor writeMethod; - - private boolean bound; - - public JAXXPropertyDescriptor(ClassDescriptor classDescriptor, String propertyName) { - this(classDescriptor, propertyName, null, null); - } - - public JAXXPropertyDescriptor(ClassDescriptor classDescriptor, String propertyName, - MethodDescriptor readMethod, MethodDescriptor writeMethod) { - this(classDescriptor, propertyName, readMethod, writeMethod, false); - } - - public JAXXPropertyDescriptor(ClassDescriptor classDescriptor, String propertyName, - MethodDescriptor readMethod, MethodDescriptor writeMethod, - boolean bound) { - super(classDescriptor, propertyName); - this.readMethod = readMethod; - this.writeMethod = writeMethod; - this.bound = bound; - } - - public MethodDescriptor getReadMethodDescriptor() { - if (readMethod == null) { - try { - readMethod = getClassDescriptor().getMethodDescriptor("get" + capitalize(getName())); - } catch (NoSuchMethodException e) { - try { - readMethod = getClassDescriptor().getMethodDescriptor("is" + capitalize(getName())); - } catch (NoSuchMethodException e2) { - } - } - } - return readMethod; - } - - public MethodDescriptor getWriteMethodDescriptor() { - if (writeMethod == null) { - try { - String methodName = "set" + capitalize(getName()); - MethodDescriptor read = getReadMethodDescriptor(); - if (read != null) { - writeMethod = getClassDescriptor().getMethodDescriptor(methodName, read.getReturnType()); - } else { - throw new CompilerException("Internal error: requesting 'set' method for property of unknown type: '" + getName() + "' (in " + getClassDescriptor() + ")"); - } - } catch (NoSuchMethodException e) { - } - } - return writeMethod; - } - - public ClassDescriptor getPropertyType() { - if (propertyType == null) { - MethodDescriptor read = getReadMethodDescriptor(); - if (read != null) { - propertyType = read.getReturnType(); - } else { - MethodDescriptor write = getWriteMethodDescriptor(); - propertyType = write.getParameterTypes()[0]; - } - } - return propertyType; - } - - public boolean isBound() { - return bound; - } - - public void setBound(boolean bound) { - this.bound = bound; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java b/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java deleted file mode 100644 index e9d33ce..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.binding; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.java.JavaFileGenerator; -import jaxx.compiler.java.JavaMethod; -import jaxx.compiler.types.TypeManager; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -/** - * Represents a data binding in a JAXX file. <code>DataBinding</code> uses - * {@link DataSource} to track changes to a source expression and update - * the destination. - */ -public class DataBinding { - - /** Logger. */ - protected static final Log log = LogFactory.getLog(DataBinding.class); - - /** Id of the data binding */ - private String id; - - /** Real Id of the data binding (can be suffix by a number for css binding to avoid collisions) */ - private String realId; - - /** Constant id build from the {@link #realId} and used instead of {@link #realId} in generated code */ - protected String constantId; - - /** source of the data binding */ - private String source; - - /** - * A Java snippet which will cause the destination property to be updated with the current value of - * the binding. - */ - private String assignment; - - /** A internal flag to */ - private boolean quickNoDependencies; - - /** Compiled data source */ - protected DataSource dataSource; - - /** code to add to processDataBinding (null if no binding) */ - protected String processDataBinding; - - /** code to register the databinding (null if no binding) */ - protected String initDataBinding; - - /** Extra method to add to the binding */ - protected final List<JavaMethod> methods = new ArrayList<>(); - - /** internal state passed to {@code true} when {@link #compile(JAXXCompiler)} method is invoked */ - private boolean compiled; - - /** - * Creates a new data binding. - * - * @param id the data binding destination in the form <code>id.propertyName</code> - * @param source the Java source code for the data binding expression - * @param assignment Java snippet which will cause the destination property to be updated with the current value of the binding - * @param quickNoDependencies internal flag to not treate process databinding in not a real binding - */ - public DataBinding(String id, String source, String assignment, boolean quickNoDependencies) { - this.id = id; - this.source = source; - this.assignment = assignment; - this.quickNoDependencies = quickNoDependencies; - if (log.isDebugEnabled()) { - log.debug("id=" + id + " assignement=" + assignment + " source=" + source + " quickNoDependencies=" + quickNoDependencies); - } - } - - public String getAssignment() { - return assignment; - } - - public String getSource() { - return source; - } - - public boolean isQuickNoDependencies() { - return quickNoDependencies; - } - - public String getProcessDataBinding() { - return processDataBinding; - } - - public String getInitDataBinding() { - return initDataBinding; - } - - public DataListener[] getTrackers() { - return dataSource == null ? null : dataSource.getTrackers(); - } - - public String getRealId() { - return realId; - } - - public String getConstantId() { - return constantId; - } - - public List<JavaMethod> getMethods() { - return methods; - } - - @Override - public String toString() { - ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); - b.append("id", id); - b.append("source", source.trim()); - b.append("assignement", assignment.trim()); - b.append("quickNoDependencies", quickNoDependencies); - if (compiled) { - b.append("realdId", realId); - b.append("constantId", getConstantId()); - b.append("objectCode", dataSource.getObjectCode()); - DataListener[] trackers = dataSource.getTrackers(); - if (trackers.length > 0) { - b.append("source:trackers", trackers.length); - for (DataListener d : trackers) { - b.append("source:tracker", d); - } - } - } - return b.toString(); - } - - /** - * Compiles the data binding expression. This method calls methods in - * <code>JAXXCompiler</code> to add the Java code that performs the data - * binding setup. - * - * @param compiler compiler which includes the data binding - * @return {@code true} if the expression has dependencies, {@code false} otherwise - * @throws CompilerException if a compilation error occurs - */ - public boolean compile(JAXXCompiler compiler) throws CompilerException { - - if (compiled) { - throw new IllegalStateException(this + " has already been compiled"); - } - - DataBindingHelper bindingHelper = compiler.getBindingHelper(); - - // obtain a safe id - realId = bindingHelper.getSafeId(id.trim()); - - // compute the constant id of the binding - constantId = TypeManager.convertVariableNameToConstantName("binding_" + realId); - - dataSource = new DataSource(realId, constantId, getSource(), compiler, methods); - - // compile binding - - boolean binding = dataSource.compile(); - - if (!binding) { - - // free the generated id - - bindingHelper.revertSafeId(id.trim()); - } - - // was compiled - compiled = true; - - if (dataSource.showLog()) { - if (binding) { - log.info("detect a databinding : " + this); - } else { - log.info("reject a databinding : " + getSource()); - } - } - - // compute initDataBinding code - - initDataBinding = getInitDataBindingCode(compiler, dataSource, binding); - - // compute processDataBinding code - - processDataBinding = getProcessDataBindingCode(compiler, dataSource, binding); - - Set<String> ids = dataSource.getOverrideIds(); - - if (binding && ids != null && !ids.isEmpty()) { - - // there is some overrides, check trackers - DataListener[] listeners = dataSource.getTrackers(); - for (DataListener listener : listeners) { - String code = listener.getAddListenerCode(); - String newCode = replaceOverrides(compiler, ids, code); - if (code.equals(newCode)) { - listener.addListenerCode = newCode; - if (dataSource.showLog()) { - log.info("Replace overrides [" + code + "] --> [" + newCode + "]"); - } - } - code = listener.getRemoveListenerCode(); - newCode = replaceOverrides(compiler, ids, code); - if (code.equals(newCode)) { - listener.removeListenerCode = newCode; - if (dataSource.showLog()) { - log.info("Replace overrides [" + code + "] --> [" + newCode + "]"); - } - } - } - } - return binding; - } - - protected String getInitDataBindingCode(JAXXCompiler compiler, DataSource dataSource, boolean isBinding) { - String eol = JAXXCompiler.getLineSeparator(); - if (isBinding) { - return null; - } - if (isQuickNoDependencies()) { - // layout is specially handled early in the chain - if (!id.endsWith(".layout")) { - return getAssignment() + eol; - } - } - return null; - } - - protected String getProcessDataBindingCode(JAXXCompiler compiler, DataSource dataSource, boolean isBinding) { - if (!isBinding) { - // no binding = no process code - return null; - } - String eol = JAXXCompiler.getLineSeparator(); - StringBuilder buffer = new StringBuilder(); - - String objectCode = dataSource.getObjectCode(); - - Set<String> overrideIds = dataSource.getOverrideIds(); - // no need to test objectCode not null if on root object - boolean needTest = objectCode != null && !objectCode.trim().isEmpty() && !compiler.getRootObject().getId().equals(objectCode + " != null"); - if (needTest) { - - objectCode = replaceOverrides(compiler, overrideIds, objectCode); - - buffer.append("if (").append(objectCode).append(") {").append(eol); - } - String assignment = getAssignment(compiler, overrideIds); - buffer.append(JavaFileGenerator.indent(assignment, needTest ? 4 : 0, false, eol)); - if (needTest) { - buffer.append(eol).append("}"); - } - return buffer.toString(); - } - - protected String getAssignment(JAXXCompiler compiler, Set<String> overrides) { - String s = getAssignment(); - - s = replaceOverrides(compiler, overrides, s); - - return s; - } - - protected String replaceOverrides(JAXXCompiler compiler, Set<String> overrides, String code) { - if (overrides != null && !overrides.isEmpty()) { - String tmp = code; - for (String override : overrides) { - CompiledObject o = compiler.getCompiledObject(override); - tmp = tmp.replaceAll(override + "\\.", o.getGetterName() + "()."); -// tmp = tmp.replaceFirst(override + ".", o.getJavaCode() + "."); - } - if (dataSource.showLog()) { - log.info("Assignment with overrides [" + code + "] to [" + tmp + "]"); - } - code = tmp; - } - return code; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBindingHelper.java b/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBindingHelper.java deleted file mode 100644 index bb6bb48..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBindingHelper.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.binding; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Helper to be used by compiler to treate data bindings. - * - * Note : The code in this class was previously directly in JAXXCompiler, now prefer have a separate - * class to make {@link JAXXCompiler} more simple and clear. - * - * Created: 27 nov. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.0 - */ -public class DataBindingHelper { - - /** To debug binding without any log interference */ - public static boolean SHOW_LOG; - - /** left brace matcher */ - protected static final Matcher leftBraceMatcher = Pattern.compile("^(\\{)|[^\\\\](\\{)").matcher(""); - - /** right brace matcher */ - protected static final Matcher rightBraceMatcher = Pattern.compile("^(\\})|[^\\\\](\\})").matcher(""); - - /** - * Registred data binding for the compiler, then after the invocation of method {@link #finalizeBindings()} - * only the real data bindings, the simple bindings will be moved to {@link #simpleBindings}. - */ - protected final List<DataBinding> dataBindings = new ArrayList<>(); - - /** Simpel bindings for the compiler */ - protected final List<DataBinding> simpleBindings = new ArrayList<>(); - - /** Associated compiler */ - protected final JAXXCompiler compiler; - - /** Counter by unsafe type */ - protected final Map<String, Integer> autoUnsafeGenIds = new TreeMap<>(); - - public DataBindingHelper(JAXXCompiler compiler) { - this.compiler = compiler; - } - - /** - * Examine an attribute value for data binding expressions. Returns a 'cooked' expression which - * can be used to determine the resulting value. It is expected that this expression will be used - * as the source expression in a call to {@link #registerDataBinding}. - * If the attribute value does not invoke data binding, this method returns <code>null</code> - * - * @param stringValue the string value of the property from the XML - * @return a processed version of the expression - * @throws CompilerException ? - */ - public static String processDataBindings(String stringValue) throws CompilerException { - int pos = getNextLeftBrace(stringValue, 0); - if (pos != -1) { - StringBuilder expression = new StringBuilder(); - int lastPos = 0; - while (pos != -1 && pos < stringValue.length()) { - if (pos > lastPos) { - if (expression.length() > 0) { - expression.append(" + "); - } - expression.append('"'); - expression.append(JAXXCompiler.escapeJavaString(stringValue.substring(lastPos, pos))); - expression.append('"'); - } - boolean multi = expression.length() > 0; - if (multi) { - expression.append(" + "); - expression.append('('); - } - int pos2 = getNextRightBrace(stringValue, pos + 1); - if (pos2 == -1) { - throw new CompilerException("unmatched '{' in expression: " + stringValue); - } - expression.append(stringValue.substring(pos + 1, pos2)); - if (multi) { - expression.append(')'); - } - pos2++; - if (pos2 < stringValue.length()) { - pos = getNextLeftBrace(stringValue, pos2); - lastPos = pos2; - } else { - pos = stringValue.length(); - lastPos = pos; - } - } - if (lastPos < stringValue.length()) { - if (expression.length() > 0) { - expression.append(" + "); - } - expression.append('"'); - expression.append(JAXXCompiler.escapeJavaString(stringValue.substring(lastPos))); - expression.append('"'); - } - //TC-20091027 : developper must write extact databinding - // the fact of adding the String boxed for String type binding is not - // a good thing, since it add one more call to process in binding - // and add nothing special more ? -// return type == ClassDescriptorHelper.getClassDescriptor(String.class) ? "String.valueOf(" + expression + ")" : expression.toString(); - return expression.toString(); - } - return null; - } - - public DataBinding[] getDataBindings() { - return dataBindings.toArray(new DataBinding[dataBindings.size()]); - } - - public DataBinding[] getSimpleBindings() { - return simpleBindings.toArray(new DataBinding[simpleBindings.size()]); - } - - public void registerDataBinding(String id, String binding, String assignment) { - binding = compiler.checkJavaCode(binding); - registerDataBinding(new DataBinding(id, binding, assignment, true)); - } - - public void registerDataBinding(DataBinding binding) { - dataBindings.add(binding); - } - - public void clear() { - simpleBindings.clear(); - dataBindings.clear(); - autoUnsafeGenIds.clear(); - } - - /** - * Obtain the next safe id for the given binding id. - * - * With css, we can obtain the same binding id, so we must - * check for unicity each time we want a new binding id. - * - * If an id is already taken, we suffix by {@code _XXX} until - * found a free id. - * - * @param id the id of the binding - * @return the safe id of the binding - */ - public String getSafeId(String id) { - - Integer integer = autoUnsafeGenIds.get(id); - String result = id; - if (integer == null) { - integer = 0; - } else { - result += "_" + integer; - } - autoUnsafeGenIds.put(id, ++integer); - return result; - } - - /** - * Revert a previous computed safe id. - * - * This is needed when a binding compiled is not an data binding, we want to free - * the safe id to avoid hole in numbers. - * - * @param id the original id to revert in counter. - */ - public void revertSafeId(String id) { - Integer integer = autoUnsafeGenIds.get(id); - if (integer != null) { - integer--; - if (integer > 0) { - autoUnsafeGenIds.put(id, integer); - } else { - autoUnsafeGenIds.remove(id); - } - } - } - - /** - * Compile all binding discovered previously. - * - * If a binding is not a dataBinding, then move it from the list {@link #dataBindings} to {@link #simpleBindings}. - */ - public void finalizeBindings() { - - for (Iterator<DataBinding> itr = dataBindings.iterator(); itr.hasNext(); ) { - DataBinding binding = itr.next(); - boolean isBinding = binding.compile(compiler); - if (!isBinding) { - // ce n'est pas un binding, on enregistre le code d'init (si il existe) - simpleBindings.add(binding); - // on supprime le faux binding - itr.remove(); - } - } - } - - protected static int getNextLeftBrace(String string, int pos) { - leftBraceMatcher.reset(string); - return leftBraceMatcher.find(pos) ? Math.max(leftBraceMatcher.start(1), leftBraceMatcher.start(2)) : -1; - } - - protected static int getNextRightBrace(String string, int pos) { - leftBraceMatcher.reset(string); - rightBraceMatcher.reset(string); - int openCount = 1; - int rightPos; - while (openCount > 0) { - pos++; - int leftPos = leftBraceMatcher.find(pos) ? - Math.max(leftBraceMatcher.start(1), leftBraceMatcher.start(2)) : - -1; - rightPos = rightBraceMatcher.find(pos) ? - Math.max(rightBraceMatcher.start(1), rightBraceMatcher.start(2)) : - -1; - assert leftPos == -1 || leftPos >= pos; - assert rightPos == -1 || rightPos >= pos; - if (leftPos != -1 && leftPos < rightPos) { - pos = leftPos; - openCount++; - } else if (rightPos != -1) { - pos = rightPos; - openCount--; - } else { - openCount = 0; - } - } - return pos; - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataListener.java b/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataListener.java deleted file mode 100644 index c5c0286..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataListener.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.binding; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -/** - * Created: 5 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - * - * Mise a jour: $Date$ par : - * $Author$ - */ -public class DataListener { - - /** - * Unique id of the data listener (should be something like objectId.propertyName - */ - protected final String symbol; - - /** - * the nullity test to do before to add or remove the listener - */ - protected final String objectCode; - - /** - * code of the add listener - */ - protected String addListenerCode; - - /** - * code of the remove listener - */ - protected String removeListenerCode; - - public DataListener(String symbol, - String objectCode, - String addListenerCode, - String removeListenerCode) { - this.symbol = symbol; - this.objectCode = objectCode; - this.addListenerCode = addListenerCode; - this.removeListenerCode = removeListenerCode; - } - - public String getSymbol() { - return symbol; - } - - public String getObjectCode() { - return objectCode; - } - - public String getAddListenerCode() { - return addListenerCode; - } - - public String getRemoveListenerCode() { - return removeListenerCode; - } - - @Override - public String toString() { - ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); - b.append("symbol", symbol); - b.append("objectCode", objectCode); - b.append("addListenerCode", addListenerCode.trim()); - b.append("removeListenerCode", removeListenerCode.trim()); - return b.toString(); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java b/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java deleted file mode 100644 index a43a6b8..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java +++ /dev/null @@ -1,882 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.binding; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.UnsupportedAttributeException; -import jaxx.compiler.finalizers.JAXXCompilerFinalizer; -import jaxx.compiler.java.JavaElementFactory; -import jaxx.compiler.java.JavaFileGenerator; -import jaxx.compiler.java.JavaMethod; -import jaxx.compiler.java.parser.JavaParser; -import jaxx.compiler.java.parser.JavaParserConstants; -import jaxx.compiler.java.parser.JavaParserTreeConstants; -import jaxx.compiler.java.parser.SimpleNode; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.reflect.FieldDescriptor; -import jaxx.compiler.reflect.MethodDescriptor; -import jaxx.compiler.tags.DefaultObjectHandler; -import jaxx.compiler.tags.TagManager; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.JAXXUtil; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.beans.Introspector; -import java.io.StringReader; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Represents a Java expression which fires a <code>PropertyChangeEvent</code> when it can be - * determined that its value may have changed. Events are fired on a "best effort" basis, and events - * may either be fired too often (the value has not actually changed) or not often enough (the value - * changed but no event was fired). - */ -public class DataSource { - - /** Logger */ - protected static final Log log = LogFactory.getLog(DataSource.class); - - /** type attached to "null" constants in parsed expressions */ - private class NULL { - } - - /** id of data source */ - private final String id; - - /** Constant id */ - protected final String constantId; - - /** The Java source code for the expression. */ - private final String source; - - /** The current <code>JAXXCompiler</code>. */ - private final JAXXCompiler compiler; - - /** List of detected tracker (if none found, it is not a data binding) */ - private final List<DataListener> trackers; - - /** the delegate of property to be required */ - private String objectCode; - - protected final List<JavaMethod> methods; - - /** - * Creates a new data source. After creating a <code>DataSource</code>, use {@link #compile()} - * to cause it to function at runtime. - * - * @param id the DataSource's id - * @param constantId the DataSource constant id - * @param source the Java source code for the data source expression - * @param compiler the current <code>JAXXCompiler</code> - * @param methods where to store extra method to add to binding - */ - public DataSource(String id, - String constantId, - String source, - JAXXCompiler compiler, - List<JavaMethod> methods) { - this.id = id; - this.constantId = constantId; - this.source = source; - this.compiler = compiler; - this.methods = methods; - trackers = new ArrayList<>(); - } - - public String getObjectCode() { - return objectCode; - } - - public DataListener[] getTrackers() { - return trackers.toArray(new DataListener[trackers.size()]); - } - - @Override - public String toString() { - ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); - b.append("source:id", id); - b.append("source:source", source); - b.append("source:objectCode", getObjectCode()); - if (!trackers.isEmpty()) { - b.append("source:trackers", trackers.size()); - for (DataListener d : trackers) { - b.append("source:tracker", d); - } - } - return b.toString(); - } - - public boolean showLog() { -// return DataBindingHelper.SHOW_LOG || log.isDebugEnabled(); - return DataBindingHelper.SHOW_LOG; - } - - /** - * Compiles the data source expression and listener. This method calls methods in <code>JAXXCompiler</code> - * to add the Java code that performs the data source setup. Adding listeners to <code>DataSource</code> is - * slightly more complicated than with ordinary classes, because <code>DataSource</code> only exists at compile - * time. You must pass in a Java expression which evaluates to a <code>PropertyChangeListener</code>; this - * expression will be compiled and evaluated at runtime to yield the <code>DataSource's</code> listener. - * - * @return <code>true</code> if the expression has dependencies, <code>false</code> otherwise - * @throws CompilerException if a compilation error occurs - * @throws IllegalStateException if data source was already compiled - */ - protected boolean compile() throws CompilerException, IllegalStateException { - - if (showLog()) { - log.info("======= Start compile of " + source); - } - JavaParser p = new JavaParser(new StringReader(source)); - - // detect all expressions to treate - Map<SimpleNode, List<SimpleNode>> expressions = new LinkedHashMap<>(); - Map<SimpleNode, List<SimpleNode>> castsExpressions = new LinkedHashMap<>(); - List<SimpleNode> literalExpressions = new ArrayList<>(); - while (!p.Line()) { - SimpleNode node = p.popNode(); - if (log.isTraceEnabled()) { - log.trace("will scan node " + node.getText()); - } - JavaParserUtil.getExpressions(node, expressions, literalExpressions, castsExpressions); - } - - // remove literal expressions - - JavaParserUtil.removeLiteralExpressions(expressions, literalExpressions); - literalExpressions.clear(); - - // remove expressions with dependencies - - JavaParserUtil.removeNoneStandaloneExpressions(expressions, castsExpressions); - - // scan accepted expressions to detect dependencies and track listeners - - for (SimpleNode node : expressions.keySet()) { - if (showLog()) { - log.info("Will parse expression " + node.getText()); - } - scanNode(node); - } - - if (log.isDebugEnabled()) { - log.debug("trackers=" + trackers); - } - - boolean isBinding = !trackers.isEmpty(); - if (isBinding) { - - Set<String> result = JavaParserUtil.getRequired(expressions.keySet(), castsExpressions); - - if (result == null || result.isEmpty()) { - - // no requirements - - objectCode = ""; - } else { - - // build the fully test from requirements - - StringBuilder buffer = new StringBuilder(); - - Iterator<String> itr = result.iterator(); - - overrideIds = new HashSet<>(); - - String realSource = getJavaCode(itr.next()); - buffer.append(realSource).append(" != null"); - while (itr.hasNext()) { - realSource = getJavaCode(itr.next()); - buffer.append(" && ").append(realSource).append(" != null"); - } - objectCode = buffer.toString().trim(); - } - } - castsExpressions.clear(); - expressions.clear(); - return isBinding; - } - - private Set<String> overrideIds; - - private String getJavaCode(String s) { - CompiledObject o = compiler.getCompiledObject(s); - if (o != null && o.isOverride()) { - - if (showLog()) { - log.info("Use an override identifier : " + o.getJavaCode()); - } - - overrideIds.add(s); - } - return s; - } - - public Set<String> getOverrideIds() { - return overrideIds; - } - - /** - * Examines a node to identify any dependencies it contains. - * - * @param node node to scan - * @throws CompilerException ? - */ - private void scanNode(SimpleNode node) throws CompilerException { - if (node.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION || - node.getId() == JavaParserTreeConstants.JJTFIELDDECLARATION) { - return; - } - if (log.isTraceEnabled()) { - log.trace(node.getText()); - } - int count = node.jjtGetNumChildren(); - for (int i = 0; i < count; i++) { - scanNode(node.getChild(i)); - } - // determine node type - ClassDescriptor type = null; - if (node.jjtGetNumChildren() == 1) { - type = node.getChild(0).getJavaType(); - } - switch (node.getId()) { - case JavaParserTreeConstants.JJTCLASSORINTERFACETYPE: - type = ClassDescriptorHelper.getClassDescriptor(Class.class); - break; - case JavaParserTreeConstants.JJTPRIMARYEXPRESSION: - type = determineExpressionType(node); - if (log.isDebugEnabled()) { - log.debug("result of determineExpressionType for " + node.getText() + " = " + type); - } - break; - case JavaParserTreeConstants.JJTLITERAL: - type = determineLiteralType(node); - break; - case JavaParserTreeConstants.JJTCASTEXPRESSION: - type = TagManager.resolveClass(node.getChild(0).getText(), compiler); - break; - } - node.setJavaType(type); - } - - /** - * Adds type information to nodes where possible, and as a side effect adds event listeners to nodes which - * can be tracked. - * - * @param expression the node to scan - * @return the class descriptor of the return type or null - */ - private ClassDescriptor determineExpressionType(SimpleNode expression) { - assert expression.getId() == JavaParserTreeConstants.JJTPRIMARYEXPRESSION; - SimpleNode prefix = expression.getChild(0); - if (log.isDebugEnabled()) { - log.debug("for expression " + expression.getText() + " - prefix " + prefix + " - nb childrens of prefix: " + prefix.jjtGetNumChildren() + ", nb childrens of expression : " + expression.jjtGetNumChildren()); - } - - if (prefix.jjtGetNumChildren() == 1) { - int type = prefix.getChild(0).getId(); - if (type == JavaParserTreeConstants.JJTLITERAL || type == JavaParserTreeConstants.JJTEXPRESSION) { - prefix.setJavaType(prefix.getChild(0).getJavaType()); - } else if (type == JavaParserTreeConstants.JJTNAME && expression.jjtGetNumChildren() == 1) { - // name with no arguments after it - ClassDescriptor classDescriptor = scanCompoundSymbol(prefix.getText().trim(), compiler.getRootObject().getObjectClass(), false); - if (log.isTraceEnabled()) { - log.trace("scanCompoundSymbol result for node " + prefix.getText().trim() + " = " + classDescriptor); - } - prefix.setJavaType(classDescriptor); - } - } - - if (expression.jjtGetNumChildren() == 1) { - return prefix.getJavaType(); - } - - ClassDescriptor contextClass = prefix.getJavaType(); - if (contextClass == null) { - contextClass = compiler.getRootObject().getObjectClass(); - } - String lastNode = prefix.getText().trim(); - - for (int i = 1; i < expression.jjtGetNumChildren(); i++) { - SimpleNode suffix = expression.getChild(i); - if (suffix.jjtGetNumChildren() == 1 && suffix.getChild(0).getId() == JavaParserTreeConstants.JJTARGUMENTS) { - if (suffix.getChild(0).jjtGetNumChildren() == 0) { - // at the moment only no-argument methods are trackable - contextClass = scanCompoundSymbol(lastNode, contextClass, true); - if (log.isTraceEnabled()) { - log.trace("scanCompoundSymbol result for node " + lastNode + " = " + contextClass); - } - if (contextClass == null) { - return null; - } - int dotPos = lastNode.lastIndexOf("."); - String code = dotPos == -1 ? "" : lastNode.substring(0, dotPos); - for (int j = i - 2; j >= 0; j--) { - code = expression.getChild(j).getText() + code; - } - if (code.length() == 0) { - code = compiler.getRootObject().getJavaCode(); - } - String methodName = lastNode.substring(dotPos + 1).trim(); - if (log.isTraceEnabled()) { - log.trace("try to find type for method " + methodName + ", code : " + code); - } - try { - MethodDescriptor method = contextClass.getMethodDescriptor(methodName); - if (log.isDebugEnabled()) { - log.debug("Will trackMemberIfPossible from method " + method.getName() + " with objectCode = " + code); - } - trackMemberIfPossible(code, contextClass, method.getName(), true); - if (log.isTraceEnabled()) { - log.trace("method found = " + method); - } - return getMethodReturnType(contextClass, method); - } catch (NoSuchMethodException e) { - if (showLog()) { - log.info("Could not find method " + methodName + ", code : " + code + " on : " + contextClass); - if (log.isDebugEnabled()) { - for (MethodDescriptor descriptor : contextClass.getMethodDescriptors()) { - log.debug(" - " + Modifier.toString(descriptor.getModifiers()) + " " + descriptor.getName() + "(...) : " + descriptor.getReturnType()); - } - } - } - // happens for methods defined in the current JAXX file via scripts - String propertyName = null; - if (methodName.startsWith("is")) { - propertyName = Introspector.decapitalize(methodName.substring("is".length())); - } else if (methodName.startsWith("get")) { - propertyName = Introspector.decapitalize(methodName.substring("get".length())); - } - if (propertyName != null) { - //TC-20091026 use the getScriptMethod from compiler - MethodDescriptor newMethod = compiler.getScriptMethod(methodName); - if (newMethod != null) { - //TC-20091202 must suffix dependency by property, otherwise can not have two bindings - // on the same parent... - String bindingId = compiler.getRootObject().getId() + "." + propertyName; - if (log.isDebugEnabled()) { - log.debug("detect a dependency [" + bindingId + "] from a script method " + newMethod.getName() + ", will try to add a listener in method is part of javaBean ..."); - } - // check this is a javaBean - CompiledObject compiledObject = compiler.getObjects().get(propertyName); - if (compiledObject != null && compiledObject.isJavaBean()) { - String objectCode = null; - if (showLog()) { - log.info("Detect a dependency from compiled object [" + objectCode + "]a script method '" + newMethod.getName() + "' which reflect a javaBean property " + propertyName); - log.info("Try to add a listener [symbol:" + bindingId + ",objectCode:" + objectCode + "]"); - log.debug(">> lastnode = " + lastNode + "(), suffix = " + suffix.getText() + ", expression = " + expression.getText()); - } - addListener(bindingId, - objectCode, - "addPropertyChangeListener(\"" + propertyName + "\", this);" + JAXXCompiler.getLineSeparator(), - "removePropertyChangeListener(\"" + propertyName + "\", this);" + JAXXCompiler.getLineSeparator()); - } - contextClass = newMethod.getReturnType(); - } - } - } - } - } - lastNode = suffix.getText().trim(); - if (lastNode.startsWith(".")) { - lastNode = lastNode.substring(1); - } - } - - return null; - } - - private ClassDescriptor determineLiteralType(SimpleNode node) { - assert node.getId() == JavaParserTreeConstants.JJTLITERAL; - if (node.jjtGetNumChildren() == 1) { - int childId = node.getChild(0).getId(); - if (childId == JavaParserTreeConstants.JJTBOOLEANLITERAL) { - return ClassDescriptorHelper.getClassDescriptor(boolean.class); - } - if (childId == JavaParserTreeConstants.JJTNULLLITERAL) { - return ClassDescriptorHelper.getClassDescriptor(NULL.class); - } - throw new RuntimeException("Expected BooleanLiteral or NullLiteral, found " + JavaParserTreeConstants.jjtNodeName[childId]); - } - int nodeId = node.firstToken.kind; - switch (nodeId) { - case JavaParserConstants.INTEGER_LITERAL: - if (node.firstToken.image.toLowerCase().endsWith("l")) { - return ClassDescriptorHelper.getClassDescriptor(long.class); - } - return ClassDescriptorHelper.getClassDescriptor(int.class); - case JavaParserConstants.CHARACTER_LITERAL: - return ClassDescriptorHelper.getClassDescriptor(char.class); - case JavaParserConstants.FLOATING_POINT_LITERAL: - if (node.firstToken.image.toLowerCase().endsWith("f")) { - return ClassDescriptorHelper.getClassDescriptor(float.class); - } - return ClassDescriptorHelper.getClassDescriptor(double.class); - case JavaParserConstants.STRING_LITERAL: - return ClassDescriptorHelper.getClassDescriptor(String.class); - default: - throw new RuntimeException("Expected literal token, found " + JavaParserConstants.tokenImage[nodeId]); - } - } - - /** - * Scans through a compound symbol (foo.bar.baz) to identify and track all trackable pieces of it. - * - * @param symbol symbol to scan - * @param contextClass current class context - * @param isMethod flag to search a method - * @return the type of the symbol (or null if it could not be determined). - */ - private ClassDescriptor scanCompoundSymbol(String symbol, ClassDescriptor contextClass, boolean isMethod) { - String[] tokens = symbol.split("\\s*\\.\\s*"); - if (log.isDebugEnabled()) { - log.debug("for symbol " + symbol + ", contextClass " + contextClass + ", isMethod " + isMethod); - log.debug("tokens " + Arrays.toString(tokens)); - } - StringBuilder currentSymbol = new StringBuilder(); - StringBuilder tokensSeenSoFar = new StringBuilder(); - // if this ends up false, it means we weren't able to figure out - boolean accepted; - // which object the method is being invoked on - boolean recognizeClassNames = true; - for (int j = 0; j < tokens.length - (isMethod ? 1 : 0); j++) { - accepted = false; - - if (tokensSeenSoFar.length() > 0) { - tokensSeenSoFar.append('.'); - } - tokensSeenSoFar.append(tokens[j]); - if (currentSymbol.length() > 0) { - currentSymbol.append('.'); - } - currentSymbol.append(tokens[j]); - if (log.isTraceEnabled()) { - log.trace("try to find type for " + currentSymbol); - } - if (currentSymbol.indexOf(".") == -1) { - String memberName = currentSymbol.toString(); - CompiledObject object = compiler.getCompiledObject(memberName); - if (object != null) { - if (log.isTraceEnabled()) { - log.trace("detected an object " + object); - } - contextClass = object.getObjectClass(); - currentSymbol.setLength(0); - accepted = true; - recognizeClassNames = false; - } else { - try { - FieldDescriptor field = contextClass.getFieldDescriptor(memberName); - if (log.isDebugEnabled()) { - log.debug("Will trackMemberIfPossible from field " + field.getName() + " with objectCode = " + tokensSeenSoFar.toString()); - } - trackMemberIfPossible(tokensSeenSoFar.toString(), contextClass, field.getName(), false); - try { - contextClass = field.getType(); - } catch (Exception e) { - log.warn("could not find type for field " + field); - throw new NoSuchFieldException(e.getMessage()); - } - - currentSymbol.setLength(0); - accepted = true; - recognizeClassNames = false; - } catch (NoSuchFieldException e) { - if (j == 0 || j == 1 && tokens[0].equals(compiler.getRootObject().getId())) { - // still in root context - FieldDescriptor newField = compiler.getScriptField(memberName); - if (newField != null) { - contextClass = newField.getType(); - if (showLog()) { - log.info("Detect a dependency from a script field '" + newField + "'"); - log.info("Try to add a listenenr [symbol:" + tokensSeenSoFar.toString() + ",objectCode:" + null + "]"); - } - String eol = JAXXCompiler.getLineSeparator(); - addListener(tokensSeenSoFar.toString(), - null, - "addPropertyChangeListener(\"" + memberName + "\", this);" + eol, -// "addPropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + eol, - "removePropertyChangeListener(\"" + memberName + "\", this);" + eol); -// "removePropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + eol); - - assert contextClass != null : "script field '" + memberName + "' is defined, but has type null"; - currentSymbol.setLength(0); - accepted = true; - recognizeClassNames = false; - } - } - } - } - } - if (currentSymbol.length() > 0 && recognizeClassNames) { - if (log.isDebugEnabled()) { - log.debug("Try to recognizeClassNames for symbol " + currentSymbol); - } - contextClass = TagManager.resolveClass(currentSymbol.toString(), compiler); - if (contextClass != null) { - currentSymbol.setLength(0); - //accepted = true; - //recognizeClassNames = false; - // TODO: for now we don't handle statics - return null; - } - } - if (!accepted) { - if (log.isDebugEnabled()) { - log.debug("symbol " + symbol + " was not accepted."); - } - return null; - } - } - - return contextClass; - } - - private void trackMemberIfPossible(String objectCode, ClassDescriptor objectClass, String memberName, boolean method) { - - if (log.isDebugEnabled()) { - log.debug("for [objectCode:" + objectCode + ", objectClass:" + objectClass + ", memberName:" + memberName + ", isMethod:" + method); - } - DefaultObjectHandler handler = TagManager.getTagHandler(objectClass); - try { - if (handler.isMemberBound(memberName)) { - String bindingId = objectCode + "." + memberName + (method ? "()" : ""); - if (showLog()) { - log.info("Detect a dependency from a event handler for memberName '" + memberName + "' for class " + objectClass); - log.info("Try to add a listener [symbol:" + bindingId + ", objectCode:" + objectCode + "]"); - } - addListener(bindingId, - objectCode, - getAddMemberListenerCode(handler, objectCode, memberName, "this", compiler), - getRemoveMemberListenerCode(handler, objectCode, memberName, "this", compiler)); - } - } catch (UnsupportedAttributeException e) { - // ignore -- this is thrown for methods like toString(), for which there is no tracking and - // no setting support - } - } - - private void addListener(String dependencySymbol, - String objectCode, - String addCode, - String removeCode) { - if (objectCode != null) { - objectCode = objectCode.trim(); - } - boolean needTest = objectCode != null && - !compiler.getRootObject().getId().equals(objectCode); - if (!needTest) { - objectCode = null; - } - if (log.isDebugEnabled()) { - log.debug("try to add listener [dependencySymbol:" + - dependencySymbol + ", objectCode:" + objectCode + - ", addCode:" + addCode + "]"); - } - - for (DataListener tracker : trackers) { - if (dependencySymbol.equals(tracker.getSymbol())) { - // listener already existing - return; - } - } - DataListener tracker = new DataListener(dependencySymbol, - objectCode, - addCode, - removeCode - ); - if (log.isDebugEnabled()) { - log.debug("add tracker " + tracker); - } - trackers.add(tracker); - } - - public boolean hasMethod(String methodName) { - for (JavaMethod method : methods) { - if (methodName.equals(method.getName())) { - return true; - } - } - return false; - } - - /** - * Returns a snippet of Java code which will cause a <code>PropertyChangeListener</code> to be notified - * when the member's value changes. The <code>PropertyChangeListener</code> is provided in the form - * of a Java code snippet that evaluates to a listener object. - * - * For ordinary bound JavaBeans properties, the Java code returned is a simple call to - * <code>addPropertyChangeListener</code>. Fields and methods which do not actually fire - * <code>PropertyChangeEvents</code> when they change necessitate more complex code. - * - * @param handler Object handler (containts known events - * @param objectCode Java code which evaluates to the object to which to add the listener - * *@param dataBinding the name of the data binding this listener is a part of - * @param memberName the name of the field or method to listen to - * @param propertyChangeListenerCode Java code which evaluates to a <code>PropertyChangeListener</code> - * @param compiler the current <code>JAXXCompiler</code> - * @return Java code snippet which causes the listener to be added to the object - */ - public String getAddMemberListenerCode(DefaultObjectHandler handler, - String objectCode, - String memberName, - String propertyChangeListenerCode, - JAXXCompiler compiler) { - if ("getClass".equals(memberName)) { - return null; - } - - DefaultObjectHandler.ProxyEventInfo eventInfo = handler.getEventInfo(memberName); - if (eventInfo != null) { - // a "proxied" event is one that doesn't fire PropertyChangeEvent, so we need to convert its native event type into PropertyChangeEvents - StringBuilder result = new StringBuilder(); - String methodName = "$pr" + compiler.getUniqueId(propertyChangeListenerCode.equals("this") ? constantId : propertyChangeListenerCode); - boolean methodExists = hasMethod(methodName); - ClassDescriptor eventClass = DefaultObjectHandler.getEventClass(eventInfo.getListenerClass()); - String type = compiler.getImportedType(JAXXCompiler.getCanonicalName(eventClass)); - if (!methodExists) { - String code = JavaFileGenerator.addDebugLoggerInvocation(compiler, "event"); - code += "propertyChange(null);"; - JavaMethod method = JavaElementFactory.newMethod( - Modifier.PUBLIC, - JAXXCompilerFinalizer.TYPE_VOID, - methodName, - code, - false, - JavaElementFactory.newArgument(type, "event")); - methods.add(method); - } - String code = objectCode + (eventInfo.getModelName() != null ? ".get" + StringUtils.capitalize(eventInfo.getModelName()) + "()" : ""); - result.append("$bindingSources.put(\"").append(code).append("\", ").append(code).append(");").append(JAXXCompiler.getLineSeparator()); - //TC-20091105 JAXXUtil.getEventListener is generic, no more need cast and use simple listener name - ClassDescriptor listenerClass = eventInfo.getListenerClass(); - String listenerType = compiler.getImportedType(listenerClass.getName()); - String jaxxUtilPrefix = compiler.getImportedType(JAXXUtil.class); - result.append(code); - result.append('.'); - result.append(eventInfo.getAddMethod()); - result.append("( ").append(jaxxUtilPrefix).append(".getEventListener("); - result.append(listenerType); - result.append(".class, "); - result.append("this"); - result.append(", "); - result.append(TypeManager.getJavaCode(methodName)); - result.append("));"); - result.append(JAXXCompiler.getLineSeparator()); - if (eventInfo.getModelName() != null) { - String addCode = getAddMemberListenerCode( - handler, - objectCode, - "get" + StringUtils.capitalize(eventInfo.getModelName()), - jaxxUtilPrefix + ".getDataBindingUpdateListener(" + compiler.getOutputClassName() + ".this" + ", " + constantId + ")", - compiler - ); - result.append(addCode); - } - return result.toString(); - } - String propertyName = null; - if (memberName.startsWith("get")) { - propertyName = Introspector.decapitalize(memberName.substring(3)); - } else if (memberName.startsWith("is")) { - propertyName = Introspector.decapitalize(memberName.substring(2)); - } else { - try { - handler.getBeanClass().getFieldDescriptor(memberName); - propertyName = memberName; - } catch (NoSuchFieldException e) { - // ignore ? - } - } - if (propertyName != null) { - //TC-20091026 when on root object, do not prefix with objectCode - String prefix = objectCode.trim() + "."; - if (objectCode.equals(compiler.getRootObject().getJavaCode())) { - prefix = ""; - } - //TC-20091203 : always use the property specific method, this is part of the javaBeans 1.1 norm - //TC-20091203 : if developpers do bad, shame on them... - return prefix + "addPropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; - -// try { -// // check for property-specific addPropertyChangeListener method -//// getBeanClass().getMethodDescriptor("addPropertyChangeListener", ClassDescriptorHelper.getClassDescriptor(String.class), -// handler.getBeanClass().getMethodDescriptor("addPropertyChangeListener", ClassDescriptorHelper.getClassDescriptor(String.class), -// ClassDescriptorHelper.getClassDescriptor(PropertyChangeListener.class)); -// return prefix + "addPropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; -// } catch (NoSuchMethodException e) { -// if (log.isInfoEnabled()) { -// log.info("Could not get named addPropertyChangeListener on class " + handler.getBeanClass()); -// } -// // no property-specific method, use general one -// return prefix + "addPropertyChangeListener(" + propertyChangeListenerCode + ");\n"; -// } - } - return null; - } - - public String getRemoveMemberListenerCode(DefaultObjectHandler handler, - String objectCode, - String memberName, - String propertyChangeListenerCode, - JAXXCompiler compiler) { - if ("getClass".equals(memberName)) { - return null; - } - - DefaultObjectHandler.ProxyEventInfo eventInfo = handler.getEventInfo(memberName); - if (eventInfo != null) { - // a "proxied" event is one that doesn't fire PropertyChangeEvent, - // so we need to convert its native event type into PropertyChangeEvents - StringBuilder result = new StringBuilder(); - String methodName = "$pr" + compiler.getUniqueId(propertyChangeListenerCode.equals("this") ? constantId : propertyChangeListenerCode); - boolean methodExists = hasMethod(methodName); - if (!methodExists) { - ClassDescriptor eventClass = DefaultObjectHandler.getEventClass(eventInfo.getListenerClass()); - String type = compiler.getImportedType(JAXXCompiler.getCanonicalName(eventClass)); - String code = JavaFileGenerator.addDebugLoggerInvocation(compiler, "event"); - code += "propertyChange(null);"; - JavaMethod method = JavaElementFactory.newMethod( - Modifier.PUBLIC, - JAXXCompilerFinalizer.TYPE_VOID, - methodName, - code, - false, - JavaElementFactory.newArgument(type, "event")); - methods.add(method); - } - try { - String modelMemberName = eventInfo.getModelName() != null ? "get" + StringUtils.capitalize(eventInfo.getModelName()) : null; - String modelClassName = modelMemberName != null ? handler.getBeanClass().getMethodDescriptor(modelMemberName).getReturnType().getName() : JAXXCompiler.getCanonicalName(handler.getBeanClass()); - String modelType = compiler.getImportedType(modelClassName); - String code = objectCode + (eventInfo.getModelName() != null ? "." + modelMemberName + "()" : ""); - String eol = JAXXCompiler.getLineSeparator(); - String jaxxUtilPrefix = compiler.getImportedType(JAXXUtil.class); - result.append(modelType).append(" $target = (").append(modelType).append(") $bindingSources.remove(\"").append(code).append("\");").append(eol); - //TC-20091105 test if $target is not null - result.append("if ($target != null) {").append(eol); - //TC-20091105 JAXXUtil.getEventListener is generic, no more need cast and use simple listener name - ClassDescriptor listenerClass = eventInfo.getListenerClass(); - String listenerType = compiler.getImportedType(listenerClass.getName()); - result.append(" $target."); - result.append(eventInfo.getRemoveMethod()); - result.append("( ").append(jaxxUtilPrefix).append(".getEventListener("); - result.append(listenerType); - result.append(".class, "); - result.append("this"); - result.append(", "); - result.append(TypeManager.getJavaCode(methodName)); - result.append("));"); - result.append(eol); - result.append("}").append(eol); - if (eventInfo.getModelName() != null) { - result.append(getRemoveMemberListenerCode(handler, objectCode, "get" + StringUtils.capitalize(eventInfo.getModelName()), - jaxxUtilPrefix + ".getDataBindingUpdateListener(" + compiler.getOutputClassName() + ".this, " + constantId + ")", - compiler)); - } - return result.toString(); - } catch (NoSuchMethodException e) { - throw new CompilerException("Internal error: " + e); - } - } - - String propertyName = null; - if (memberName.startsWith("get")) { - propertyName = Introspector.decapitalize(memberName.substring("get".length())); - } else if (memberName.startsWith("is")) { - propertyName = Introspector.decapitalize(memberName.substring("is".length())); - } else { - try { - handler.getBeanClass().getFieldDescriptor(memberName); - propertyName = memberName; - } catch (NoSuchFieldException e) { - // ignore ? - } - } - if (propertyName == null) { - return null; - } - - String prefix = objectCode.trim() + "."; - if (objectCode.equals(compiler.getRootObject().getJavaCode())) { - prefix = ""; - } - //TC-20091203 : always use the property specific method, this is part of the javaBeans 1.1 norm - //TC-20091203 : if developpers do bad, shame on them... - return prefix + "removePropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; -// try { -// // check for property-specific removePropertyChangeListener method -// handler.getBeanClass().getMethodDescriptor("removePropertyChangeListener", ClassDescriptorHelper.getClassDescriptor(String.class), -// ClassDescriptorHelper.getClassDescriptor(PropertyChangeListener.class)); -// return prefix + "removePropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; -// } catch (NoSuchMethodException e) { -// // no property-specific method, use general one -// return prefix + "removePropertyChangeListener(" + propertyChangeListenerCode + ");\n"; -// } - } - - /** - * Given a method from a given context class, try to obtain his method - * return type. - * - * Sometimes, the return type is unknown (generics can not be bind for - * example). As a fallback, we try if the context class is exactly the - * root context class of the compiler, replace it by the script method with - * same name on which we can have more chance to obtain a return type... - * - * @param contextClass the context class of the method - * @param method the method - * @return the method return type - * @since 2.4.2 - */ - protected ClassDescriptor getMethodReturnType(ClassDescriptor contextClass, - MethodDescriptor method) { - ClassDescriptor returnType = method.getReturnType(); - if (returnType == null && - contextClass.equals(compiler.getRootObject().getObjectClass())) { - - // special case to deal with generics (we need to - // have the concrete type)... - method = compiler.getScriptMethod(method.getName()); - if (method != null) { - returnType = method.getReturnType(); - } - } - return returnType; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/binding/JavaParserUtil.java b/jaxx-compiler/src/main/java/jaxx/compiler/binding/JavaParserUtil.java deleted file mode 100644 index 9d78e56..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/binding/JavaParserUtil.java +++ /dev/null @@ -1,387 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.binding; - -import jaxx.compiler.java.parser.JavaParserTreeConstants; -import jaxx.compiler.java.parser.SimpleNode; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.beans.Introspector; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Created: 4 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - * - * Mise a jour: $Date$ par : - * $Author$ - */ -public class JavaParserUtil { - - /** - * Logger - */ - private static final Log log = LogFactory.getLog(JavaParserUtil.class); - - private static final Comparator<String> STRING_LENGTH_COMPARATOR = new Comparator<String>() { - - @Override - public int compare(String o1, String o2) { - return o1.length() - o2.length(); - } - }; - - /** - * Obtain all expressions of a node and store them in {@code store} with their dependencies expressions. - * - * Also fill the {@code literals} list of literal expressions. - * - * @param node the node to scan - * @param store the store of expressions detected with all the expression which compose the expression (can be empty) - * @param literals the list of literal expressions detected - * @param casts the list of casted expression detected - */ - public static void getExpressions(SimpleNode node, Map<SimpleNode, List<SimpleNode>> store, List<SimpleNode> literals, Map<SimpleNode, List<SimpleNode>> casts) { - - if (node.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION || - node.getId() == JavaParserTreeConstants.JJTFIELDDECLARATION) { - //TODO add all others non intressing type of node to reject directly - return; - } - - if (node.getId() == JavaParserTreeConstants.JJTPRIMARYEXPRESSION) { - // get a primary expression, look for his dependencies - scanForExpressions(node, null, store, literals, casts); - return; - } - - // recurse of childs of node - for (int i = 0, count = node.jjtGetNumChildren(); i < count; i++) { - getExpressions(node.getChild(i), store, literals, casts); - } - - } - - /** - * Remove from expressions store, all literal expressions and dependencies on it. - * - * @param store the store of expressions with theirs dependencies - * @param literalExpressions the unvierse of literal expressions - */ - public static void removeLiteralExpressions(Map<SimpleNode, List<SimpleNode>> store, List<SimpleNode> literalExpressions) { - for (SimpleNode n : literalExpressions) { - - // on supprime toutes les dependences sur les expression literales - // car on en a pas besoin pour decouvrir les expressions qui peuvent etre nulles... - - if (log.isDebugEnabled()) { - log.debug("Reject literal expression " + n.getText()); - } - for (List<SimpleNode> dependencies : store.values()) { - dependencies.remove(n); - } - store.remove(n); - } - } - - /** - * Remove from expressions sotre, all expressions with dependencies. - * - * @param store the store of expressions with their dependencies - * @param castsExpressions list of cast expression to keep - */ - public static void removeNoneStandaloneExpressions(Map<SimpleNode, List<SimpleNode>> store, Map<SimpleNode, List<SimpleNode>> castsExpressions) { - List<SimpleNode> rejectedExpressions = new ArrayList<>(); - - for (Map.Entry<SimpleNode, List<SimpleNode>> e : store.entrySet()) { - - List<SimpleNode> dependencies = e.getValue(); - SimpleNode node = e.getKey(); - if (castsExpressions.containsKey(node)) { - // the expression is part of a cast, need to keep it - continue; - } - if (!dependencies.isEmpty()) { - - // expression with dependencies, don't treate it, but treate all in dependencies :) - rejectedExpressions.add(node); - if (log.isDebugEnabled()) { - log.debug("Reject expression " + node.getText() + " with " + dependencies.size() + " dependencies"); - for (SimpleNode n : dependencies) { - log.debug(" " + n.getText()); - } - } - } - } - - for (SimpleNode node : rejectedExpressions) { - store.remove(node); - } - - rejectedExpressions.clear(); - } - - - public static Set<String> getRequired(Set<SimpleNode> store, Map<SimpleNode, List<SimpleNode>> casts) { - if (store.isEmpty()) { - return null; - } - - Set<SimpleNode> castCodes = new LinkedHashSet<>(); - for (List<SimpleNode> cast : casts.values()) { - for (SimpleNode node : cast) { - castCodes.add(node); - if (log.isDebugEnabled()) { - log.debug("cast = " + node.getText().trim()); - } - } - } - - List<String> result = new ArrayList<>(); - for (SimpleNode node : store) { - String expression = node.getText().trim(); - if (result.contains(expression)) { - // already treated - continue; - } - for (SimpleNode castCode : castCodes) { - String str = castCode.getText().trim(); - int index = expression.indexOf(str); - if (index > -1) { - // got a cast, replace the cast expression, by the simple expression - // we have (CAST)XXX --> XXX - if (log.isDebugEnabled()) { - log.debug("got a cast in expresion " + expression + " = " + castCode); - } - String tmp = ""; - //FIXME : should check this is a complete cast : could be only a conversion... - if (index > 1) { - tmp = expression.substring(0, index - 1); - } - tmp += ((SimpleNode) castCode.jjtGetChild(1)).getText().trim() + expression.substring(index + str.length() + 1); - if (log.isDebugEnabled()) { - log.debug("REMOVED CAST : " + tmp); - } - expression = tmp; - } - } - if (expression.indexOf(".") == -1) { - // not an expression to keep - // a simple field use like 'isEnabled()' or 'field' - // or a not method invocation - if (log.isDebugEnabled()) { - log.debug("Reject simple expression " + expression); - } - continue; - } - if (expression.indexOf("(") == -1) { - // expression with no called method, probably is a constant - // should test it, but for the moment just limits bindings to interfield expressions : a.b - // is not possible, use a.getB() instead of - if (log.isDebugEnabled()) { - log.debug("Reject constant or static expression " + expression); - } - continue; - } - - if (log.isDebugEnabled()) { - log.debug("Keep expression " + expression); - } - result.add(expression); - } - - if (result.isEmpty()) { - return null; - } - - Collections.sort(result, STRING_LENGTH_COMPARATOR); - if (log.isDebugEnabled()) { - log.debug("======= start with values : " + result); - } - - - Set<String> objectCodes = new LinkedHashSet<>(); - - for (String expression : result) { - - // test if we have a cast in this expression - - Set<String> tmp = new LinkedHashSet<>(); - - String[] paths = expression.split("\\s*\\.\\s*"); - if (paths.length < 2) { - // just a simple expression - // TODO Should never come here... - continue; - } - - if (log.isDebugEnabled()) { - log.debug("Expression to treate : " + expression + " :: " + Arrays.toString(paths)); - } - - StringBuilder buffer = new StringBuilder(); - String last = paths[0].trim(); - if (last.indexOf("(") > -1) { - // first path is a method invocation or a cast - // at the moment allow cast only on the first member and do no perform any check - - // must check this is a complete method invocation - String args = getMethodInvocationParameters(last); - if (args == null) { - // this path is not a method invocation - // must break - continue; - } - if (!args.isEmpty()) { - // for the moment, we only accept method with no args - // must break - continue; - } - - } - buffer.append(last); - tmp.add(buffer.toString()); - for (int i = 1, max = paths.length - 1; i < max; i++) { - String s = paths[i].trim(); - String args = getMethodInvocationParameters(s); - if (args == null) { - // this path is not a method invocation - // must break - // if previous - break; - } - if (!args.isEmpty()) { - // for the moment, we only accept method with no args - // must break - break; - } - buffer.append(".").append(s); - last = buffer.toString(); - tmp.add(last); - } - objectCodes.addAll(tmp); - } - - if (log.isDebugEnabled()) { - log.debug("Detected requirements : " + objectCodes); - } - return objectCodes; - } - - public static String getMethodInvocationParameters(String code) { - int openIndex = code.indexOf("("); - int closeIndex = code.lastIndexOf(")"); - if (openIndex > -1 && closeIndex > -1) { - if (closeIndex == openIndex + 1) { - return ""; - } - // missing something - return code.substring(openIndex + 1, closeIndex - 1).trim(); - } - return null; - } - - public static String getPropertyNameFromMethod(String code) { - int openIndex = code.indexOf("("); - if (openIndex != -1) { - code = code.substring(0, openIndex); - } - int index = 3; - if (code.startsWith("is")) { - index = 2; - } - code = code.substring(index); - code = Introspector.decapitalize(code); - return code; - } - - public static void scanForExpressions(SimpleNode node, SimpleNode lastExpressionNode, Map<SimpleNode, List<SimpleNode>> store, List<SimpleNode> literals, Map<SimpleNode, List<SimpleNode>> casts) { - - String nodeExpression = node.getText().trim(); - if (log.isTraceEnabled()) { - log.trace("node " + node.getId() + " nbChilds : " + node.jjtGetNumChildren() + " : " + nodeExpression); - } - if (node.getId() == JavaParserTreeConstants.JJTLITERAL) { - // expression literal qu'on ne veut pas garder ? - if (log.isDebugEnabled()) { - log.debug("detected literal " + nodeExpression + " for last expression " + lastExpressionNode.getText()); - } - literals.add(lastExpressionNode); - return; - } - if (node.getId() == JavaParserTreeConstants.JJTCASTEXPRESSION) { - // expression literal qu'on ne veut pas garder ? - if (log.isDebugEnabled()) { - log.debug("detected cast " + nodeExpression + " for last expression " + lastExpressionNode.getText()); - } - List<SimpleNode> simpleNodeList = casts.get(lastExpressionNode); - if (simpleNodeList == null) { - simpleNodeList = new ArrayList<>(); - casts.put(lastExpressionNode, simpleNodeList); - } - simpleNodeList.add(node); - } - - if (node.getId() == JavaParserTreeConstants.JJTPRIMARYEXPRESSION) { - - if (store.get(node) == null) { - store.put(node, new ArrayList<SimpleNode>()); - } - if (lastExpressionNode == null) { - - // premiere entree dans la methode (detection d'une nouvelle expression) - // rien a faire - - - } else { - - // on vient d'un appel recursif, on ajoute le noeud courant a la liste des expression de l'expression parent - - List<SimpleNode> simpleNodeList = store.get(lastExpressionNode); - if (simpleNodeList == null) { - simpleNodeList = new ArrayList<>(); - store.put(node, simpleNodeList); - } - simpleNodeList.add(node); - } - - // on change la derniere expression rencontree - lastExpressionNode = node; - } - - // on parcours tous les fils du noeud courant - for (int i = 0, count = node.jjtGetNumChildren(); i < count; i++) { - scanForExpressions(node.getChild(i), lastExpressionNode, store, literals, casts); - } - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/binding/PseudoClassDataBinding.java b/jaxx-compiler/src/main/java/jaxx/compiler/binding/PseudoClassDataBinding.java deleted file mode 100644 index a5566d3..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/binding/PseudoClassDataBinding.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.binding; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.java.JavaFileGenerator; -import jaxx.compiler.java.parser.JavaParser; -import jaxx.compiler.java.parser.JavaParserTreeConstants; -import jaxx.compiler.java.parser.SimpleNode; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.StringReader; - -/** - * Represents a data binding in a JAXX file. <code>DataBinding</code> uses - * {@link DataSource} to track changes to a source expression and update - * the destination. - */ -public class PseudoClassDataBinding extends DataBinding { - - /** - * Logger - */ - protected static final Log log = LogFactory.getLog(PseudoClassDataBinding.class); - - protected final boolean invert; - - public static PseudoClassDataBinding newPseudoClassDataBinding(String pseudoClass, CompiledObject object, String propertyCode, String methodName, boolean invertTest) { - PseudoClassDataBinding binding = null; - if (pseudoClass.startsWith("{")) { - pseudoClass = pseudoClass.substring(1, pseudoClass.length() - 1).trim(); - pseudoClass = replaceObjectReferences(pseudoClass, object.getJavaCode()); - String id = object.getId() + ".style." + pseudoClass + "." + methodName; - - if (log.isDebugEnabled()) { - log.debug("will test if databinding : [" + pseudoClass + "] " + id); - } - binding = new PseudoClassDataBinding(id, pseudoClass, propertyCode, invertTest); - } - return binding; - } - - protected PseudoClassDataBinding(String id, String source, String assignment, boolean invert) { - super(id, source, assignment, false); - this.invert = invert; - } - - /** - * Replaces all references to the variable "object" with the actual object ID. - * - * @param code ? - * @param id ? - * @return ? - * @throws CompilerException ? - */ - public static String replaceObjectReferences(String code, String id) throws CompilerException { - JavaParser p = new JavaParser(new StringReader(code + ";")); - p.Expression(); - SimpleNode node = p.popNode(); - scanNode(node, id); - return node.getText(); - } - - public static void scanNode(SimpleNode node, String id) { - if (node.getId() == JavaParserTreeConstants.JJTNAME) { - String name = node.getText(); - if (name.equals("object") || - (name.indexOf(".") != -1 && - name.substring(0, name.indexOf(".")).trim().equals("object"))) { - node.firstToken.image = id; - } - } else { - int count = node.jjtGetNumChildren(); - for (int i = 0; i < count; i++) { - scanNode(node.getChild(i), id); - } - } - } - - @Override - protected String getInitDataBindingCode(JAXXCompiler compiler, DataSource dataSource, boolean isBinding) { - // nothing to init - return null; - } - - @Override - protected String getProcessDataBindingCode(JAXXCompiler compiler, DataSource dataSource, boolean isBinding) { - if (!isBinding) { - return null; - } - - String eol = JAXXCompiler.getLineSeparator(); - - StringBuilder buffer = new StringBuilder(); - - String realSource = invert ? invert(getSource()) : getSource(); - buffer.append("if (").append(realSource).append(") {").append(eol); - buffer.append(JavaFileGenerator.indent(getAssignment(), 4, false, eol)).append(eol); - buffer.append("}"); - return buffer.toString(); - } - - protected String invert(String javaCode) { - javaCode = javaCode.trim(); - return javaCode.startsWith("!") ? javaCode.substring(1) : "!(" + javaCode + ")"; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/AbstractJAXXBindingWriter.java b/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/AbstractJAXXBindingWriter.java deleted file mode 100644 index 9a73c30..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/AbstractJAXXBindingWriter.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.binding.writers; - -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.binding.DataBinding; -import jaxx.compiler.binding.DataListener; -import jaxx.compiler.finalizers.DefaultFinalizer; -import jaxx.compiler.java.JavaFileGenerator; -import jaxx.compiler.java.JavaMethod; -import jaxx.runtime.JAXXBinding; - -import java.util.List; - -/** - * Created: 5 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Id$ - */ -public abstract class AbstractJAXXBindingWriter<B extends JAXXBinding> implements JAXXBindingWriter<B> { - - private final Class<B> type; - - protected boolean used; - - protected AbstractJAXXBindingWriter(Class<B> type) { - this.type = type; - } - - @Override - public boolean isUsed() { - return used; - } - - @Override - public Class<B> getType() { - return type; - } - - @Override - public void reset() { - used = false; - } - - protected abstract String getConstructorParams(DataBinding binding, - DataListener[] trackers); - - protected void writeInvocationMethod(DataBinding binding, - DataListener[] trackers, - JavaFileGenerator generator, - StringBuilder buffer, - List<JavaMethod> bMethods) { - used = true; - String eol = JAXXCompiler.getLineSeparator(); - buffer.append(DefaultFinalizer.METHOD_NAME_REGISTER_DATA_BINDING); - buffer.append("(new "); - buffer.append(getType().getSimpleName()); - buffer.append("("); - buffer.append(getConstructorParams(binding, trackers)); - buffer.append(") {"); - buffer.append(eol); - for (JavaMethod m : bMethods) { - buffer.append(eol); - String source = generator.generateMethod(m); - buffer.append(JavaFileGenerator.indent(source, 4, false, eol)); - buffer.append(eol); - } - buffer.append("});").append(eol); - - if (binding.getInitDataBinding() != null) { - buffer.append(binding.getInitDataBinding()); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/DefaultJAXXBindingWriter.java b/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/DefaultJAXXBindingWriter.java deleted file mode 100644 index cdee04e..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/DefaultJAXXBindingWriter.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.binding.writers; - -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.binding.DataBinding; -import jaxx.compiler.binding.DataListener; -import jaxx.compiler.finalizers.DefaultFinalizer; -import jaxx.compiler.finalizers.JAXXCompilerFinalizer; -import jaxx.compiler.java.JavaElementFactory; -import jaxx.compiler.java.JavaFileGenerator; -import jaxx.compiler.java.JavaMethod; -import jaxx.runtime.binding.DefaultJAXXBinding; - -import java.util.List; - -import static java.lang.reflect.Modifier.PUBLIC; - -/** - * Created: 5 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - * - * Mise a jour: $Date$ par : - * $Author$ - */ -public class DefaultJAXXBindingWriter extends AbstractJAXXBindingWriter<DefaultJAXXBinding> { - - public DefaultJAXXBindingWriter() { - super(DefaultJAXXBinding.class); - } - - @Override - public boolean accept(DataBinding binding) { - return true; - } - - @Override - public void write(DataBinding binding, - JavaFileGenerator generator, - StringBuilder buffer) { - DataListener[] trackers = binding.getTrackers(); - String eol = JAXXCompiler.getLineSeparator(); - - StringBuilder addBuffer = new StringBuilder(); - StringBuilder removeBuffer = new StringBuilder(); - - for (DataListener tracker : trackers) { - boolean needTest = tracker.getObjectCode() != null; - if (needTest) { - addBuffer.append("if ("); - addBuffer.append(tracker.getObjectCode()); - addBuffer.append(" != null) {"); - addBuffer.append(eol); - - removeBuffer.append("if ("); - removeBuffer.append(tracker.getObjectCode()); - removeBuffer.append(" != null) {"); - removeBuffer.append(eol); - } - int indentLevel = needTest ? 4 : 0; - addBuffer.append(JavaFileGenerator.indent( - tracker.getAddListenerCode(), indentLevel, false, eol)); - removeBuffer.append(JavaFileGenerator.indent( - tracker.getRemoveListenerCode(), indentLevel, false, eol)); - if (needTest) { - addBuffer.append(eol).append("}"); - removeBuffer.append(eol).append("}"); - } - addBuffer.append(eol); - removeBuffer.append(eol); - } - - List<JavaMethod> bMethods = binding.getMethods(); - bMethods.add(0, JavaElementFactory.newMethod( - PUBLIC, - JAXXCompilerFinalizer.TYPE_VOID, - DefaultFinalizer.METHOD_NAME_REMOVE_DATA_BINDING, - removeBuffer.toString(), - true) - ); - bMethods.add(0, JavaElementFactory.newMethod( - PUBLIC, - JAXXCompilerFinalizer.TYPE_VOID, - DefaultFinalizer.METHOD_NAME_PROCESS_DATA_BINDING, - binding.getProcessDataBinding(), - true) - ); - bMethods.add(0, JavaElementFactory.newMethod( - PUBLIC, - JAXXCompilerFinalizer.TYPE_VOID, - DefaultFinalizer.METHOD_NAME_APPLY_DATA_BINDING, - addBuffer.toString(), - true) - ); - - writeInvocationMethod(binding, trackers, generator, buffer, bMethods); - } - - @Override - protected String getConstructorParams(DataBinding binding, - DataListener[] trackers) { - - String params = "this, " + binding.getConstantId() + ", true"; - if (trackers.length > 1) { - //FIXME tchemit-2011-04-21 Must improve this : only need a complex binding - // when chaining properties : example getA().getB() but not getA() || getB() - // with a complex binding, we will need to reload de binding after each fire... - params += ", true"; - - } - return params; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/JAXXBindingWriter.java b/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/JAXXBindingWriter.java deleted file mode 100644 index 8ab3060..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/JAXXBindingWriter.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.binding.writers; - -import jaxx.compiler.binding.DataBinding; -import jaxx.compiler.java.JavaFileGenerator; -import jaxx.runtime.JAXXBinding; - -/** - * The contract of a writer of {@link JAXXBinding} creation code from a - * {@link DataBinding}. - * - * Created: 5 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - * - * Mise a jour: $Date$ par : - * $Author$ - */ -public interface JAXXBindingWriter<B extends JAXXBinding> { - - /** - * Test if a binding can be treated by the writer. - * - * @param binding the binding to test - * @return {@code true} if this writer can be used to generate binding creation code, {@code false} otherwise. - */ - boolean accept(DataBinding binding); - - /** - * Test if the writer was at least used once (says that the method - * {@link #write(DataBinding, JavaFileGenerator, StringBuilder)} was at least invoked once). - * - * @return {@code true} if this writer was used - */ - boolean isUsed(); - - /** @return the type of {@link JAXXBinding} to generate */ - Class<B> getType(); - - /** - * Generate the creation code of the given {@code binding} and push it in the given {@code buffer}. - * - * Note: after beean in this method, the {@link #isUsed()} should always return {@code true}. - * - * @param binding the binding to use - * @param generator common generator to build creation code - * @param buffer where to push creation code - */ - void write(DataBinding binding, - JavaFileGenerator generator, - StringBuilder buffer); - - /** - * Reset internal states. - * - * At the moment, there is only the {@code used} property which is - * internal and must be reset to {@code false} for each compiler in order - * to know if a type of writer is used for the file. - * - * @since 2.4 - */ - void reset(); -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/SimpleJAXXObjectBindingWriter.java b/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/SimpleJAXXObjectBindingWriter.java deleted file mode 100644 index 5efae36..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/SimpleJAXXObjectBindingWriter.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.binding.writers; - -import jaxx.compiler.binding.DataBinding; -import jaxx.compiler.binding.DataListener; -import jaxx.compiler.binding.JavaParserUtil; -import jaxx.compiler.finalizers.DefaultFinalizer; -import jaxx.compiler.finalizers.JAXXCompilerFinalizer; -import jaxx.compiler.java.JavaElementFactory; -import jaxx.compiler.java.JavaFileGenerator; -import jaxx.compiler.java.JavaMethod; -import jaxx.runtime.binding.SimpleJAXXObjectBinding; - -import java.lang.reflect.Modifier; -import java.util.List; - -/** - * Created: 5 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - * - * Mise a jour: $Date$ par : - * $Author$ - */ -public class SimpleJAXXObjectBindingWriter extends AbstractJAXXBindingWriter<SimpleJAXXObjectBinding> { - - protected boolean used; - - public SimpleJAXXObjectBindingWriter() { - super(SimpleJAXXObjectBinding.class); - } - - @Override - public boolean accept(DataBinding binding) { - DataListener[] trackers = binding.getTrackers(); - if (trackers.length > 0) { - for (DataListener tracker : trackers) { - if (tracker.getObjectCode() != null) { - // tracker must be without any requirement - return false; - } - } - } - return true; - } - - @Override - protected String getConstructorParams(DataBinding binding, - DataListener[] trackers) { - - StringBuilder addBuffer = new StringBuilder(); - addBuffer.append("this, "); - addBuffer.append(binding.getConstantId()); - addBuffer.append(", true"); - - for (DataListener tracker : trackers) { - String symbol = tracker.getSymbol(); - String name = symbol.substring(symbol.indexOf(".") + 1); - if (JavaParserUtil.getMethodInvocationParameters(name) != null) { - // obtain the property name from the method name - name = JavaParserUtil.getPropertyNameFromMethod(name); - } - addBuffer.append(" ,\"").append(name).append("\""); - } - return addBuffer.toString(); - } - - @Override - public void write(DataBinding binding, - JavaFileGenerator generator, - StringBuilder buffer) { - DataListener[] trackers = binding.getTrackers(); - List<JavaMethod> bMethods = binding.getMethods(); - - JavaMethod method = JavaElementFactory.newMethod( - Modifier.PUBLIC, - JAXXCompilerFinalizer.TYPE_VOID, - DefaultFinalizer.METHOD_NAME_PROCESS_DATA_BINDING, - binding.getProcessDataBinding(), - true - ); - - bMethods.add(0, method); - - writeInvocationMethod(binding, trackers, generator, buffer, bMethods); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/css/StylesheetHelper.java b/jaxx-compiler/src/main/java/jaxx/compiler/css/StylesheetHelper.java deleted file mode 100644 index e6a4ada..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/css/StylesheetHelper.java +++ /dev/null @@ -1,702 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.css; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.binding.DataBinding; -import jaxx.compiler.binding.DataBindingHelper; -import jaxx.compiler.binding.PseudoClassDataBinding; -import jaxx.compiler.css.parser.CSSParser; -import jaxx.compiler.css.parser.CSSParserConstants; -import jaxx.compiler.css.parser.CSSParserTreeConstants; -import jaxx.compiler.css.parser.SimpleNode; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.reflect.MethodDescriptor; -import jaxx.compiler.tags.DefaultComponentHandler; -import jaxx.compiler.tags.DefaultObjectHandler; -import jaxx.compiler.tags.TagManager; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.css.Pseudoclasses; -import jaxx.runtime.css.Rule; -import jaxx.runtime.css.Selector; -import jaxx.runtime.css.Stylesheet; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * A helper class to compute {@link Stylesheet}, {@link Rule} and {@link Selector} - * and extract all the compiler logic from this class. - * - * In that way we can make the compiler as a single module and a runtime as another module. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class StylesheetHelper { - - /** Logger */ - static private final Log log = LogFactory.getLog(StylesheetHelper.class); - - public static Stylesheet processStylesheet(String stylesheetText) throws CompilerException { - CSSParser p = new CSSParser(new StringReader(stylesheetText)); - SimpleNode node; - try { - node = p.Stylesheet(); - } catch (Error e) { - throw new CompilerException(e); - } - List<Rule> rules = new ArrayList<>(); - for (int i = 0; i < node.jjtGetNumChildren(); i++) { - SimpleNode ruleNode = node.getChild(i); - Rule rule = processRule(ruleNode); - rules.add(rule); - } - Stylesheet stylesheet; - stylesheet = new Stylesheet(rules.toArray(new Rule[rules.size()])); - return stylesheet; - } - - public static Rule processRule(SimpleNode ruleNode) { - if (ruleNode.getId() != CSSParserTreeConstants.JJTRULE) { - throw new IllegalArgumentException("argument node is not a Rule"); - } - SimpleNode selectorsNode = ruleNode.getChild(0); - assert selectorsNode.getId() == CSSParserTreeConstants.JJTSELECTORS : - "expected node to be of type Selectors"; - - List<Selector> selectors = new ArrayList<>(); - for (int i = 0; i < selectorsNode.jjtGetNumChildren(); i++) { - SimpleNode selectorNode = selectorsNode.getChild(i); - selectors.add(processSelector(selectorNode)); - } - - Map<String, String> properties = new HashMap<>(); - for (int i = 1; i < ruleNode.jjtGetNumChildren(); i++) { - SimpleNode declarationNode = ruleNode.getChild(i); - if (declarationNode.getId() == CSSParserTreeConstants.JJTDECLARATION) { - String key = declarationNode.getChild(0).getText(); - SimpleNode valueNode = declarationNode.getChild(1); - String value = valueNode.getText(); - if (valueNode.firstToken.kind == CSSParserConstants.STRING) { - value = value.substring(1, value.length() - 1); - } - properties.put(key, value); - } - } - Rule rule; - rule = new Rule(selectors.toArray( - new Selector[selectors.size()]), properties); - return rule; - } - - public static Selector processSelector(SimpleNode selector) { - if (selector.getId() != CSSParserTreeConstants.JJTSELECTOR) { - throw new IllegalArgumentException("argument node is not a Selector"); - } - String javaClassName = null; - String styleClass = null; - String pseudoClass = null; - String id = null; - - for (int i = 0; i < selector.jjtGetNumChildren(); i++) { - SimpleNode child = selector.getChild(i); - switch (child.getId()) { - case CSSParserTreeConstants.JJTJAVACLASS: - if (!child.getText().trim().equals("*")) { - javaClassName = child.getText(); - } - break; - case CSSParserTreeConstants.JJTCLASS: - styleClass = child.getText().substring(1); - break; - case CSSParserTreeConstants.JJTPSEUDOCLASS: - pseudoClass = child.getText().substring(1); - break; - case CSSParserTreeConstants.JJTID: - id = child.getText().substring(1); - break; - - default: - throw new IllegalStateException( - "unexpected child of Selector node, type=" + - child.getId()); - } - } - - return new Selector(javaClassName, styleClass, pseudoClass, id); - } - - public enum MouseEventEnum { - - mouseover("mouseEntered", "mouseExited"), - mouseout("mouseExited", "mouseReleased"), - mousedown("mousePressed", "mousePressed"), - mouseup("mouseReleased", "mousePressed"); - - final String addMethod; - - final String removeMethod; - -// ClassDescriptor mouseListenerDescriptor; -// ClassDescriptor mouseEventDescriptor; - - MouseEventEnum(String addMethod, String removeMethod) { - this.removeMethod = removeMethod; - this.addMethod = addMethod; - } - - public String getProperty(int i) { - return i == 0 ? addMethod : removeMethod; - } - } - - static ClassDescriptor mouseListenerDescriptor; - - static ClassDescriptor mouseEventDescriptor; - - public static ClassDescriptor getMouseEventDescriptor() { - if (mouseEventDescriptor == null) { - mouseEventDescriptor = - ClassDescriptorHelper.getClassDescriptor(MouseEvent.class); - } - return mouseEventDescriptor; - } - - public static ClassDescriptor getMouseListenerDescriptor() { - if (mouseListenerDescriptor == null) { - mouseListenerDescriptor = - ClassDescriptorHelper.getClassDescriptor(MouseListener.class); - } - return mouseListenerDescriptor; - } - - public static MethodDescriptor getAddMouseListenerMethod(CompiledObject object) { - try { - return object.getObjectClass().getMethodDescriptor( - "addMouseListener", - getMouseListenerDescriptor() - ); - } catch (NoSuchMethodException e) { - throw new CompilerException( - "could not find addMouseListener for object " + object); - } - } - - public static MethodDescriptor getMouseListenerMethod(CompiledObject object, String property) { - try { - return getMouseListenerDescriptor().getMethodDescriptor( - property, - getMouseEventDescriptor() - ); - } catch (NoSuchMethodException e) { - throw new CompilerException( - "could not find " + property + " for object " + object); - } - } - - public static void applyTo(CompiledObject object, - JAXXCompiler compiler, - Stylesheet stylesheet, - Stylesheet overrides) throws CompilerException { - Map<String, String> overriddenProperties; - if (overrides != null) { - overriddenProperties = getApplicableProperties(overrides, object); - //overriddenProperties = overrides.getApplicableProperties(s,object); - } else { - overriddenProperties = null; - } - - Map<String, String> properties = getApplicableProperties(stylesheet, - object); - if (properties != null) { - if (overriddenProperties != null) { - properties.keySet().removeAll(overriddenProperties.keySet()); - } - DefaultObjectHandler handler = - TagManager.getTagHandler(object.getObjectClass()); - for (Map.Entry<String, String> e : properties.entrySet()) { - String value = e.getValue(); - if (value.equals(Rule.INLINE_ATTRIBUTE) || - value.equals(Rule.DATA_BINDING)) { - continue; - } - - if (handler instanceof DefaultComponentHandler) - handler.setAttribute(object, e.getKey(), e.getValue(), - false, compiler); - else { - handler.setAttributeFromCss(object, e.getKey(), value, compiler); - } - } - } - - Rule[] pseudoClasses = getApplicablePseudoClasses(stylesheet, object); - if (pseudoClasses != null) { - Map<String, Map<String, String>> combinedPseudoClasses = - new LinkedHashMap<>(); - for (Rule pseudoClass1 : pseudoClasses) { - Selector[] selectors = pseudoClass1.getSelectors(); - for (Selector selector : selectors) { - if (appliesTo(selector, object) == - Selector.PSEUDOCLASS_APPLIES) { - properties = pseudoClass1.getProperties(); - String pseudoClass = selector.getPseudoClass(); - // TODO: overrides by downstream pseudoclasses are not handled - Map<String, String> combinedProperties = - combinedPseudoClasses.get(pseudoClass); - if (combinedProperties == null) { - combinedProperties = new HashMap<>(); - combinedPseudoClasses.put(pseudoClass, - combinedProperties); - } - combinedProperties.putAll(properties); - } - } - } - - int count = 0; - for (Map.Entry<String, Map<String, String>> e : - combinedPseudoClasses.entrySet()) { - applyPseudoClass(e.getKey(), e.getValue(), object, compiler, - count++); - } - } - } - - public static String unwrap(ClassDescriptor type, String valueCode) { - if (ClassDescriptorHelper.getClassDescriptor(boolean.class).equals(type)) { - return "((Boolean) " + valueCode + ").booleanValue()"; - } - if (ClassDescriptorHelper.getClassDescriptor(byte.class).equals(type)) { - return "((Byte) " + valueCode + ").byteValue()"; - } - if (ClassDescriptorHelper.getClassDescriptor(short.class).equals(type)) { - return "((Short) " + valueCode + ").shortValue()"; - } - if (ClassDescriptorHelper.getClassDescriptor(int.class).equals(type)) { - return "((Integer) " + valueCode + ").intValue()"; - } - if (ClassDescriptorHelper.getClassDescriptor(long.class).equals(type)) { - return "((Long) " + valueCode + ").longValue()"; - } - if (ClassDescriptorHelper.getClassDescriptor(float.class).equals(type)) { - return "((Float) " + valueCode + ").floatValue()"; - } - if (ClassDescriptorHelper.getClassDescriptor(double.class).equals(type)) { - return "((Double) " + valueCode + ").doubleValue()"; - } - if (ClassDescriptorHelper.getClassDescriptor(char.class).equals(type)) { - return "((Character) " + valueCode + ").charValue()"; - } - return valueCode; - } - - public enum PseudoClassEnum { - focused("{ object.hasFocus() }"), - unfocused("{ !object.hasFocus() }"), - enabled("{ object.isEnabled() }"), - disabled("{ !object.isEnabled() }"), - selected("{ object.isSelected() }"), - deselected("{ !object.isSelected() }"); - - final String code; - - PseudoClassEnum(String code) { - this.code = code; - } - - public String getCode() { - return code; - } - } - - public static void applyPseudoClass(String pseudoClass, - Map<String, String> properties, - CompiledObject object, - JAXXCompiler compiler, - int priority) throws CompilerException { - if (pseudoClass.contains("[")) { - pseudoClass = pseudoClass.substring(0, pseudoClass.indexOf("[")); - } - StringBuilder buffer = new StringBuilder(); - - DefaultObjectHandler handler = - TagManager.getTagHandler(object.getObjectClass()); - boolean valueDeclared = false; - String eol = JAXXCompiler.getLineSeparator(); - DataBindingHelper bindingHelper = compiler.getBindingHelper(); - - String pseudoClassesPrefix = null; - String dataBindingPrefix = null; - - if (!properties.isEmpty()) { - pseudoClassesPrefix = compiler.getImportedType(Pseudoclasses.class); - dataBindingPrefix = compiler.getImportedType(jaxx.runtime.css.DataBinding.class); - } - - String outputClassName = - compiler.getImportedType(compiler.getOutputClassName()); - - for (Map.Entry<String, String> e : properties.entrySet()) { - String property = e.getKey(); - ClassDescriptor type = handler.getPropertyType(object, - property, - compiler - ); - if (log.isDebugEnabled()) { - log.debug("will test if databinding : [" + e.getValue() + - "] type=" + type); - } - String dataBindingCode = - DataBindingHelper.processDataBindings(e.getValue()); - String valueCode; - String simpleType = compiler.getImportedType(JAXXCompiler.getCanonicalName(type)); - - if (dataBindingCode != null) { - String code = object.getId() + "." + property + "." + priority; - valueCode = "new " + dataBindingPrefix + "(" + - TypeManager.getJavaCode(code) + ")"; - DataBinding binding = new DataBinding( - code, - dataBindingCode, - handler.getSetPropertyCode( - object.getJavaCode(), - property, - "(" + simpleType + ") " + dataBindingCode, -// "(" + JAXXCompiler.getCanonicalName(type) + ") " + dataBindingCode, - compiler - ), - false - ); - bindingHelper.registerDataBinding(binding); - } else { - try { - Class<?> typeClass = type != null ? - ClassDescriptorHelper.getClass( - type.getName(), - type.getClassLoader() - ) : - null; - valueCode = TypeManager.getJavaCode( - TypeManager.convertFromString(e.getValue(), typeClass) - ); - } catch (ClassNotFoundException ex) { - compiler.reportError( - "could not find class " + type.getName()); - return; - } - } - if (!valueDeclared) { - buffer.append("Object "); - valueDeclared = true; - } - - buffer.append("value = "); - buffer.append(pseudoClassesPrefix); - buffer.append(".applyProperty("); - buffer.append(outputClassName); - buffer.append(".this, "); - buffer.append(object.getJavaCode()); - buffer.append(", "); - buffer.append(TypeManager.getJavaCode(property)); - buffer.append(", "); - buffer.append(valueCode); - buffer.append(", "); - buffer.append(pseudoClassesPrefix); - buffer.append(".wrap("); - buffer.append(handler.getGetPropertyCode(object.getJavaCode(), property, compiler)); - buffer.append("), "); - buffer.append(priority); - buffer.append(");"); - buffer.append(eol); - - buffer.append("if (!(value instanceof "); - buffer.append(dataBindingPrefix); - buffer.append(")) {"); - buffer.append(eol); - - String unwrappedValue = unwrap(type, "value"); - buffer.append(" "); - buffer.append(handler.getSetPropertyCode(object.getJavaCode(), property, "(" + simpleType + ") " + unwrappedValue, compiler)); - buffer.append(eol); - buffer.append("}").append(eol); - } - - try { - PseudoClassEnum classEnum = PseudoClassEnum.valueOf(pseudoClass); - pseudoClass = classEnum.getCode(); - } catch (IllegalArgumentException e) { - // should never happens ? -// throw new RuntimeException("could not find " + PseudoClassEnum.class + " with pseudoClass " + pseudoClass, e); - } - - compilePseudoClass(pseudoClass, object, buffer.toString(), 0, "add", compiler, false); - - buffer.setLength(0); - valueDeclared = false; - for (Map.Entry<String, String> e : properties.entrySet()) { - String property = e.getKey(); - ClassDescriptor type = handler.getPropertyType(object, property, compiler); - String simpleType = compiler.getImportedType(JAXXCompiler.getCanonicalName(type)); - if (log.isDebugEnabled()) { - log.debug("will test if databinding : [" + e.getValue() + "] type=" + type); - } - String dataBindingCode = DataBindingHelper.processDataBindings(e.getValue()); - String valueCode; - if (dataBindingCode != null) { - String code = object.getId() + "." + property + "." + priority; - valueCode = "new " + dataBindingPrefix + "(" + TypeManager.getJavaCode(code) + ")"; - DataBinding binding = new DataBinding( - code, - dataBindingCode, - handler.getSetPropertyCode( - object.getJavaCode(), - property, - "(" + simpleType + ") " + dataBindingCode, - compiler - ), - false - ); - bindingHelper.registerDataBinding(binding); - } else { - try { - Class<?> typeClass = - type != null ? - ClassDescriptorHelper.getClass(type.getName(), type.getClassLoader()) : - null; - valueCode = TypeManager.getJavaCode(TypeManager.convertFromString(e.getValue(), typeClass)); - } catch (ClassNotFoundException ex) { - compiler.reportError("could not find class " + type.getName()); - return; - } - } - if (!valueDeclared) { - buffer.append("Object "); - valueDeclared = true; - } - buffer.append("value = ").append(pseudoClassesPrefix).append(".removeProperty("); - - buffer.append(outputClassName); - buffer.append(".this, "); - buffer.append(object.getJavaCode()); - buffer.append(", "); - buffer.append(TypeManager.getJavaCode(property)); - buffer.append(", "); - buffer.append(valueCode); - buffer.append(", ").append(pseudoClassesPrefix).append(".wrap("); - buffer.append(handler.getGetPropertyCode(object.getJavaCode(), - property, - compiler) - ); - buffer.append("), "); - buffer.append(priority); - buffer.append(");"); - buffer.append(eol); - - buffer.append("if (!(value instanceof "); - buffer.append(dataBindingPrefix); - buffer.append(")) {"); - buffer.append(eol); - -// String simpleType = importManager.getType(JAXXCompiler.getCanonicalName(type)); - String unwrappedValue = unwrap(type, "value"); - buffer.append(" "); - buffer.append(handler.getSetPropertyCode( - object.getJavaCode(), - property, - "(" + simpleType + ") " + unwrappedValue, - compiler) - ); - buffer.append(eol); - buffer.append("}").append(eol); - } - compilePseudoClass(pseudoClass, - object, - buffer.toString(), - 1, - "remove", - compiler, - true - ); - } - - - public static void compilePseudoClass(String pseudoClass, - CompiledObject object, - String propertyCode, - int pos, - String methodName, - JAXXCompiler compiler, - boolean invertTest) throws CompilerException { - - PseudoClassDataBinding binding = - PseudoClassDataBinding.newPseudoClassDataBinding( - pseudoClass, - object, - propertyCode, - methodName, - invertTest - ); - if (binding != null) { - compiler.getBindingHelper().registerDataBinding(binding); - return; - } - MouseEventEnum constant = MouseEventEnum.valueOf(pseudoClass); - String property = constant.getProperty(pos); - MethodDescriptor addMouseListener = getAddMouseListenerMethod(object); - MethodDescriptor methodDescriptor = - getMouseListenerMethod(object, property); - object.addEventHandler("style." + pseudoClass + "." + methodName, - addMouseListener, - methodDescriptor, - propertyCode, - compiler - ); - } - - public static Map<String, String> getApplicableProperties( - Stylesheet s, CompiledObject object) throws CompilerException { - DefaultObjectHandler handler = - TagManager.getTagHandler(object.getObjectClass()); - Map<String, String> result = null; - for (Rule rule : s.getRules()) { - int apply = appliesTo(rule, object); - if (apply == Selector.ALWAYS_APPLIES || - apply == Selector.ALWAYS_APPLIES_INHERIT_ONLY) { - if (result == null) { - result = new HashMap<>(); - } - for (Map.Entry<String, String> entry : - rule.getProperties().entrySet()) { - String property = entry.getKey(); - if (apply == Selector.ALWAYS_APPLIES || - handler.isPropertyInherited(property)) { - result.put(property, entry.getValue()); - } - } - } - } - return result; - } - - public static Rule[] getApplicablePseudoClasses( - Stylesheet s, CompiledObject object) throws CompilerException { - List<Rule> result = null; - for (Rule rule : s.getRules()) { - if (appliesTo(rule, object) == Selector.PSEUDOCLASS_APPLIES) { - if (result == null) { - result = new ArrayList<>(); - } - result.add(rule); - } - } - return result != null ? result.toArray(new Rule[result.size()]) : null; - } - - public static Rule inlineAttribute(CompiledObject object, - String propertyName, - boolean dataBinding) { - Map<String, String> properties = new HashMap<>(); - properties.put(propertyName, dataBinding ? - Rule.DATA_BINDING : - Rule.INLINE_ATTRIBUTE); - return new Rule(new Selector[]{ - new Selector(null, null, null, object.getId(), true)}, - properties - ); - } - - public static int appliesTo(Rule rule, - CompiledObject object) throws CompilerException { - int appliesTo = Selector.NEVER_APPLIES; - for (Selector selector : rule.getSelectors()) { - appliesTo = Math.max(appliesTo(selector, object), appliesTo); - if (appliesTo == Selector.ALWAYS_APPLIES || - appliesTo == Selector.ALWAYS_APPLIES_INHERIT_ONLY) { - break; - } - } - return appliesTo; - } - - public static int appliesTo(Selector selector, CompiledObject object) { - boolean inheritOnly = false; - CompiledObject parent = object; - String javaClassName = selector.getJavaClassName(); - String styleClass = selector.getStyleClass(); - String pseudoClass = selector.getPseudoClass(); - String id = selector.getId(); - - while (parent != null) { - boolean classMatch = javaClassName == null; - if (!classMatch) { - ClassDescriptor javaClass = parent.getObjectClass(); - do { - String name = javaClass.getName(); - if (name.equals(javaClassName) || - name.substring(name.lastIndexOf(".") + 1).equals(javaClassName)) { - classMatch = true; - break; - } - javaClass = javaClass.getSuperclass(); - } while (javaClass != null); - } - - boolean styleClassMatch = styleClass == null || - styleClass.equals(parent.getStyleClass()); - - String objectId = parent.getId(); - objectId = objectId.substring(objectId.lastIndexOf(".") + 1); - boolean idMatch = id == null || - (' ' + objectId + ' ').contains(' ' + id + ' '); - - if (classMatch && styleClassMatch && idMatch) { - if (pseudoClass != null) { - return inheritOnly ? - Selector.PSEUDOCLASS_APPLIES_INHERIT_ONLY : - Selector.PSEUDOCLASS_APPLIES; - } else { - return inheritOnly ? - Selector.ALWAYS_APPLIES_INHERIT_ONLY : - Selector.ALWAYS_APPLIES; - } - } - - parent = parent.getParent(); - inheritOnly = true; - } - return Selector.NEVER_APPLIES; - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParser.java b/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParser.java deleted file mode 100644 index dd6d9fb..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParser.java +++ /dev/null @@ -1,831 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JJTree&JavaCC: Do not edit this line. CSSParser.java */ - -package jaxx.compiler.css.parser; - -public class CSSParser/*@bgen(jjtree)*/ implements CSSParserTreeConstants, CSSParserConstants {/*@bgen(jjtree)*/ - - protected JJTCSSParserState jjtree = new JJTCSSParserState(); - - public SimpleNode popNode() { - if (jjtree.nodeArity() > 0) // number of child nodes - return (SimpleNode) jjtree.popNode(); - else - return null; - } - - void jjtreeOpenNodeScope(Node n) { - ((SimpleNode) n).firstToken = getToken(1); - } - - void jjtreeCloseNodeScope(Node n) { - ((SimpleNode) n).lastToken = getToken(0); - } - - public static void main(String args[]) { - System.out.println("Reading from standard input..."); - CSSParser css = new CSSParser(System.in); - try { - SimpleNode n = css.Stylesheet(); - n.dump(""); - System.out.println("Thank you."); - } catch (Exception e) { - System.out.println("Oops."); - System.out.println(e.getMessage()); - e.printStackTrace(); - } - } - - final public SimpleNode Stylesheet() throws ParseException { - /*@bgen(jjtree) Stylesheet */ - SimpleNode jjtn000 = new SimpleNode(JJTSTYLESHEET); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - label_1: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENTIFIER: - case PSEUDOCLASS_COLON: - case 29: - case 30: - case 31: - ; - break; - default: - jj_la1[0] = jj_gen; - break label_1; - } - Rule(); - } - jjtree.closeNodeScope(jjtn000, true); - jjtc000 = false; - jjtreeCloseNodeScope(jjtn000); - { - if (true) return jjtn000; - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - throw new Error("Missing return statement in function"); - } - - final public void Rule() throws ParseException { - /*@bgen(jjtree) Rule */ - SimpleNode jjtn000 = new SimpleNode(JJTRULE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - Selectors(); - jj_consume_token(LEFT_BRACE); - Declaration(); - label_2: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SEMICOLON: - ; - break; - default: - jj_la1[1] = jj_gen; - break label_2; - } - jj_consume_token(SEMICOLON); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENTIFIER: - Declaration(); - break; - default: - jj_la1[2] = jj_gen; - ; - } - } - jj_consume_token(RIGHT_BRACE); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void Selectors() throws ParseException { - /*@bgen(jjtree) Selectors */ - SimpleNode jjtn000 = new SimpleNode(JJTSELECTORS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - Selector(); - label_3: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case 28: - ; - break; - default: - jj_la1[3] = jj_gen; - break label_3; - } - jj_consume_token(28); - Selector(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void Selector() throws ParseException { - /*@bgen(jjtree) Selector */ - SimpleNode jjtn000 = new SimpleNode(JJTSELECTOR); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENTIFIER: - case 29: - JavaClass(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case 30: - Id(); - break; - default: - jj_la1[4] = jj_gen; - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case 31: - Class(); - break; - default: - jj_la1[5] = jj_gen; - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PSEUDOCLASS_COLON: - PseudoClass(); - break; - default: - jj_la1[6] = jj_gen; - ; - } - break; - case 30: - Id(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case 31: - Class(); - break; - default: - jj_la1[7] = jj_gen; - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PSEUDOCLASS_COLON: - PseudoClass(); - break; - default: - jj_la1[8] = jj_gen; - ; - } - break; - case 31: - Class(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PSEUDOCLASS_COLON: - PseudoClass(); - break; - default: - jj_la1[9] = jj_gen; - ; - } - break; - case PSEUDOCLASS_COLON: - PseudoClass(); - break; - default: - jj_la1[10] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void JavaClass() throws ParseException { - /*@bgen(jjtree) JavaClass */ - SimpleNode jjtn000 = new SimpleNode(JJTJAVACLASS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENTIFIER: - jj_consume_token(IDENTIFIER); - break; - case 29: - jj_consume_token(29); - break; - default: - jj_la1[11] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void Id() throws ParseException { - /*@bgen(jjtree) Id */ - SimpleNode jjtn000 = new SimpleNode(JJTID); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(30); - jj_consume_token(IDENTIFIER); - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void Class() throws ParseException { - /*@bgen(jjtree) Class */ - SimpleNode jjtn000 = new SimpleNode(JJTCLASS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(31); - jj_consume_token(IDENTIFIER); - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void PseudoClass() throws ParseException { - /*@bgen(jjtree) PseudoClass */ - SimpleNode jjtn000 = new SimpleNode(JJTPSEUDOCLASS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(PSEUDOCLASS_COLON); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PSEUDOCLASS_IDENTIFIER: - jj_consume_token(PSEUDOCLASS_IDENTIFIER); - break; - case PROGRAMMATIC_PSEUDOCLASS: - jj_consume_token(PROGRAMMATIC_PSEUDOCLASS); - break; - default: - jj_la1[12] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case 32: - AnimationProperties(); - break; - default: - jj_la1[13] = jj_gen; - ; - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void AnimationProperties() throws ParseException { - /*@bgen(jjtree) AnimationProperties */ - SimpleNode jjtn000 = new SimpleNode(JJTANIMATIONPROPERTIES); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(32); - AnimationProperty(); - label_4: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case 28: - ; - break; - default: - jj_la1[14] = jj_gen; - break label_4; - } - jj_consume_token(28); - AnimationProperty(); - } - jj_consume_token(33); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void AnimationProperty() throws ParseException { - /*@bgen(jjtree) AnimationProperty */ - SimpleNode jjtn000 = new SimpleNode(JJTANIMATIONPROPERTY); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(IDENTIFIER); - jj_consume_token(34); - jj_consume_token(DECIMAL_LITERAL); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENTIFIER: - jj_consume_token(IDENTIFIER); - break; - default: - jj_la1[15] = jj_gen; - ; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void Declaration() throws ParseException { - /*@bgen(jjtree) Declaration */ - SimpleNode jjtn000 = new SimpleNode(JJTDECLARATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - Property(); - jj_consume_token(COLON); - Expression(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void Property() throws ParseException { - /*@bgen(jjtree) Property */ - SimpleNode jjtn000 = new SimpleNode(JJTPROPERTY); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(IDENTIFIER); - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void Expression() throws ParseException { - /*@bgen(jjtree) Expression */ - SimpleNode jjtn000 = new SimpleNode(JJTEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case DECIMAL_LITERAL: - jj_consume_token(DECIMAL_LITERAL); - break; - case STRING: - jj_consume_token(STRING); - break; - case IDENTIFIER: - jj_consume_token(IDENTIFIER); - break; - case HEXCOLOR: - jj_consume_token(HEXCOLOR); - break; - case EMS: - jj_consume_token(EMS); - break; - case EXS: - jj_consume_token(EXS); - break; - case LENGTH: - jj_consume_token(LENGTH); - break; - case JAVA_CODE_START: - JavaCode(); - break; - default: - jj_la1[16] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void JavaCode() throws ParseException { - /*@bgen(jjtree) JavaCode */ - SimpleNode jjtn000 = new SimpleNode(JJTJAVACODE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(JAVA_CODE_START); - jj_consume_token(JAVA_CODE); - jj_consume_token(JAVA_CODE_END); - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void Identifier() throws ParseException { - /*@bgen(jjtree) Identifier */ - SimpleNode jjtn000 = new SimpleNode(JJTIDENTIFIER); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(IDENTIFIER); - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - public CSSParserTokenManager token_source; - - SimpleCharStream jj_input_stream; - - public Token token, jj_nt; - - private int jj_ntk; - - private int jj_gen; - - final private int[] jj_la1 = new int[17]; - - static private int[] jj_la1_0; - - static private int[] jj_la1_1; - - static { - jj_la1_0(); - jj_la1_1(); - } - - private static void jj_la1_0() { - jj_la1_0 = new int[]{0xe0002200, 0x8000, 0x200, 0x10000000, 0x40000000, 0x80000000, 0x2000, 0x80000000, 0x2000, 0x2000, 0xe0002200, 0x20000200, 0x201000, 0x0, 0x10000000, 0x200, 0xec40280,}; - } - - private static void jj_la1_1() { - jj_la1_1 = new int[]{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,}; - } - - public CSSParser(java.io.InputStream stream) { - this(stream, null); - } - - public CSSParser(java.io.InputStream stream, String encoding) { - try { - jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); - } catch (java.io.UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - token_source = new CSSParserTokenManager(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 17; i++) jj_la1[i] = -1; - } - - public void ReInit(java.io.InputStream stream) { - ReInit(stream, null); - } - - public void ReInit(java.io.InputStream stream, String encoding) { - try { - jj_input_stream.ReInit(stream, encoding, 1, 1); - } catch (java.io.UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - token_source.ReInit(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jjtree.reset(); - jj_gen = 0; - for (int i = 0; i < 17; i++) jj_la1[i] = -1; - } - - public CSSParser(java.io.Reader stream) { - jj_input_stream = new SimpleCharStream(stream, 1, 1); - token_source = new CSSParserTokenManager(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 17; i++) jj_la1[i] = -1; - } - - public void ReInit(java.io.Reader stream) { - jj_input_stream.ReInit(stream, 1, 1); - token_source.ReInit(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jjtree.reset(); - jj_gen = 0; - for (int i = 0; i < 17; i++) jj_la1[i] = -1; - } - - public CSSParser(CSSParserTokenManager tm) { - token_source = tm; - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 17; i++) jj_la1[i] = -1; - } - - public void ReInit(CSSParserTokenManager tm) { - token_source = tm; - token = new Token(); - jj_ntk = -1; - jjtree.reset(); - jj_gen = 0; - for (int i = 0; i < 17; i++) jj_la1[i] = -1; - } - - final private Token jj_consume_token(int kind) throws ParseException { - Token oldToken; - if ((oldToken = token).next != null) token = token.next; - else token = token.next = token_source.getNextToken(); - jj_ntk = -1; - if (token.kind == kind) { - jj_gen++; - return token; - } - token = oldToken; - jj_kind = kind; - throw generateParseException(); - } - - final public Token getNextToken() { - if (token.next != null) token = token.next; - else token = token.next = token_source.getNextToken(); - jj_ntk = -1; - jj_gen++; - return token; - } - - final public Token getToken(int index) { - Token t = token; - for (int i = 0; i < index; i++) { - if (t.next != null) t = t.next; - else t = t.next = token_source.getNextToken(); - } - return t; - } - - final private int jj_ntk() { - if ((jj_nt = token.next) == null) - return (jj_ntk = (token.next = token_source.getNextToken()).kind); - else - return (jj_ntk = jj_nt.kind); - } - - private java.util.Vector jj_expentries = new java.util.Vector(); - - private int[] jj_expentry; - - private int jj_kind = -1; - - public ParseException generateParseException() { - Token errortok = token.next; - int line = errortok.beginLine, column = errortok.beginColumn; - String mess = (errortok.kind == 0) ? tokenImage[0] : errortok.image; - return new ParseException("Parse error. Encountered: " + mess, line, column); - } - - final public void enable_tracing() { - } - - final public void disable_tracing() { - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserConstants.java b/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserConstants.java deleted file mode 100644 index 22774f6..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserConstants.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JJTree&JavaCC: Do not edit this line. CSSParserConstants.java */ - -package jaxx.compiler.css.parser; - -public interface CSSParserConstants { - - int EOF = 0; - - int DECIMAL_LITERAL = 7; - - int INTEGER_LITERAL = 8; - - int IDENTIFIER = 9; - - int LETTER = 10; - - int DIGIT = 11; - - int PSEUDOCLASS_IDENTIFIER = 12; - - int PSEUDOCLASS_COLON = 13; - - int COLON = 14; - - int SEMICOLON = 15; - - int LEFT_BRACE = 16; - - int RIGHT_BRACE = 17; - - int JAVA_CODE_START = 18; - - int JAVA_CODE = 19; - - int JAVA_CODE_END = 20; - - int PROGRAMMATIC_PSEUDOCLASS = 21; - - int STRING = 22; - - int HEXCOLOR = 23; - - int HEXDIGIT = 24; - - int EMS = 25; - - int EXS = 26; - - int LENGTH = 27; - - int DEFAULT = 0; - - int IN_RULE = 1; - - int JAVA_CODE_RULE = 2; - - int IN_PSEUDOCLASS = 3; - - String[] tokenImage = { - "<EOF>", - "\" \"", - "\"\\t\"", - "\"\\n\"", - "\"\\r\"", - "<token of kind 5>", - "<token of kind 6>", - "<DECIMAL_LITERAL>", - "<INTEGER_LITERAL>", - "<IDENTIFIER>", - "<LETTER>", - "<DIGIT>", - "<PSEUDOCLASS_IDENTIFIER>", - "\":\"", - "\":\"", - "\";\"", - "\"{\"", - "\"}\"", - "<JAVA_CODE_START>", - "<JAVA_CODE>", - "<JAVA_CODE_END>", - "<PROGRAMMATIC_PSEUDOCLASS>", - "<STRING>", - "<HEXCOLOR>", - "<HEXDIGIT>", - "<EMS>", - "<EXS>", - "<LENGTH>", - "\",\"", - "\"*\"", - "\"#\"", - "\".\"", - "\"[\"", - "\"]\"", - "\"=\"", - }; - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserTokenManager.java b/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserTokenManager.java deleted file mode 100644 index a75517b..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserTokenManager.java +++ /dev/null @@ -1,1176 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JJTree&JavaCC: Do not edit this line. CSSParserTokenManager.java */ - -package jaxx.compiler.css.parser; - -public class CSSParserTokenManager implements CSSParserConstants { - public java.io.PrintStream debugStream = System.out; - - public void setDebugStream(java.io.PrintStream ds) { - debugStream = ds; - } - - private int jjStopStringLiteralDfa_0(int pos, long active0) { - switch (pos) { - default: - return -1; - } - } - - private int jjStartNfa_0(int pos, long active0) { - return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1); - } - - private int jjStopAtPos(int pos, int kind) { - jjmatchedKind = kind; - jjmatchedPos = pos; - return pos + 1; - } - - private int jjStartNfaWithStates_0(int pos, int kind, int state) { - jjmatchedKind = kind; - jjmatchedPos = pos; - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - return pos + 1; - } - return jjMoveNfa_0(state, pos + 1); - } - - private int jjMoveStringLiteralDfa0_0() { - switch (curChar) { - case 35: - return jjStopAtPos(0, 30); - case 42: - return jjStopAtPos(0, 29); - case 44: - return jjStopAtPos(0, 28); - case 46: - return jjStopAtPos(0, 31); - case 58: - return jjStopAtPos(0, 13); - case 59: - return jjStopAtPos(0, 15); - case 61: - return jjStopAtPos(0, 34); - case 91: - return jjStopAtPos(0, 32); - case 93: - return jjStopAtPos(0, 33); - case 123: - return jjStopAtPos(0, 16); - default: - return jjMoveNfa_0(3, 0); - } - } - - private void jjCheckNAdd(int state) { - if (jjrounds[state] != jjround) { - jjstateSet[jjnewStateCnt++] = state; - jjrounds[state] = jjround; - } - } - - private void jjAddStates(int start, int end) { - do { - jjstateSet[jjnewStateCnt++] = jjnextStates[start]; - } while (start++ != end); - } - - private void jjCheckNAddTwoStates(int state1, int state2) { - jjCheckNAdd(state1); - jjCheckNAdd(state2); - } - - private void jjCheckNAddStates(int start, int end) { - do { - jjCheckNAdd(jjnextStates[start]); - } while (start++ != end); - } - - private void jjCheckNAddStates(int start) { - jjCheckNAdd(jjnextStates[start]); - jjCheckNAdd(jjnextStates[start + 1]); - } - - static final long[] jjbitVec0 = { - 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL - }; - - private int jjMoveNfa_0(int startState, int curPos) { - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 17; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (; ; ) { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) { - long l = 1L << curChar; - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 3: - if ((0x3ff000000000000L & l) != 0L) { - if (kind > 7) - kind = 7; - jjCheckNAddTwoStates(0, 1); - } else if (curChar == 47) - jjAddStates(0, 1); - else if (curChar == 45) { - if (kind > 9) - kind = 9; - jjCheckNAdd(4); - } - break; - case 0: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 7) - kind = 7; - jjCheckNAddTwoStates(0, 1); - break; - case 1: - if (curChar == 46) - jjCheckNAdd(2); - break; - case 2: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 7) - kind = 7; - jjCheckNAdd(2); - break; - case 4: - if ((0x3ff200000000000L & l) == 0L) - break; - if (kind > 9) - kind = 9; - jjCheckNAdd(4); - break; - case 5: - if (curChar == 47) - jjAddStates(0, 1); - break; - case 6: - if (curChar == 47) - jjCheckNAddStates(2, 4); - break; - case 7: - if ((0xffffffffffffdbffL & l) != 0L) - jjCheckNAddStates(2, 4); - break; - case 8: - if ((0x2400L & l) != 0L && kind > 5) - kind = 5; - break; - case 9: - if (curChar == 10 && kind > 5) - kind = 5; - break; - case 10: - if (curChar == 13) - jjstateSet[jjnewStateCnt++] = 9; - break; - case 11: - if (curChar == 42) - jjCheckNAddTwoStates(12, 13); - break; - case 12: - if ((0xfffffbffffffffffL & l) != 0L) - jjCheckNAddTwoStates(12, 13); - break; - case 13: - if (curChar == 42) - jjAddStates(5, 6); - break; - case 14: - if ((0xffff7fffffffffffL & l) != 0L) - jjCheckNAddTwoStates(15, 13); - break; - case 15: - if ((0xfffffbffffffffffL & l) != 0L) - jjCheckNAddTwoStates(15, 13); - break; - case 16: - if (curChar == 47 && kind > 6) - kind = 6; - break; - default: - break; - } - } while (i != startsAt); - } else if (curChar < 128) { - long l = 1L << (curChar & 077); - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 3: - case 4: - if ((0x7fffffe87fffffeL & l) == 0L) - break; - if (kind > 9) - kind = 9; - jjCheckNAdd(4); - break; - case 7: - jjAddStates(2, 4); - break; - case 12: - jjCheckNAddTwoStates(12, 13); - break; - case 14: - case 15: - jjCheckNAddTwoStates(15, 13); - break; - default: - break; - } - } while (i != startsAt); - } else { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 7: - if ((jjbitVec0[i2] & l2) != 0L) - jjAddStates(2, 4); - break; - case 12: - if ((jjbitVec0[i2] & l2) != 0L) - jjCheckNAddTwoStates(12, 13); - break; - case 14: - case 15: - if ((jjbitVec0[i2] & l2) != 0L) - jjCheckNAddTwoStates(15, 13); - break; - default: - break; - } - } while (i != startsAt); - } - if (kind != 0x7fffffff) { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 17 - (jjnewStateCnt = startsAt))) - return curPos; - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - return curPos; - } - } - } - - private int jjStopStringLiteralDfa_3(int pos, long active0) { - switch (pos) { - default: - return -1; - } - } - - private int jjStartNfa_3(int pos, long active0) { - return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1); - } - - private int jjStartNfaWithStates_3(int pos, int kind, int state) { - jjmatchedKind = kind; - jjmatchedPos = pos; - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - return pos + 1; - } - return jjMoveNfa_3(state, pos + 1); - } - - private int jjMoveStringLiteralDfa0_3() { - switch (curChar) { - case 59: - return jjStopAtPos(0, 15); - default: - return jjMoveNfa_3(3, 0); - } - } - - private int jjMoveNfa_3(int startState, int curPos) { - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 8; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (; ; ) { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) { - long l = 1L << curChar; - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 3: - if ((0x3ff000000000000L & l) != 0L) { - if (kind > 7) - kind = 7; - jjCheckNAddTwoStates(0, 1); - } else if (curChar == 45) { - if (kind > 12) - kind = 12; - jjCheckNAdd(4); - } - break; - case 0: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 7) - kind = 7; - jjCheckNAddTwoStates(0, 1); - break; - case 1: - if (curChar == 46) - jjCheckNAdd(2); - break; - case 2: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 7) - kind = 7; - jjCheckNAdd(2); - break; - case 4: - if ((0x3ff200000000000L & l) == 0L) - break; - if (kind > 12) - kind = 12; - jjCheckNAdd(4); - break; - case 6: - jjAddStates(7, 8); - break; - default: - break; - } - } while (i != startsAt); - } else if (curChar < 128) { - long l = 1L << (curChar & 077); - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 3: - if ((0x7fffffe87fffffeL & l) != 0L) { - if (kind > 12) - kind = 12; - jjCheckNAdd(4); - } else if (curChar == 123) - jjCheckNAdd(6); - break; - case 4: - if ((0x7fffffe87fffffeL & l) == 0L) - break; - if (kind > 12) - kind = 12; - jjCheckNAdd(4); - break; - case 5: - if (curChar == 123) - jjCheckNAdd(6); - break; - case 6: - if ((0xdfffffffffffffffL & l) != 0L) - jjCheckNAddTwoStates(6, 7); - break; - case 7: - if (curChar == 125) - kind = 21; - break; - default: - break; - } - } while (i != startsAt); - } else { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 6: - if ((jjbitVec0[i2] & l2) != 0L) - jjAddStates(7, 8); - break; - default: - break; - } - } while (i != startsAt); - } - if (kind != 0x7fffffff) { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 8 - (jjnewStateCnt = startsAt))) - return curPos; - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - return curPos; - } - } - } - - private int jjStopStringLiteralDfa_1(int pos, long active0) { - switch (pos) { - default: - return -1; - } - } - - private int jjStartNfa_1(int pos, long active0) { - return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1); - } - - private int jjStartNfaWithStates_1(int pos, int kind, int state) { - jjmatchedKind = kind; - jjmatchedPos = pos; - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - return pos + 1; - } - return jjMoveNfa_1(state, pos + 1); - } - - private int jjMoveStringLiteralDfa0_1() { - switch (curChar) { - case 58: - return jjStopAtPos(0, 14); - case 59: - return jjStopAtPos(0, 15); - case 125: - return jjStopAtPos(0, 17); - default: - return jjMoveNfa_1(0, 0); - } - } - - private int jjMoveNfa_1(int startState, int curPos) { - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 50; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (; ; ) { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) { - long l = 1L << curChar; - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 0: - if ((0x3ff000000000000L & l) != 0L) { - if (kind > 7) - kind = 7; - jjCheckNAddStates(9, 22); - } else if (curChar == 47) - jjAddStates(23, 24); - else if (curChar == 35) - jjstateSet[jjnewStateCnt++] = 7; - else if (curChar == 34) - jjCheckNAddTwoStates(4, 5); - else if (curChar == 45) { - if (kind > 9) - kind = 9; - jjCheckNAdd(1); - } - break; - case 1: - if ((0x3ff200000000000L & l) == 0L) - break; - if (kind > 9) - kind = 9; - jjCheckNAdd(1); - break; - case 3: - if (curChar == 34) - jjCheckNAddTwoStates(4, 5); - break; - case 4: - if ((0xfffffffbffffdbffL & l) != 0L) - jjCheckNAddTwoStates(4, 5); - break; - case 5: - if (curChar == 34 && kind > 22) - kind = 22; - break; - case 6: - if (curChar == 35) - jjstateSet[jjnewStateCnt++] = 7; - break; - case 7: - if ((0x3ff000000000000L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 8; - break; - case 8: - if ((0x3ff000000000000L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 9; - break; - case 9: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 23) - kind = 23; - jjstateSet[jjnewStateCnt++] = 10; - break; - case 10: - if ((0x3ff000000000000L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 11; - break; - case 11: - if ((0x3ff000000000000L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 12; - break; - case 12: - if ((0x3ff000000000000L & l) != 0L && kind > 23) - kind = 23; - break; - case 13: - if (curChar == 47) - jjAddStates(23, 24); - break; - case 14: - if (curChar == 47) - jjCheckNAddStates(25, 27); - break; - case 15: - if ((0xffffffffffffdbffL & l) != 0L) - jjCheckNAddStates(25, 27); - break; - case 16: - if ((0x2400L & l) != 0L && kind > 5) - kind = 5; - break; - case 17: - if (curChar == 10 && kind > 5) - kind = 5; - break; - case 18: - if (curChar == 13) - jjstateSet[jjnewStateCnt++] = 17; - break; - case 19: - if (curChar == 42) - jjCheckNAddTwoStates(20, 21); - break; - case 20: - if ((0xfffffbffffffffffL & l) != 0L) - jjCheckNAddTwoStates(20, 21); - break; - case 21: - if (curChar == 42) - jjAddStates(28, 29); - break; - case 22: - if ((0xffff7fffffffffffL & l) != 0L) - jjCheckNAddTwoStates(23, 21); - break; - case 23: - if ((0xfffffbffffffffffL & l) != 0L) - jjCheckNAddTwoStates(23, 21); - break; - case 24: - if (curChar == 47 && kind > 6) - kind = 6; - break; - case 25: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 7) - kind = 7; - jjCheckNAddStates(9, 22); - break; - case 26: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 7) - kind = 7; - jjCheckNAddTwoStates(26, 27); - break; - case 27: - if (curChar == 46) - jjCheckNAdd(28); - break; - case 28: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 7) - kind = 7; - jjCheckNAdd(28); - break; - case 29: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddStates(30, 32); - break; - case 30: - if (curChar == 46) - jjCheckNAdd(31); - break; - case 31: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddTwoStates(31, 33); - break; - case 34: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddStates(33, 35); - break; - case 35: - if (curChar == 46) - jjCheckNAdd(36); - break; - case 36: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddTwoStates(36, 38); - break; - case 39: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddStates(36, 41); - break; - case 40: - if (curChar == 46) - jjCheckNAdd(41); - break; - case 41: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddStates(42, 46); - break; - default: - break; - } - } while (i != startsAt); - } else if (curChar < 128) { - long l = 1L << (curChar & 077); - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 0: - if ((0x7fffffe87fffffeL & l) != 0L) { - if (kind > 9) - kind = 9; - jjCheckNAdd(1); - } else if (curChar == 123) { - if (kind > 18) - kind = 18; - } - break; - case 1: - if ((0x7fffffe87fffffeL & l) == 0L) - break; - if (kind > 9) - kind = 9; - jjCheckNAdd(1); - break; - case 2: - if (curChar == 123 && kind > 18) - kind = 18; - break; - case 4: - if ((0xffffffffefffffffL & l) != 0L) - jjAddStates(47, 48); - break; - case 7: - if ((0x7e0000007eL & l) != 0L) - jjstateSet[jjnewStateCnt++] = 8; - break; - case 8: - if ((0x7e0000007eL & l) != 0L) - jjstateSet[jjnewStateCnt++] = 9; - break; - case 9: - if ((0x7e0000007eL & l) == 0L) - break; - if (kind > 23) - kind = 23; - jjstateSet[jjnewStateCnt++] = 10; - break; - case 10: - if ((0x7e0000007eL & l) != 0L) - jjstateSet[jjnewStateCnt++] = 11; - break; - case 11: - if ((0x7e0000007eL & l) != 0L) - jjstateSet[jjnewStateCnt++] = 12; - break; - case 12: - if ((0x7e0000007eL & l) != 0L && kind > 23) - kind = 23; - break; - case 15: - jjAddStates(25, 27); - break; - case 20: - jjCheckNAddTwoStates(20, 21); - break; - case 22: - case 23: - jjCheckNAddTwoStates(23, 21); - break; - case 32: - if (curChar == 109 && kind > 25) - kind = 25; - break; - case 33: - if (curChar == 101) - jjstateSet[jjnewStateCnt++] = 32; - break; - case 37: - if (curChar == 120 && kind > 26) - kind = 26; - break; - case 38: - if (curChar == 101) - jjstateSet[jjnewStateCnt++] = 37; - break; - case 42: - if (curChar == 109 && kind > 27) - kind = 27; - break; - case 43: - if (curChar == 109) - jjCheckNAdd(42); - break; - case 44: - if (curChar == 99) - jjCheckNAdd(42); - break; - case 45: - if (curChar == 110 && kind > 27) - kind = 27; - break; - case 46: - if (curChar == 105) - jjstateSet[jjnewStateCnt++] = 45; - break; - case 47: - if (curChar == 112) - jjAddStates(49, 50); - break; - case 48: - if (curChar == 116 && kind > 27) - kind = 27; - break; - case 49: - if (curChar == 99 && kind > 27) - kind = 27; - break; - default: - break; - } - } while (i != startsAt); - } else { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 4: - if ((jjbitVec0[i2] & l2) != 0L) - jjAddStates(47, 48); - break; - case 15: - if ((jjbitVec0[i2] & l2) != 0L) - jjAddStates(25, 27); - break; - case 20: - if ((jjbitVec0[i2] & l2) != 0L) - jjCheckNAddTwoStates(20, 21); - break; - case 22: - case 23: - if ((jjbitVec0[i2] & l2) != 0L) - jjCheckNAddTwoStates(23, 21); - break; - default: - break; - } - } while (i != startsAt); - } - if (kind != 0x7fffffff) { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 50 - (jjnewStateCnt = startsAt))) - return curPos; - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - return curPos; - } - } - } - - private int jjStopStringLiteralDfa_2(int pos, long active0) { - switch (pos) { - default: - return -1; - } - } - - private int jjStartNfa_2(int pos, long active0) { - return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1); - } - - private int jjStartNfaWithStates_2(int pos, int kind, int state) { - jjmatchedKind = kind; - jjmatchedPos = pos; - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - return pos + 1; - } - return jjMoveNfa_2(state, pos + 1); - } - - private int jjMoveStringLiteralDfa0_2() { - switch (curChar) { - case 59: - return jjStartNfaWithStates_2(0, 15, 3); - default: - return jjMoveNfa_2(4, 0); - } - } - - private int jjMoveNfa_2(int startState, int curPos) { - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 5; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (; ; ) { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) { - long l = 1L << curChar; - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 4: - if (kind > 19) - kind = 19; - jjCheckNAdd(3); - if ((0x3ff000000000000L & l) != 0L) { - if (kind > 7) - kind = 7; - jjCheckNAddTwoStates(0, 1); - } - break; - case 0: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 7) - kind = 7; - jjCheckNAddTwoStates(0, 1); - break; - case 1: - if (curChar == 46) - jjCheckNAdd(2); - break; - case 2: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 7) - kind = 7; - jjCheckNAdd(2); - break; - case 3: - if (kind > 19) - kind = 19; - jjCheckNAdd(3); - break; - default: - break; - } - } while (i != startsAt); - } else if (curChar < 128) { - long l = 1L << (curChar & 077); - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 4: - if ((0xdfffffffffffffffL & l) != 0L) { - if (kind > 19) - kind = 19; - jjCheckNAdd(3); - } else if (curChar == 125) { - if (kind > 20) - kind = 20; - } - break; - case 3: - if ((0xdfffffffffffffffL & l) == 0L) - break; - kind = 19; - jjCheckNAdd(3); - break; - default: - break; - } - } while (i != startsAt); - } else { - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 4: - case 3: - if ((jjbitVec0[i2] & l2) == 0L) - break; - if (kind > 19) - kind = 19; - jjCheckNAdd(3); - break; - default: - break; - } - } while (i != startsAt); - } - if (kind != 0x7fffffff) { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 5 - (jjnewStateCnt = startsAt))) - return curPos; - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - return curPos; - } - } - } - - static final int[] jjnextStates = { - 6, 11, 7, 8, 10, 14, 16, 6, 7, 26, 27, 29, 30, 33, 34, 35, - 38, 39, 40, 43, 44, 46, 47, 14, 19, 15, 16, 18, 22, 24, 29, 30, - 33, 34, 35, 38, 39, 40, 43, 44, 46, 47, 41, 43, 44, 46, 47, 4, - 5, 48, 49, - }; - - public static final String[] jjstrLiteralImages = { - "", null, null, null, null, null, null, null, null, null, null, null, null, - "\72", "\72", "\73", "\173", "\175", null, null, null, null, null, null, null, null, - null, null, "\54", "\52", "\43", "\56", "\133", "\135", "\75",}; - - public static final String[] lexStateNames = { - "DEFAULT", - "IN_RULE", - "JAVA_CODE_RULE", - "IN_PSEUDOCLASS", - }; - - public static final int[] jjnewLexState = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 3, -1, -1, 1, 0, 2, -1, 1, 0, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - }; - - static final long[] jjtoToken = { - 0x7fefff281L, - }; - - static final long[] jjtoSkip = { - 0x7eL, - }; - - protected SimpleCharStream input_stream; - - private final int[] jjrounds = new int[50]; - - private final int[] jjstateSet = new int[100]; - - protected char curChar; - - public CSSParserTokenManager(SimpleCharStream stream) { - if (SimpleCharStream.staticFlag) - throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); - input_stream = stream; - } - - public CSSParserTokenManager(SimpleCharStream stream, int lexState) { - this(stream); - SwitchTo(lexState); - } - - public void ReInit(SimpleCharStream stream) { - jjmatchedPos = jjnewStateCnt = 0; - curLexState = defaultLexState; - input_stream = stream; - ReInitRounds(); - } - - private void ReInitRounds() { - int i; - jjround = 0x80000001; - for (i = 50; i-- > 0; ) - jjrounds[i] = 0x80000000; - } - - public void ReInit(SimpleCharStream stream, int lexState) { - ReInit(stream); - SwitchTo(lexState); - } - - public void SwitchTo(int lexState) { - if (lexState >= 4 || lexState < 0) - throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); - else - curLexState = lexState; - } - - protected Token jjFillToken() { - Token t = Token.newToken(jjmatchedKind); - t.kind = jjmatchedKind; - String im = jjstrLiteralImages[jjmatchedKind]; - t.image = (im == null) ? input_stream.GetImage() : im; - t.beginLine = input_stream.getBeginLine(); - t.beginColumn = input_stream.getBeginColumn(); - t.endLine = input_stream.getEndLine(); - t.endColumn = input_stream.getEndColumn(); - return t; - } - - int curLexState = 0; - - int defaultLexState = 0; - - int jjnewStateCnt; - - int jjround; - - int jjmatchedPos; - - int jjmatchedKind; - - public Token getNextToken() { - int kind; - Token specialToken = null; - Token matchedToken; - int curPos = 0; - - EOFLoop: - for (; ; ) { - try { - curChar = input_stream.BeginToken(); - } catch (java.io.IOException e) { - jjmatchedKind = 0; - matchedToken = jjFillToken(); - return matchedToken; - } - - switch (curLexState) { - case 0: - try { - input_stream.backup(0); - while (curChar <= 32 && (0x100002600L & (1L << curChar)) != 0L) - curChar = input_stream.BeginToken(); - } catch (java.io.IOException e1) { - continue EOFLoop; - } - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_0(); - break; - case 1: - try { - input_stream.backup(0); - while (curChar <= 32 && (0x100002600L & (1L << curChar)) != 0L) - curChar = input_stream.BeginToken(); - } catch (java.io.IOException e1) { - continue EOFLoop; - } - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_1(); - break; - case 2: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_2(); - break; - case 3: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_3(); - break; - } - if (jjmatchedKind != 0x7fffffff) { - if (jjmatchedPos + 1 < curPos) - input_stream.backup(curPos - jjmatchedPos - 1); - if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) { - matchedToken = jjFillToken(); - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - return matchedToken; - } else { - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - continue EOFLoop; - } - } - int error_line = input_stream.getEndLine(); - int error_column = input_stream.getEndColumn(); - String error_after = null; - boolean EOFSeen = false; - try { - input_stream.readChar(); - input_stream.backup(1); - } catch (java.io.IOException e1) { - EOFSeen = true; - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - if (curChar == '\n' || curChar == '\r') { - error_line++; - error_column = 0; - } else - error_column++; - } - if (!EOFSeen) { - input_stream.backup(1); - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - } - throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); - } - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserTreeConstants.java b/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserTreeConstants.java deleted file mode 100644 index 3a97370..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserTreeConstants.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JJTree: Do not edit this line. .\CSSParserTreeConstants.java */ - - -package jaxx.compiler.css.parser; - -public interface CSSParserTreeConstants { - int JJTSTYLESHEET = 0; - - int JJTRULE = 1; - - int JJTSELECTORS = 2; - - int JJTSELECTOR = 3; - - int JJTJAVACLASS = 4; - - int JJTID = 5; - - int JJTCLASS = 6; - - int JJTPSEUDOCLASS = 7; - - int JJTANIMATIONPROPERTIES = 8; - - int JJTANIMATIONPROPERTY = 9; - - int JJTDECLARATION = 10; - - int JJTPROPERTY = 11; - - int JJTEXPRESSION = 12; - - int JJTJAVACODE = 13; - - int JJTIDENTIFIER = 14; - - - String[] jjtNodeName = { - "Stylesheet", - "Rule", - "Selectors", - "Selector", - "JavaClass", - "Id", - "Class", - "PseudoClass", - "AnimationProperties", - "AnimationProperty", - "Declaration", - "Property", - "Expression", - "JavaCode", - "Identifier", - }; -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/JJTCSSParserState.java b/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/JJTCSSParserState.java deleted file mode 100644 index aaa5b40..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/JJTCSSParserState.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JJTree: Do not edit this line. .\JJTCSSParserState.java */ - - -package jaxx.compiler.css.parser; - -class JJTCSSParserState { - private java.util.Stack<Node> nodes; - - private java.util.Stack<Integer> marks; - - private int sp; // number of nodes on stack - - private int mk; // current mark - - private boolean node_created; - - JJTCSSParserState() { - nodes = new java.util.Stack<>(); - marks = new java.util.Stack<>(); - sp = 0; - mk = 0; - } - - /* Determines whether the current node was actually closed and - pushed. This should only be called in the final user action of a - node scope. */ - boolean nodeCreated() { - return node_created; - } - - /* Call this to reinitialize the node stack. It is called -automatically by the parser's ReInit() method. */ - void reset() { - nodes.removeAllElements(); - marks.removeAllElements(); - sp = 0; - mk = 0; - } - - /* Returns the root node of the AST. It only makes sense to call -this after a successful parse. */ - Node rootNode() { - return nodes.elementAt(0); - } - - /* Pushes a node on to the stack. */ - void pushNode(Node n) { - nodes.push(n); - ++sp; - } - - /* Returns the node on the top of the stack, and remove it from the - stack. */ - Node popNode() { - if (--sp < mk) { - mk = marks.pop(); - } - return nodes.pop(); - } - - /* Returns the node currently on the top of the stack. */ - Node peekNode() { - return nodes.peek(); - } - - /* Returns the number of children on the stack in the current node - scope. */ - int nodeArity() { - return sp - mk; - } - - - void clearNodeScope(Node n) { - while (sp > mk) { - popNode(); - } - mk = marks.pop(); - } - - - void openNodeScope(Node n) { - marks.push(mk); - mk = sp; - n.jjtOpen(); - } - - - /* A definite node is constructed from a specified number of -children. That number of nodes are popped from the stack and -made the children of the definite node. Then the definite node -is pushed on to the stack. */ - void closeNodeScope(Node n, int num) { - mk = marks.pop(); - while (num-- > 0) { - Node c = popNode(); - c.jjtSetParent(n); - n.jjtAddChild(c, num); - } - n.jjtClose(); - pushNode(n); - node_created = true; - } - - - /* A conditional node is constructed if its condition is true. All -the nodes that have been pushed since the node was opened are -made children of the the conditional node, which is then pushed -on to the stack. If the condition is false the node is not -constructed and they are left on the stack. */ - void closeNodeScope(Node n, boolean condition) { - if (condition) { - int a = nodeArity(); - mk = marks.pop(); - while (a-- > 0) { - Node c = popNode(); - c.jjtSetParent(n); - n.jjtAddChild(c, a); - } - n.jjtClose(); - pushNode(n); - node_created = true; - } else { - mk = marks.pop(); - node_created = false; - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/Node.java b/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/Node.java deleted file mode 100644 index 8c532ac..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/Node.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JJTree: Do not edit this line. Node.java */ - - -package jaxx.compiler.css.parser; - -/* All AST nodes must implement this interface. It provides basic - machinery for constructing the parent and child relationships - between nodes. */ - -public interface Node { - - /** - * This method is called after the node has been made the current - * node. It indicates that child nodes can now be added to it. - */ - public void jjtOpen(); - - /** - * This method is called after all the child nodes have been - * added. - */ - public void jjtClose(); - - /** - * This pair of methods are used to inform the node of its - * parent. - * - * @param n node - */ - public void jjtSetParent(Node n); - - public Node jjtGetParent(); - - /** - * This method tells the node to add its argument to the node's - * list of children. - * - * @param n node - * @param i pos - */ - public void jjtAddChild(Node n, int i); - - /** - * @param i pos - * @return a child node. The children are numbered - * from zero, left to right. - */ - public Node jjtGetChild(int i); - - /** @return the number of children the node has. */ - public int jjtGetNumChildren(); -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/ParseException.java b/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/ParseException.java deleted file mode 100644 index 03dad51..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/ParseException.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */ - -package jaxx.compiler.css.parser; - -public class ParseException extends jaxx.compiler.java.parser.ParseException { - private static final long serialVersionUID = 229575674880359031L; - - public ParseException() { - super(); - } - - - public ParseException(String message) { - super(message); - } - - - public ParseException(String message, int line, int column) { - super(message, line, column); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/SimpleCharStream.java b/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/SimpleCharStream.java deleted file mode 100644 index a84b46c..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/SimpleCharStream.java +++ /dev/null @@ -1,429 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.0 */ - -package jaxx.compiler.css.parser; - -/** - * An implementation of interface CharStream, where the stream is assumed to - * contain only ASCII characters (without unicode processing). - */ - -public class SimpleCharStream { - public static final boolean staticFlag = false; - - int bufsize; - - int available; - - int tokenBegin; - - public int bufpos = -1; - - protected int bufline[]; - - protected int bufcolumn[]; - - protected int column = 0; - - protected int line = 1; - - protected boolean prevCharIsCR = false; - - protected boolean prevCharIsLF = false; - - protected java.io.Reader inputStream; - - protected char[] buffer; - - protected int maxNextCharInd = 0; - - protected int inBuf = 0; - - protected int tabSize = 8; - - protected void setTabSize(int i) { - tabSize = i; - } - - protected int getTabSize(int i) { - return tabSize; - } - - - protected void ExpandBuff(boolean wrapAround) { - char[] newbuffer = new char[bufsize + 2048]; - int newbufline[] = new int[bufsize + 2048]; - int newbufcolumn[] = new int[bufsize + 2048]; - - try { - if (wrapAround) { - System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); - System.arraycopy(buffer, 0, newbuffer, - bufsize - tokenBegin, bufpos); - buffer = newbuffer; - - System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); - System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); - bufline = newbufline; - - System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); - System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); - bufcolumn = newbufcolumn; - - maxNextCharInd = (bufpos += (bufsize - tokenBegin)); - } else { - System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); - buffer = newbuffer; - - System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); - bufline = newbufline; - - System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); - bufcolumn = newbufcolumn; - - maxNextCharInd = (bufpos -= tokenBegin); - } - } catch (Throwable t) { - throw new Error(t.getMessage()); - } - - - bufsize += 2048; - available = bufsize; - tokenBegin = 0; - } - - protected void FillBuff() throws java.io.IOException { - if (maxNextCharInd == available) { - if (available == bufsize) { - if (tokenBegin > 2048) { - bufpos = maxNextCharInd = 0; - available = tokenBegin; - } else if (tokenBegin < 0) - bufpos = maxNextCharInd = 0; - else - ExpandBuff(false); - } else if (available > tokenBegin) - available = bufsize; - else if ((tokenBegin - available) < 2048) - ExpandBuff(true); - else - available = tokenBegin; - } - - int i; - try { - if ((i = inputStream.read(buffer, maxNextCharInd, - available - maxNextCharInd)) == -1) { - inputStream.close(); - throw new java.io.IOException(); - } else - maxNextCharInd += i; - } catch (java.io.IOException e) { - --bufpos; - backup(0); - if (tokenBegin == -1) - tokenBegin = bufpos; - throw e; - } - } - - public char BeginToken() throws java.io.IOException { - tokenBegin = -1; - char c = readChar(); - tokenBegin = bufpos; - - return c; - } - - protected void UpdateLineColumn(char c) { - column++; - - if (prevCharIsLF) { - prevCharIsLF = false; - line += (column = 1); - } else if (prevCharIsCR) { - prevCharIsCR = false; - if (c == '\n') { - prevCharIsLF = true; - } else - line += (column = 1); - } - - switch (c) { - case '\r': - prevCharIsCR = true; - break; - case '\n': - prevCharIsLF = true; - break; - case '\t': - column--; - column += (tabSize - (column % tabSize)); - break; - default: - break; - } - - bufline[bufpos] = line; - bufcolumn[bufpos] = column; - } - - public char readChar() throws java.io.IOException { - if (inBuf > 0) { - --inBuf; - - if (++bufpos == bufsize) - bufpos = 0; - - return buffer[bufpos]; - } - - if (++bufpos >= maxNextCharInd) - FillBuff(); - - char c = buffer[bufpos]; - - UpdateLineColumn(c); - return (c); - } - - /** - * @return ??? - * @see #getEndColumn - * @deprecated - */ - - public int getColumn() { - return bufcolumn[bufpos]; - } - - /** - * @return ??? - * @see #getEndLine - * @deprecated - */ - - public int getLine() { - return bufline[bufpos]; - } - - public int getEndColumn() { - return bufcolumn[bufpos]; - } - - public int getEndLine() { - return bufline[bufpos]; - } - - public int getBeginColumn() { - return bufcolumn[tokenBegin]; - } - - public int getBeginLine() { - return bufline[tokenBegin]; - } - - public void backup(int amount) { - - inBuf += amount; - if ((bufpos -= amount) < 0) - bufpos += bufsize; - } - - public SimpleCharStream(java.io.Reader dstream, int startline, - int startcolumn, int buffersize) { - inputStream = dstream; - line = startline; - column = startcolumn - 1; - - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - } - - public SimpleCharStream(java.io.Reader dstream, int startline, - int startcolumn) { - this(dstream, startline, startcolumn, 4096); - } - - public SimpleCharStream(java.io.Reader dstream) { - this(dstream, 1, 1, 4096); - } - - public void ReInit(java.io.Reader dstream, int startline, - int startcolumn, int buffersize) { - inputStream = dstream; - line = startline; - column = startcolumn - 1; - - if (buffer == null || buffersize != buffer.length) { - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - } - prevCharIsLF = prevCharIsCR = false; - tokenBegin = inBuf = maxNextCharInd = 0; - bufpos = -1; - } - - public void ReInit(java.io.Reader dstream, int startline, - int startcolumn) { - ReInit(dstream, startline, startcolumn, 4096); - } - - public void ReInit(java.io.Reader dstream) { - ReInit(dstream, 1, 1, 4096); - } - - public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, - int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { - this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); - } - - public SimpleCharStream(java.io.InputStream dstream, int startline, - int startcolumn, int buffersize) { - this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); - } - - public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, - int startcolumn) throws java.io.UnsupportedEncodingException { - this(dstream, encoding, startline, startcolumn, 4096); - } - - public SimpleCharStream(java.io.InputStream dstream, int startline, - int startcolumn) { - this(dstream, startline, startcolumn, 4096); - } - - public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { - this(dstream, encoding, 1, 1, 4096); - } - - public SimpleCharStream(java.io.InputStream dstream) { - this(dstream, 1, 1, 4096); - } - - public void ReInit(java.io.InputStream dstream, String encoding, int startline, - int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { - ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); - } - - public void ReInit(java.io.InputStream dstream, int startline, - int startcolumn, int buffersize) { - ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); - } - - public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { - ReInit(dstream, encoding, 1, 1, 4096); - } - - public void ReInit(java.io.InputStream dstream) { - ReInit(dstream, 1, 1, 4096); - } - - public void ReInit(java.io.InputStream dstream, String encoding, int startline, - int startcolumn) throws java.io.UnsupportedEncodingException { - ReInit(dstream, encoding, startline, startcolumn, 4096); - } - - public void ReInit(java.io.InputStream dstream, int startline, - int startcolumn) { - ReInit(dstream, startline, startcolumn, 4096); - } - - public String GetImage() { - if (bufpos >= tokenBegin) - return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); - else - return new String(buffer, tokenBegin, bufsize - tokenBegin) + - new String(buffer, 0, bufpos + 1); - } - - public char[] GetSuffix(int len) { - char[] ret = new char[len]; - - if ((bufpos + 1) >= len) - System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); - else { - System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, - len - bufpos - 1); - System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); - } - - return ret; - } - - public void Done() { - buffer = null; - bufline = null; - bufcolumn = null; - } - - /** - * Method to adjust line and column numbers for the start of a token. - * - * @param newLine ? - * @param newCol ? - */ - public void adjustBeginLineColumn(int newLine, int newCol) { - int start = tokenBegin; - int len; - - if (bufpos >= tokenBegin) { - len = bufpos - tokenBegin + inBuf + 1; - } else { - len = bufsize - tokenBegin + bufpos + 1 + inBuf; - } - - int i = 0, j = 0, k; - int nextColDiff, columnDiff = 0; - - while (i < len && - bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) { - bufline[j] = newLine; - nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; - bufcolumn[j] = newCol + columnDiff; - columnDiff = nextColDiff; - i++; - } - - if (i < len) { - bufline[j] = newLine++; - bufcolumn[j] = newCol + columnDiff; - - while (i++ < len) { - if (bufline[j = start % bufsize] != bufline[++start % bufsize]) - bufline[j] = newLine++; - else - bufline[j] = newLine; - } - } - - line = bufline[j]; - column = bufcolumn[j]; - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/SimpleNode.java b/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/SimpleNode.java deleted file mode 100644 index 19a84a1..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/SimpleNode.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JJTree: Do not edit this line. SimpleNode.java */ - - -package jaxx.compiler.css.parser; - -public class SimpleNode implements Node { - protected Node parent; - - protected Node[] children; - - protected int id; - - protected CSSParser parser; - - public Token firstToken; - - public Token lastToken; - - - public SimpleNode(int i) { - id = i; - } - - public SimpleNode(CSSParser p, int i) { - this(i); - parser = p; - } - - - public int getId() { - return id; - } - - public void jjtOpen() { - } - - public void jjtClose() { - } - - public void jjtSetParent(Node n) { - parent = n; - } - - public Node jjtGetParent() { - return parent; - } - - public SimpleNode getParent() { - return (SimpleNode) parent; - } - - public void jjtAddChild(Node n, int i) { - if (children == null) { - children = new Node[i + 1]; - } else if (i >= children.length) { - Node c[] = new Node[i + 1]; - System.arraycopy(children, 0, c, 0, children.length); - children = c; - } - children[i] = n; - } - - public Node jjtGetChild(int i) { - return children[i]; - } - - public SimpleNode getChild(int i) { - return (SimpleNode) children[i]; - } - - public int jjtGetNumChildren() { - return children == null ? 0 : children.length; - } - - /* You can override these two methods in subclasses of SimpleNode to -customize the way the node appears when the tree is dumped. If -your output uses more than one line you should override -toString(String), otherwise overriding toString() is probably all -you need to do. */ - - @Override - public String toString() { - return getClass().getName() + "[" + getText() + "]"; - } - - public String toString(String prefix) { - return prefix + toString(); - } - - /* Override this method if you want to customize how the node dumps - out its children. */ - - public void dump(String prefix) { - System.out.println(toString(prefix)); - if (children != null) { - for (Node aChildren : children) { - SimpleNode n = (SimpleNode) aChildren; - if (n != null) { - n.dump(prefix + " "); - } - } - } - } - - private void appendSpecialTokens(StringBuilder s, Token st) { - if (st != null) { - appendSpecialTokens(s, st.specialToken); - s.append(st.image); - } - } - - - /** @return the text of the tokens comprising this node. */ - public String getText() { - StringBuilder text = new StringBuilder(); - Token t = firstToken; - while (t != null) { - appendSpecialTokens(text, t.specialToken); - text.append(t.image); - if (t == lastToken) - break; - t = t.next; - } - - return text.toString(); - } -} - diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/Token.java b/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/Token.java deleted file mode 100644 index d07fbee..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/Token.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */ - -package jaxx.compiler.css.parser; - -/** Describes the input token stream. */ - -public class Token { - - /** - * An integer that describes the kind of this token. This numbering - * system is determined by JavaCCParser, and a table of these numbers is - * stored in the file ...Constants.java. - */ - public int kind; - - /** - * beginLine and beginColumn describe the position of the first character - * of this token; endLine and endColumn describe the position of the - * last character of this token. - */ - public int beginLine, beginColumn, endLine, endColumn; - - /** The string image of the token. */ - public String image; - - /** - * A reference to the next regular (non-special) token from the input - * stream. If this is the last token from the input stream, or if the - * token manager has not read tokens beyond this one, this field is - * set to null. This is true only if this token is also a regular - * token. Otherwise, see below for a description of the contents of - * this field. - */ - public Token next; - - /** - * This field is used to access special tokens that occur prior to this - * token, but after the immediately preceding regular (non-special) token. - * If there are no such special tokens, this field is set to null. - * When there are more than one such special token, this field refers - * to the last of these special tokens, which in turn refers to the next - * previous special token through its specialToken field, and so on - * until the first special token (whose specialToken field is null). - * The next fields of special tokens refer to other special tokens that - * immediately follow it (without an intervening regular token). If there - * is no such token, this field is null. - */ - public Token specialToken; - - /** Returns the image. */ - public String toString() { - return image; - } - - /** - * Returns a new Token object, by default. However, if you want, you - * can create and return subclass objects based on the value of ofKind. - * Simply add the cases to the switch for all those special cases. - * For example, if you have a subclass of Token called IDToken that - * you want to create if ofKind is ID, simlpy add something like : - * - * case MyParserConstants.ID : return new IDToken(); - * - * to the following switch statement. Then you can cast matchedToken - * variable to the appropriate type and use it in your lexical actions. - * - * @param ofKind kind of token - * @return the new token - */ - public static Token newToken(int ofKind) { - switch (ofKind) { - default: - return new Token(); - } - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/TokenMgrError.java b/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/TokenMgrError.java deleted file mode 100644 index d7b95cd..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/TokenMgrError.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */ - -package jaxx.compiler.css.parser; - -public class TokenMgrError extends Error { - /* - * Ordinals for various reasons why an Error of this type can be thrown. - */ - - /** Lexical error occured. */ - static final int LEXICAL_ERROR = 0; - - /** An attempt wass made to create a second instance of a static token manager. */ - static final int STATIC_LEXER_ERROR = 1; - - /** Tried to change to an invalid lexical state. */ - static final int INVALID_LEXICAL_STATE = 2; - - /** Detected (and bailed out of) an infinite loop in the token manager. */ - static final int LOOP_DETECTED = 3; - - /** - * Indicates the reason why the exception is thrown. It will have - * one of the above 4 values. - */ - int errorCode; - - private static final long serialVersionUID = -4308847190164230336L; - - /** - * Replaces unprintable characters by their espaced (or unicode escaped) - * equivalents in the given string - * - * @param str text to espace - * @return the espaced text - */ - protected static String addEscapes(String str) { - StringBuilder retval = new StringBuilder(); - char ch; - for (int i = 0; i < str.length(); i++) { - switch (str.charAt(i)) { - case 0: - continue; - case '\b': - retval.append("\\b"); - continue; - case '\t': - retval.append("\\t"); - continue; - case '\n': - retval.append("\\n"); - continue; - case '\f': - retval.append("\\f"); - continue; - case '\r': - retval.append("\\r"); - continue; - case '\"': - retval.append("\\\""); - continue; - case '\'': - retval.append("\\\'"); - continue; - case '\\': - retval.append("\\\\"); - continue; - default: - if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { - String s = "0000" + Integer.toString(ch, 16); - retval.append("\\u").append(s.substring(s.length() - 4, s.length())); - } else { - retval.append(ch); - } - } - } - return retval.toString(); - } - - /** - * @param EOFSeen : indicates if EOF caused the lexicl error - * @param lexState : lexical state in which this error occured - * @param errorLine : line number when the error occured - * @param errorColumn : column number when the error occured - * @param errorAfter : prefix that was seen before this error occured - * @param curChar : the offending character - * Note: You can customize the lexical error message by modifying this method. - * @return a detailed message for the Error when it is thrown by the - * token manager to indicate a lexical error. - */ - protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { - return "Lexical error at line " + - errorLine + ", column " + - errorColumn + ". Encountered: " + - (EOFSeen ? "<EOF> " : "\"" + addEscapes(String.valueOf(curChar)) + "\"" + " (" + (int) curChar + "), ") + - "after : \"" + addEscapes(errorAfter) + "\""; - } - - /** - * You can also modify the body of this method to customize your error messages. - * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not - * of end-users concern, so you can return something like : - * - * "Internal Error : Please file a bug report .... " - * - * from this method for such cases in the release version of your parser. - */ - @Override - public String getMessage() { - return super.getMessage(); - } - - /* - * Constructors of various flavors follow. - */ - - public TokenMgrError() { - } - - public TokenMgrError(String message, int reason) { - super(message); - errorCode = reason; - } - - public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { - this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/decorators/BoxedCompiledObjectDecorator.java b/jaxx-compiler/src/main/java/jaxx/compiler/decorators/BoxedCompiledObjectDecorator.java deleted file mode 100644 index 8162923..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/decorators/BoxedCompiledObjectDecorator.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.decorators; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompiledObject.ChildRef; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.java.JavaFile; -import jaxx.runtime.SwingUtil; - -/** - * A decorator to surround a compiled object (should be a component at least) - * with a JXLayer. - * - * @author Tony Chemit - chemit@codelutin.com - * @plexus.component role-hint="boxed" role="jaxx.compiler.CompiledObjectDecorator" - * @since 1.2 - */ -public class BoxedCompiledObjectDecorator extends DefaultCompiledObjectDecorator { - - @Override - public String getName() { - return "boxed"; - } - - @Override - public void finalizeCompiler(JAXXCompiler compiler, - CompiledObject root, - CompiledObject object, - JavaFile javaFile, - String packageName, - String className, - String fullClassName) throws ClassNotFoundException { - CompiledObject parent = object.getParent(); - if (parent == null) { - parent = root; - } - for (ChildRef child : parent.getChilds()) { - if (child.getChild() == object) { - String javaCode = child.getChildJavaCode(); - String type = compiler.getImportedType(SwingUtil.class); - child.setChildJavaCode( - type + - ".boxComponentWithJxLayer(" + javaCode + ")"); - break; - } - } - super.finalizeCompiler(compiler, - root, - object, - javaFile, - packageName, - className, - fullClassName - ); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java b/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java deleted file mode 100644 index 86f2fb8..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java +++ /dev/null @@ -1,359 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.decorators; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompiledObjectDecorator; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.finalizers.JAXXCompilerFinalizer; -import jaxx.compiler.java.JavaElementFactory; -import jaxx.compiler.java.JavaField; -import jaxx.compiler.java.JavaFile; -import jaxx.compiler.java.JavaMethod; -import jaxx.compiler.script.ScriptInitializer; -import jaxx.compiler.types.TypeManager; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.lang.reflect.Modifier; -import java.util.Map.Entry; - -/** - * The default decorator to use on all compiled objects. - * - * @author Tony Chemit - chemit@codelutin.com - * @plexus.component role-hint="default" role="jaxx.compiler.CompiledObjectDecorator" - * @since 1.2 - */ -public class DefaultCompiledObjectDecorator implements CompiledObjectDecorator { - - - /** Logger */ - protected static final Log log = - LogFactory.getLog(DefaultCompiledObjectDecorator.class); - - @Override - public String getName() { - return "default"; - } - - @Override - public void finalizeCompiler(JAXXCompiler compiler, - CompiledObject root, - CompiledObject object, - JavaFile javaFile, - String packageName, - String className, - String fullClassName) throws ClassNotFoundException { - - if (object instanceof ScriptInitializer) { - - // nothing to finalize - return; - } - - String fqn = JAXXCompiler.getCanonicalName(object); - - String id = object.getId(); - - if (log.isDebugEnabled()) { - log.debug("finalize " + id); - } - - boolean override = object.isOverride(); - - if (override) { - - if (object.isOverrideType()) { - - // add a specialized getter, only if type has changed - - String methodName = object.getGetterName(); - - String type = object.getSimpleType(); - String body = "return (" + type + ") super." + methodName + "();"; - - if (log.isDebugEnabled()) { - log.debug("Add specialized getter " + methodName + " : " + body); - } - JavaMethod getter = JavaElementFactory.newMethod( - Modifier.PUBLIC, - fqn, - methodName, - body, - true - ); - javaFile.addMethod(getter); - } - } else { - - int access = id.startsWith("$") ? Modifier.PRIVATE : - Modifier.PROTECTED; - if (root.equals(object)) { - - // add the generic type if required - String type = className + root.getGenericTypes(); - - JavaField field = JavaElementFactory.newField(access, - type, - id, - false, - null - ); - - javaFile.addSimpleField(field); - } else { - - JavaField field = JavaElementFactory.newField(access, - fqn, - id, - override - ); - javaFile.addField(field, object.isJavaBean()); - } - } - - if (compiler.inlineCreation(object) || root.equals(object)) { - - // nothing more to do here - return; - } - - String code = getCreationCode(compiler, object); - - // tchemit 20100519 Do not add the method only if overriden and code is null - - if (code != null) { - - JavaMethod javaMethod = JavaElementFactory.newMethod( - Modifier.PROTECTED, - JAXXCompilerFinalizer.TYPE_VOID, - object.getCreationMethodName(), - code, - override - ); - javaFile.addMethod(javaMethod); - } - } - - @Override - public String getCreationCode(JAXXCompiler compiler, - CompiledObject object) throws CompilerException { - if (object instanceof ScriptInitializer) { - throw new IllegalStateException( - "A script initializer can not come in getCreationcode method!"); - } - String eol = JAXXCompiler.getLineSeparator(); - - StringBuilder result = new StringBuilder(); - StringBuilder init = new StringBuilder(); - - if (compiler.getRootObject().equals(object) || - compiler.inlineCreation(object)) { - result.append("// inline creation of ").append(object.getId()); - } - - if (object.isJavaBean() && object.getJavaBeanInitCode() != null) { - init.append(object.getJavaBeanInitCode()); - } else if (object.getInitializer() != null) { - init.append(object.getInitializer()); - } - - boolean addToObjectMap = true; - String id = TypeManager.getJavaCode(object.getId()); - String constructorParams = object.getConstructorParams(); - - if (object.isOverride()) { - - if (init.length() == 0 && constructorParams == null) { - - // no init code is given, no need to add to objectMap - addToObjectMap = false; - } - } - - if (addToObjectMap && init.length() == 0) { - - // on special init, use constructor - String canonicalName = JAXXCompiler.getCanonicalName(object); - String impl = compiler.getImportedType(canonicalName); - - init.append("new ").append(impl).append("("); - - if (constructorParams != null) { - init.append(constructorParams); - } - init.append(")"); - } - - String superCall = "super." + object.getCreationMethodName() + "();"; - - if (addToObjectMap) { - result.append(eol); - result.append("$objectMap.put("); - result.append(id); - result.append(", "); - result.append(object.getId()).append(" = "); - result.append(init); - result.append(");"); - result.append(eol); - } else { - if (object.isOverride()) { - - // when override has no special init code, just use the super method - - result.append(superCall); - - } - } - - String initCode = object.getInitializationCode(compiler); - if (StringUtils.isNotEmpty(initCode)) { - result.append(eol).append(initCode); - } - - // add client properties - addClientProperties(object, result, eol); - - String code = result.toString(); - - if (!compiler.inlineCreation(object) && - object.isOverride() && - superCall.equals(code.trim())) { - - // special case : when override but do nothing more - // method creation can be skipped - return null; - } - return code; - } - - @Override - public String createCompleteSetupMethod(JAXXCompiler compiler, - CompiledObject object, - JavaFile javaFile) { - StringBuilder code = new StringBuilder(); - String eol = JAXXCompiler.getLineSeparator(); - if (object.getId().startsWith("$")) { - String additionCode = object.getAdditionCode(); - //TC-20091025 only generate the code if not empty - if (!additionCode.isEmpty()) { - code.append("// inline complete setup of "); - code.append(object.getId()); - code.append(eol); - code.append(additionCode); - } - } else { - //TODO-TC-20091202 should always create the method to make api more consistent ? - //TODO-TC-20091202 While generating, we deal with this case, it seems not sa natural - //TODO-TC-20091202 to NOT having the setup method on each public property ? -// code.append(object.getAdditionMethodName()).append("();").append(eol); -// if (!additionCode.isEmpty()) { -// additionCode = "if (!allComponentsCreated) {" + eol + " return;" + eol + "}" + eol + additionCode; -// } -// javaFile.addMethod(JavaFileGenerator.newMethod(Modifier.PROTECTED, "void", object.getAdditionMethodName(), additionCode, false)); - String additionCode = object.getAdditionCode(); - if (additionCode.length() > 0) { - code.append(object.getAdditionMethodName()).append("();").append(eol); -// additionCode = "if (!allComponentsCreated) {" + eol + " return;" + eol + "}" + eol + additionCode; - javaFile.addMethod(JavaElementFactory.newMethod( - Modifier.PROTECTED, - JAXXCompilerFinalizer.TYPE_VOID, - object.getAdditionMethodName(), - additionCode, - false) - ); - } - } - return code.toString(); - } - - @Override - public boolean createInitializer(JAXXCompiler compiler, - CompiledObject root, - CompiledObject object, - StringBuilder code, - boolean lastWasMethodCall) { - String eol = JAXXCompiler.getLineSeparator(); - - if (object instanceof ScriptInitializer) { - - // initializer has special direct treatment : can not be in a method - // just push code to compiler - code.append(object.getInitializationCode(compiler)); - - // nothing to initialize of a script - return lastWasMethodCall; - } - - if (root.equals(object)) { - String rootCode = root.getInitializationCode(compiler); - if (rootCode != null && rootCode.length() > 0) { - code.append("// inline creation of "); - code.append(object.getId()); - code.append(eol); - code.append(rootCode); - //TC-20091025 generate client properties at creation time (not at setup time) - // in some case can save to create a setup method (when there is only client properties - // to store) - addClientProperties(object, code, eol); - code.append(eol); - } - } else { - if (!object.isOverride()) { - if (compiler.inlineCreation(object)) { - if (lastWasMethodCall) { - lastWasMethodCall = false; - } - code.append(getCreationCode(compiler, object)); - } else { - code.append(object.getCreationMethodName()).append("();"); - code.append(eol); - lastWasMethodCall = true; - } - } - } - return lastWasMethodCall; - } - - protected void addClientProperties(CompiledObject object, - StringBuilder code, - String eol) { - //TC-20090327 generate client properties - if (object.hasClientProperties()) { - // generate putClientProperty invocations - for (Entry<String, String> entry : - object.getClientProperties().entrySet()) { - code.append(object.getJavaCode()); - code.append(".putClientProperty(\""); - code.append(entry.getKey()); - code.append("\", "); - code.append(entry.getValue()); - code.append(");"); - code.append(eol); - } - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java b/jaxx-compiler/src/main/java/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java deleted file mode 100644 index 28c1149..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.decorators; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompiledObjectDecorator; -import jaxx.compiler.CompilerConfiguration; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.finalizers.JAXXCompilerFinalizer; -import jaxx.compiler.java.JavaElementFactory; -import jaxx.compiler.java.JavaFile; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.runtime.swing.help.JAXXHelpUI; - -import java.awt.Component; -import java.lang.reflect.Modifier; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import static jaxx.compiler.java.JavaElementFactory.newArgument; - -/** - * A decorator to place on a root compiled object to process javaHelp on the file. - * - * @author Tony Chemit - chemit@codelutin.com - * @plexus.component role-hint="help" role="jaxx.compiler.CompiledObjectDecorator" - * @since 1.2 - */ -public class HelpRootCompiledObjectDecorator extends DefaultCompiledObjectDecorator { - - /** the list of discovered helpId */ - protected static Set<String> helpIds = new HashSet<>(); - - @Override - public String getName() { - return "help"; - } - - protected String getBrokerFQN(JAXXCompiler compiler) { - return compiler.getConfiguration().getHelpBrokerFQN(); - } - - protected String getHelpId(CompiledObject o) { - String helpID = null; - if (o.hasClientProperties()) { - helpID = o.getClientProperty("help"); - } - return helpID; - } - - @Override - public void finalizeCompiler(JAXXCompiler compiler, - CompiledObject root, - CompiledObject object, - JavaFile javaFile, - String packageName, - String className, - String fullClassName) throws ClassNotFoundException { - super.finalizeCompiler(compiler, - root, - object, - javaFile, - packageName, - className, - fullClassName) - ; - CompilerConfiguration options = compiler.getConfiguration(); - - if (options.isGenerateHelp()) { - - // add JAXXHelpUI interface - Class<?> validatorInterface = JAXXHelpUI.class; - String helpBrokerFQN = getBrokerFQN(compiler); - - boolean needInterface = isNeedInterface(compiler, - validatorInterface); - - if (needInterface) { - - // only add the contract if needed - - if (log.isDebugEnabled()) { - log.debug("Add " + validatorInterface + " on " + - javaFile.getName() + " : parent " + - JAXXCompiler.getCanonicalName( - compiler.getRootObject())); - } - - javaFile.addInterface(validatorInterface.getName() + - "<" + helpBrokerFQN + ">"); - } - - javaFile.addMethod(JavaElementFactory.newMethod( - Modifier.PUBLIC, - JAXXCompilerFinalizer.TYPE_VOID, - "registerHelpId", - "broker.installUI(component, helpId);", - true, - newArgument(helpBrokerFQN, "broker"), - newArgument(Component.class.getName(), "component"), - newArgument(JAXXCompilerFinalizer.TYPE_STRING, "helpId")) - ); - - javaFile.addMethod(JavaElementFactory.newMethod( - Modifier.PUBLIC, - JAXXCompilerFinalizer.TYPE_VOID, - "showHelp", - "getBroker().showHelp(this, helpId);", - true, - newArgument(JAXXCompilerFinalizer.TYPE_STRING, "helpId")) - ); - - StringBuilder buffer = new StringBuilder(); - - String eol = JAXXCompiler.getLineSeparator(); - -// if (options.isGenerateHelp()) { - - // add code to init javax help system - Iterator<CompiledObject> itr = compiler.getObjectCreationOrder(); - - for (; itr.hasNext(); ) { - CompiledObject o = itr.next(); - String helpID = getHelpId(o); - if (helpID != null) { - buffer.append(eol); - // detects a helpId to register - buffer.append("registerHelpId(_broker, "); - buffer.append(o.getJavaCode()); - buffer.append(", "); - buffer.append(helpID); - buffer.append(");"); - //keep the helpID for helpSet generation - helpIds.add(helpID); - } - } -// } - if (buffer.length() > 0) { - - String type = compiler.getImportedType(helpBrokerFQN); - - buffer.append(eol).append("_broker.prepareUI(this);"); - buffer.append(eol); - - // add the calls - compiler.appendLateInitializer("// help broker setup" + eol); - compiler.appendLateInitializer(type + " _broker = getBroker();"); - compiler.appendLateInitializer(buffer.toString()); - } - } - } - - /** - * Detects if the given {@code compiler} need the validatorInterface. - * - * We need to test it deeply since the interface is added by the decorator - * and is not present on the symbol table of compiled objects. - * - * @param compiler the compiler to test - * @param validatorInterface the validator interface to seek for - * @return {@code true} if we need to add the interface, {@code false} otherwise - * @throws ClassNotFoundException if could not find a class - * @since 2.4 - */ - protected boolean isNeedInterface(JAXXCompiler compiler, - Class<?> validatorInterface) throws ClassNotFoundException { - if (compiler.isSuperClassAware(validatorInterface)) { - - // parent has already the interface - return false; - } - CompiledObject root = compiler.getRootObject(); - ClassDescriptor rootObjectClass = root.getObjectClass(); - String superClassName = JAXXCompiler.getCanonicalName(rootObjectClass); - JAXXCompiler parentCompiler = compiler.getEngine().getJAXXCompiler(superClassName); - if (parentCompiler == null) { - - // parent was not compiled - return true; - } - - CompiledObjectDecorator decorator = parentCompiler.getRootObject().getDecorator(); - - if (decorator != null && decorator instanceof HelpRootCompiledObjectDecorator) { - - // parent is already with help, no need of the interface - return false; - } - - // ok must add the interface - return isNeedInterface(parentCompiler, validatorInterface); - } - - public static Set<String> getHelpIds() { - return new HashSet<>(helpIds); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/AbstractFinalizer.java b/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/AbstractFinalizer.java deleted file mode 100644 index 23e839e..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/AbstractFinalizer.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.finalizers; - -import jaxx.compiler.java.JavaElementFactory; -import jaxx.compiler.java.JavaField; -import jaxx.compiler.java.JavaFile; -import jaxx.compiler.java.JavaMethod; - -/** - * Base implementation of a {@link JAXXCompilerFinalizer}. - * - * Contains commons methods and constants. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.4 - */ -public abstract class AbstractFinalizer implements JAXXCompilerFinalizer { - - /** - * Clones the given {@code field} and adds it to the {@code file} as a - * property via the method {@link JavaFile#addField(JavaField)}. - * - * @param file the file where to add the cloned field - * @param field the field to clone - * @since 2.4 - */ - protected void addField(JavaFile file, JavaField field) { - - JavaField clonedField = JavaElementFactory.cloneField(field); - file.addField(clonedField); - } - - /** - * Clones the given {@code method} and adds it to the {@code file} as a - * simple method using the method {@link JavaFile#addMethod(JavaMethod)}. - * - * @param file the file where to add the cloned field - * @param field the field to clone - * @since 2.4 - */ - protected void addSimpleField(JavaFile file, JavaField field) { - - JavaField clonedField = JavaElementFactory.cloneField(field); - file.addSimpleField(clonedField); - } - - /** - * Clones the given {@code field} and adds it to the {@code file} as a - * simple field using the method {@link JavaFile#addSimpleField(JavaField)}. - * - * @param file the file where to add the cloned method - * @param method the method to clone - * @param types optional types to use to simplify the body of the method - * @since 2.4 - */ - protected void addMethod(JavaFile file, JavaMethod method, String... types) { - - JavaMethod clonedMethod = JavaElementFactory.cloneMethod(method); - if (types.length > 0) { - String body = clonedMethod.getBody(); - String simplifiedBody = file.simplifyCode(body, types); - clonedMethod.setBody(simplifiedBody); - } - file.addMethod(clonedMethod); - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/DefaultFinalizer.java b/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/DefaultFinalizer.java deleted file mode 100644 index afcc93f..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/DefaultFinalizer.java +++ /dev/null @@ -1,1191 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.finalizers; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompiledObjectDecorator; -import jaxx.compiler.CompilerException; -import jaxx.compiler.EventHandler; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.binding.DataBinding; -import jaxx.compiler.binding.writers.DefaultJAXXBindingWriter; -import jaxx.compiler.binding.writers.JAXXBindingWriter; -import jaxx.compiler.binding.writers.SimpleJAXXObjectBindingWriter; -import jaxx.compiler.java.JavaArgument; -import jaxx.compiler.java.JavaElementFactory; -import jaxx.compiler.java.JavaField; -import jaxx.compiler.java.JavaFile; -import jaxx.compiler.java.JavaFileGenerator; -import jaxx.compiler.java.JavaMethod; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.reflect.MethodDescriptor; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.Base64Coder; -import jaxx.runtime.JAXXBinding; -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.JAXXObjectDescriptor; -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.SwingUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.awt.Container; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import static java.lang.reflect.Modifier.FINAL; -import static java.lang.reflect.Modifier.PRIVATE; -import static java.lang.reflect.Modifier.PROTECTED; -import static java.lang.reflect.Modifier.PUBLIC; -import static java.lang.reflect.Modifier.STATIC; -import static java.lang.reflect.Modifier.isProtected; -import static java.lang.reflect.Modifier.isPublic; -import static jaxx.compiler.java.JavaElementFactory.newArgument; -import static jaxx.compiler.java.JavaElementFactory.newField; -import static jaxx.compiler.java.JavaElementFactory.newMethod; - -/** - * This class is a refactoring of the {@link JAXXCompiler}. - * - * We delegate now the generation of a {@link JAXXObject} to this class, the - * {@link JAXXCompiler} now only deals with the compilation of files. - * - * @author Tony Chemit - chemit@codelutin.com - * @plexus.component role-hint="default" role="jaxx.compiler.finalizers.JAXXCompilerFinalizer" - */ -public class DefaultFinalizer extends AbstractFinalizer { - - /** Logger. */ - protected static final Log log = LogFactory.getLog(DefaultFinalizer.class); - - private static final String PARAMETER_NAME_$BINDING = "$binding"; - - public static final String FIELD_NAME_$BINDING_SOURCES = "$bindingSources"; - - public static final String FIELD_NAME_$OBJECT_MAP = "$objectMap"; - - public static final String FIELD_NAME_$ACTIVE_BINDINGS = "$activeBindings"; - - public static final String FIELD_NAME_$PREVIOUS_VALUES = "$previousValues"; - - public static final String FIELD_NAME_$BINDINGS = "$bindings"; - - public static final String FIELD_NAME_$PROPERTY_CHANGE_SUPPORT = "$propertyChangeSupport"; - - public static final String FIELD_NAME_DELEGATE_CONTEXT = "delegateContext"; - - public static final String FIELD_NAME_SERIAL_VERSION_UID = "serialVersionUID"; - - public static final String FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR = "$jaxxObjectDescriptor"; - - public static final String METHOD_NAME_$GET_JAXXOBJECT_DESCRIPTOR = "$getJAXXObjectDescriptor"; - - public static final String METHOD_NAME_REGISTER_DATA_BINDING = "registerDataBinding"; - - public static final String METHOD_NAME_REMOVE_DATA_BINDING = "removeDataBinding"; - - public static final String METHOD_NAME_APPLY_DATA_BINDING = "applyDataBinding"; - - public static final String METHOD_NAME_PROCESS_DATA_BINDING = "processDataBinding"; - - public static final String METHOD_NAME_FIRE_PROPERTY_CHANGE = "firePropertyChange"; - - public static final String METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT = "$getPropertyChangeSupport"; - - public static final String METHOD_NAME_$INITIALIZE = "$initialize"; - public static final String METHOD_NAME_$INITIALIZE_01_CREATE_COMPONENTS = "$initialize_01_createComponents"; - public static final String METHOD_NAME_$INITIALIZE_02_REGISTER_DATA_BINDINGS = "$initialize_02_registerDataBindings"; - public static final String METHOD_NAME_$INITIALIZE_03_FINALIZE_CREATE_COMPONENTS = "$initialize_03_finalizeCreateComponents"; - public static final String METHOD_NAME_$INITIALIZE_04_APPLY_DATA_BINDINGS = "$initialize_04_applyDataBindings"; - public static final String METHOD_NAME_$INITIALIZE_05_SET_PROPERTIES = "$initialize_05_setProperties"; - public static final String METHOD_NAME_$INITIALIZE_06_FINALIZE_INITIALIZE = "$initialize_06_finalizeInitialize"; - - /** serialVersionUID field */ - - protected static final JavaField SERIAL_VERSION_UID_FIELD = newField( - PRIVATE | STATIC | FINAL, - "long", - FIELD_NAME_SERIAL_VERSION_UID, - false, - "1L" - ); - - /** - * - */ - protected static final JavaField ACTIVE_BINDINGS_FIELD = newField( - PROTECTED, - List.class.getName() + "<" + TYPE_OBJECT + ">", - FIELD_NAME_$ACTIVE_BINDINGS, - false, - "new %s<" + TYPE_OBJECT + ">()", - ArrayList.class.getName() - ); - - /** - * - */ - protected static final JavaField BINDING_SOURCES_FIELD = newField( - PROTECTED, - Map.class.getName() + "<" + TYPE_STRING + ", " + TYPE_OBJECT + ">", - FIELD_NAME_$BINDING_SOURCES, - false, - "new %s<" + TYPE_STRING + ", " + TYPE_OBJECT + ">()", - HashMap.class.getName() - ); - - /** - * - */ - protected static final JavaField OBJECT_MAP_FIELD = newField( - PROTECTED, - Map.class.getName() + "<" + TYPE_STRING + ", " + TYPE_OBJECT + ">", - FIELD_NAME_$OBJECT_MAP, - true, - "new %s<" + TYPE_STRING + ", " + TYPE_OBJECT + ">()", - HashMap.class.getName() - ); - - /** - * - */ - protected static final JavaField PREVIOUS_VALUES_FIELD = newField( - PROTECTED, - Map.class.getName() + "<?,?>", FIELD_NAME_$PREVIOUS_VALUES, - false, - "new %s<" + TYPE_OBJECT + ", " + TYPE_OBJECT + ">()", - HashMap.class.getName() - ); - - /** - * - */ - protected static final JavaField BINDINGS_FIELD = newField( - PROTECTED | FINAL, - Map.class.getName() + "<" + TYPE_STRING + ", " + JAXXBinding.class.getName() + ">", - FIELD_NAME_$BINDINGS, - false, - "new %s<" + TYPE_STRING + ", %s>()", - TreeMap.class.getName(), - JAXXBinding.class.getName() - ); - - /** - * - */ - protected static final JavaField PROPERTY_CHANGE_SUPPORT_FIELD = newField( - PROTECTED, - PropertyChangeSupport.class.getName(), - FIELD_NAME_$PROPERTY_CHANGE_SUPPORT, - false - ); - - /** - * - */ - protected static final JavaMethod GET_CONTEXT_VALUE_METHOD = newMethod( - PUBLIC, - "<T> T", - "getContextValue", - "return " + FIELD_NAME_DELEGATE_CONTEXT + ".getContextValue(clazz, null);", - true, - newArgument("Class<T>", "clazz") - ); - - /** - * - */ - protected static final JavaMethod GET_CONTEXT_VALUE_NAMED_METHOD = newMethod( - PUBLIC, - "<T> T", - "getContextValue", - "return " + FIELD_NAME_DELEGATE_CONTEXT + ".getContextValue(clazz, name);", - true, - newArgument("Class<T>", "clazz"), newArgument(TYPE_STRING, "name") - ); - - /** - * - */ - protected static final JavaMethod SET_CONTEXT_VALUE_NAMED_METHOD = newMethod( - PUBLIC, - "<T> " + TYPE_VOID, - "setContextValue", - FIELD_NAME_DELEGATE_CONTEXT + ".setContextValue(o, name);", - true, - newArgument("T", "o"), newArgument(TYPE_STRING, "name")); - - /** - * - */ - protected static final JavaMethod SET_CONTEXT_VALUE_METHOD = newMethod( - PUBLIC, - "<T> " + TYPE_VOID, - "setContextValue", - FIELD_NAME_DELEGATE_CONTEXT + ".setContextValue(o, null);", - true, - newArgument("T", "o") - ); - - /** - * - */ - protected static final JavaMethod REMOVE_CONTEXT_VALUE_NAMED_METHOD = newMethod( - PUBLIC, - "<T> " + TYPE_VOID, - "removeContextValue", - FIELD_NAME_DELEGATE_CONTEXT + ".removeContextValue(clazz, name);", - true, - newArgument("Class<T>", "clazz"), - newArgument(TYPE_STRING, "name") - ); - - /** - * - */ - protected static final JavaMethod REMOVE_CONTEXT_VALUE_METHOD = newMethod( - PUBLIC, - "<T> " + TYPE_VOID, - "removeContextValue", - FIELD_NAME_DELEGATE_CONTEXT + ".removeContextValue(clazz, null);", - true, - newArgument("Class<T>", "clazz") - ); - - /** - * - */ - protected static final JavaMethod GET_PARENT_CONTAINER_MORE_METHOD = newMethod( - PUBLIC, - "<O extends Container> O", - "getParentContainer", - "return %s.getParentContainer(source, clazz);", - true, - newArgument(TYPE_OBJECT, "source"), - newArgument("Class<O>", "clazz") - ); - - /** - * - */ - protected static final JavaMethod GET_PARENT_CONTAINER_METHOD = newMethod( - PUBLIC, - "<O extends Container> O", - "getParentContainer", - "return %s.getParentContainer(this, clazz);", - true, - newArgument("Class<O>", "clazz") - ); - - /** - * - */ - protected static final JavaMethod GET_OBJECT_BY_ID_METHOD = newMethod( - PUBLIC, TYPE_OBJECT, "getObjectById", - "return " + FIELD_NAME_$OBJECT_MAP + ".get(id);", - true, - newArgument(TYPE_STRING, "id") - ); - - /** - * - */ - protected static final JavaMethod GET_JAXX_OBJECT_DESCRIPTOR_METHOD = newMethod( - PUBLIC | STATIC, - JAXXObjectDescriptor.class.getName(), - METHOD_NAME_$GET_JAXXOBJECT_DESCRIPTOR, - "return %s.decodeCompressedJAXXObjectDescriptor(" + - FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR + ");", - false - ); - - /** - * - */ - protected static final JavaMethod PROCESS_DATA_BINDING_METHOD = newMethod( - PUBLIC, - TYPE_VOID, - METHOD_NAME_PROCESS_DATA_BINDING, - METHOD_NAME_PROCESS_DATA_BINDING + "(" + PARAMETER_NAME_$BINDING + ", false);", - true, - newArgument(TYPE_STRING, PARAMETER_NAME_$BINDING) - ); - - /** - * - */ - protected static final JavaMethod REGISTER_DATA_BINDING_METHOD = newMethod( - PUBLIC, - TYPE_VOID, - METHOD_NAME_REGISTER_DATA_BINDING, - FIELD_NAME_$BINDINGS + ".put(binding.getId(), binding);", - true, - newArgument(JAXXBinding.class.getName(), "binding") - ); - - /** - * - */ - protected static final JavaMethod GET_DATA_BINDINGS_METHOD = newMethod( - PUBLIC, - JAXXBinding.class.getName() + "[]", - "getDataBindings", - "return " + FIELD_NAME_$BINDINGS + ".values().toArray(new %s[" + FIELD_NAME_$BINDINGS + ".size()]);", - true - ); - - /** - * - */ - protected static final JavaMethod GET_DATA_BINDING_METHOD = newMethod( - PUBLIC, - JAXXBinding.class.getName(), - "getDataBinding", - "return " + FIELD_NAME_$BINDINGS + ".get(bindingId);", - true, - newArgument(TYPE_STRING, "bindingId") - ); - - - /** - * - */ - protected static final JavaMethod FIRE_PROPERTY_CHANGE_METHOD = newMethod( - PUBLIC, - TYPE_VOID, - METHOD_NAME_FIRE_PROPERTY_CHANGE, - "super." + METHOD_NAME_FIRE_PROPERTY_CHANGE + "(propertyName, oldValue, newValue);", - true, - newArgument(TYPE_STRING, "propertyName"), - newArgument(TYPE_OBJECT, "oldValue"), - newArgument(TYPE_OBJECT, "newValue") - ); - - /** - * - */ - protected static final JavaMethod FIRE_PROPERTY_CHANGE_NAMED_METHOD = newMethod( - PUBLIC, - TYPE_VOID, - METHOD_NAME_FIRE_PROPERTY_CHANGE, - METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "()." + METHOD_NAME_FIRE_PROPERTY_CHANGE + "(propertyName, oldValue, newValue);", - true, - newArgument(TYPE_STRING, "propertyName"), - newArgument(TYPE_OBJECT, "oldValue"), - newArgument(TYPE_OBJECT, "newValue") - ); - - /** - * - */ - protected static final JavaMethod GET_PROPERTY_CHANGE_SUPPORT_METHOD = newMethod( - 0, - PropertyChangeSupport.class.getName(), - METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT, - "if (" + FIELD_NAME_$PROPERTY_CHANGE_SUPPORT + " == null)\n" + - " " + FIELD_NAME_$PROPERTY_CHANGE_SUPPORT + " = new PropertyChangeSupport(this);\n" + - "return " + FIELD_NAME_$PROPERTY_CHANGE_SUPPORT + ";", - false - ); - - /** - * - */ - protected static final JavaMethod ADD_PROPERTY_CHANGE_SUPPORT_METHOD = newMethod( - PUBLIC, - TYPE_VOID, - "addPropertyChangeListener", - METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "().addPropertyChangeListener(listener);", - true, - newArgument(PropertyChangeListener.class.getName(), "listener") - ); - - /** - * - */ - protected static final JavaMethod ADD_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD = newMethod( - PUBLIC, - TYPE_VOID, - "addPropertyChangeListener", - METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "().addPropertyChangeListener(property, listener);", - true, - newArgument(TYPE_STRING, "property"), - newArgument(PropertyChangeListener.class.getName(), "listener") - ); - - /** - * - */ - protected static final JavaMethod REMOVE_PROPERTY_CHANGE_SUPPORT_METHOD = newMethod( - PUBLIC, - TYPE_VOID, - "removePropertyChangeListener", - METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "().removePropertyChangeListener(listener);", - true, - newArgument(PropertyChangeListener.class.getName(), "listener") - ); - - /** - * - */ - protected static final JavaMethod REMOVE_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD = newMethod( - PUBLIC, - TYPE_VOID, - "removePropertyChangeListener", - METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "().removePropertyChangeListener(property, listener);", - true, - newArgument(TYPE_STRING, "property"), - newArgument(PropertyChangeListener.class.getName(), "listener") - ); - - public static final String METHOD_NAME$BEFORE_INIT = "beforeInit"; - - private static final String METHOD_NAME$AFTER_INIT = "afterInit"; - - @Override - public boolean accept(JAXXCompiler compiler) { - - // alwyas use the default finalizer - return true; - } - - @Override - public void finalizeCompiler(CompiledObject root, - JAXXCompiler compiler, - JavaFile javaFile, - String packageName, - String className) throws ClassNotFoundException { - - String fullClassName = packageName != null ? - packageName + "." + className : className; - if (root == null) { - throw new CompilerException("root tag can not be null"); - } - ClassDescriptor superclass = root.getObjectClass(); - boolean superclassIsJAXXObject = - compiler.isSuperClassAware(JAXXObject.class); - javaFile.setModifiers(PUBLIC); - javaFile.setName(fullClassName); - javaFile.setSimpleName(className); - - javaFile.setSuperClass(JAXXCompiler.getCanonicalName(superclass)); - javaFile.setSuperclassIsJAXXObject(superclassIsJAXXObject); - - javaFile.addInterface(compiler.getExtraInterfaces()); - javaFile.setAbstractClass(compiler.isAbstractClass()); - javaFile.setGenericType(compiler.getGenericType()); - javaFile.setSuperGenericType(compiler.getSuperGenericType()); - - if (!superclassIsJAXXObject) { - javaFile.addInterface(JAXXObject.class.getName()); - } - } - - @Override - public void prepareJavaFile(CompiledObject root, - JAXXCompiler compiler, - JavaFile javaFile, - String packageName, - String className) throws ClassNotFoundException { - - // add logger support if required - addLoggerSupport(compiler, javaFile, className); - - // add JAXXObject support if required - addJAXXObjectSupport(compiler, root, javaFile); - - addSimpleField(javaFile, SERIAL_VERSION_UID_FIELD); - - addJAXXObjectDescriptorField(compiler, javaFile); - addMethod(javaFile, GET_JAXX_OBJECT_DESCRIPTOR_METHOD, JAXXUtil.class.getName()); - - addPreviousValuesField(compiler, javaFile, root); - - DataBinding[] bindings = compiler.getBindingHelper().getDataBindings(); - - addInitializerMethod(compiler, javaFile); - addInitialize_01_createComponents(compiler, javaFile); - addInitialize_02_registerDataBindings(compiler, javaFile); - addInitialize_03_finalizeCreateComponents(compiler, javaFile); - addInitialize_04_applyDataBindings(compiler, javaFile); - addInitialize_05_setProperties(compiler, javaFile); - addInitialize_06_finalizeInitialize(compiler, javaFile); - - javaFile.addBodyCode(compiler.getBodyCode().toString()); - - addDataBindings(compiler, javaFile, bindings); - addEventHandlers(compiler, javaFile); - } - - protected void addDataBindings(JAXXCompiler compiler, - JavaFile javaFile, - DataBinding[] bindings) { - - if (bindings.length < 1) { - // no data bindings - return; - } - - // add import on each type of JAXXBinding used - for (JAXXBindingWriter<?> writer : bindingWriters) { - if (writer.isUsed()) { - javaFile.addImport(writer.getType()); - } - } - - // for each binding declare the constant Id - - for (DataBinding binding : bindings) { - - String constantId = binding.getConstantId(); - - // add the data binding constant Id - - compiler.addSimpleField(newField( - (constantId.startsWith("BINDING_$") ? PRIVATE : PUBLIC) | FINAL | STATIC, - TYPE_STRING, - constantId, - false, - TypeManager.getJavaCode(binding.getRealId())) - ); - } - } - - protected void addJAXXObjectSupport(JAXXCompiler compiler, - CompiledObject root, - JavaFile javaFile) { - - String jaxxContextImplementorClass = - compiler.getConfiguration().getJaxxContextClass().getName(); - - boolean superclassIsJAXXObject = javaFile.isSuperclassIsJAXXObject(); - - if (superclassIsJAXXObject) { - - //FIXME tchemit 2011-01-30 : We should not add it (if user want to use it in script it must add the correct import - // Will be removed in version 3.0 with strict imports features - javaFile.addImport(JAXXContext.class); - - } else { - - // add JAXXObject support - addField(javaFile, OBJECT_MAP_FIELD); - addSimpleField(javaFile, BINDING_SOURCES_FIELD); - addSimpleField(javaFile, ACTIVE_BINDINGS_FIELD); - addSimpleField(javaFile, BINDINGS_FIELD); - javaFile.addMethod(GET_OBJECT_BY_ID_METHOD); - addMethod(javaFile, REGISTER_DATA_BINDING_METHOD); - addMethod(javaFile, GET_DATA_BINDINGS_METHOD, JAXXBinding.class.getSimpleName()); - addMethod(javaFile, GET_DATA_BINDING_METHOD, JAXXBinding.class.getSimpleName()); - - javaFile.addMethod(createApplyDataBindingMethod()); - javaFile.addMethod(createProcessDataBindingMethod()); - javaFile.addMethod(createRemoveDataBindingMethod()); - - // JAXXContext - - String type = - javaFile.getImportedType(jaxxContextImplementorClass); - - javaFile.addField(newField( - PROTECTED | FINAL, - JAXXContext.class.getName(), - FIELD_NAME_DELEGATE_CONTEXT, - true, - "new " + type + "()") - ); - - javaFile.addImport(Container.class); - - javaFile.addMethod(SET_CONTEXT_VALUE_METHOD); - javaFile.addMethod(SET_CONTEXT_VALUE_NAMED_METHOD); - javaFile.addMethod(GET_CONTEXT_VALUE_METHOD); - javaFile.addMethod(GET_CONTEXT_VALUE_NAMED_METHOD); - javaFile.addMethod(REMOVE_CONTEXT_VALUE_METHOD); - javaFile.addMethod(REMOVE_CONTEXT_VALUE_NAMED_METHOD); - addMethod(javaFile, GET_PARENT_CONTAINER_METHOD, SwingUtil.class.getName()); - addMethod(javaFile, GET_PARENT_CONTAINER_MORE_METHOD, SwingUtil.class.getName()); - - // PropertyChangeSupport - addPropertyChangeSupport(root, javaFile); - - // DataBinding - javaFile.addMethod(PROCESS_DATA_BINDING_METHOD); - } - } - - protected void addLoggerSupport(JAXXCompiler compiler, JavaFile javaFile, String className) { - if (compiler.getConfiguration().isAddLogger()) { - - javaFile.addSimpleField(newField( - PRIVATE | STATIC | FINAL, - Log.class.getName(), - "log", - false, - "%s.getLog(" + className + ".class)", - LogFactory.class.getName() - ) - ); - } - } - - protected final JAXXBindingWriter<?>[] bindingWriters = new - JAXXBindingWriter[]{new SimpleJAXXObjectBindingWriter(), - new DefaultJAXXBindingWriter() - }; - - /*---------------------------------------------------------------------------------*/ - /*-- Create fields ----------------------------------------------------------------*/ - /*---------------------------------------------------------------------------------*/ - protected JavaField addJAXXObjectDescriptorField(JAXXCompiler compiler, - JavaFile javaFile) { - JavaField field; - try { - JAXXObjectDescriptor descriptor = compiler.getJAXXObjectDescriptor(); - String data = Base64Coder.serialize(descriptor, true); - /*ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - ObjectOutputStream out = new ObjectOutputStream(new GZIPOutputStream(buffer)); - out.writeObject(descriptor); - out.close(); - // the use of the weird deprecated constructor is deliberate -- we need to store the data as a String - // in the compiled class file, since byte array initialization is horribly inefficient compared to - // String initialization. So we store the bytes in the String, and we quite explicitly want a 1:1 - // mapping between bytes and chars, with the high byte of the char set to zero. We can then safely - // reconstitute the original byte[] at a later date. This is unquestionably an abuse of the String - // type, but if we could efficiently store a byte[] we wouldn't have to do this. - String data = new String(buffer.toByteArray(), 0);*/ - - int sizeLimit = 65000; // constant strings are limited to 64K, and I'm not brave enough to push right up to the limit - if (data.length() < sizeLimit) { - field = newField(PRIVATE | STATIC | FINAL, - TYPE_STRING, - FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR, - false, - TypeManager.getJavaCode(data) - ); - - } else { - StringBuilder initializer = new StringBuilder(); - for (int i = 0; i < data.length(); i += sizeLimit) { - String name = FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR + i; - javaFile.addField(newField( - PRIVATE | STATIC, - TYPE_STRING, - name, - false, - TypeManager.getJavaCode(data.substring(i, Math.min(i + sizeLimit, data.length())))) - ); - if (initializer.length() > 0) { - initializer.append(" + "); - } - initializer.append(TYPE_STRING + ".valueOf("); - initializer.append(name); - initializer.append(")"); - } - field = newField(PRIVATE | STATIC | FINAL, - TYPE_STRING, - FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR, - false, - initializer.toString() - ); - } - } catch (IOException e) { - throw new RuntimeException("Internal error: can't-happen error", e); - } - javaFile.addSimpleField(field); - return field; - } - - protected void addPreviousValuesField(JAXXCompiler compiler, - JavaFile javaFile, CompiledObject root) { - - boolean superclassIsJAXXObject = javaFile.isSuperclassIsJAXXObject(); - - if (compiler.getStylesheet() != null) { - boolean needField = true; - if (superclassIsJAXXObject) { - // check alreay exists on parent - ClassDescriptor superclass = root.getObjectClass(); - if (log.isDebugEnabled()) { - log.debug("superclass : " + superclass); - } - JAXXCompiler parentCompiler = - compiler.getEngine().getJAXXCompiler( - superclass.getName() - ); - - if (parentCompiler != null) { - needField = parentCompiler.getStylesheet() == null; - } else { - try { - superclass.getDeclaredFieldDescriptor( - PREVIOUS_VALUES_FIELD.getName()); - needField = false; - } catch (NoSuchFieldException ex) { - // field not found - } - } - if (needField && log.isDebugEnabled()) { - log.debug("no " + PREVIOUS_VALUES_FIELD.getName() + - " field in super class"); - } - } - if (needField) { - addSimpleField(javaFile, PREVIOUS_VALUES_FIELD); - } - } - } - - /*---------------------------------------------------------------------------------*/ - /*-- Create methods ---------------------------------------------------------------*/ - /*---------------------------------------------------------------------------------*/ - protected void addPropertyChangeSupport(CompiledObject root, - JavaFile javaFile) { - ClassDescriptor currentClass = root.getObjectClass(); - MethodDescriptor firePropertyChange = null; - while (firePropertyChange == null && currentClass != null) { - try { - firePropertyChange = currentClass.getDeclaredMethodDescriptor( - METHOD_NAME_FIRE_PROPERTY_CHANGE, - ClassDescriptorHelper.getClassDescriptor(String.class), - ClassDescriptorHelper.getClassDescriptor(Object.class), - ClassDescriptorHelper.getClassDescriptor(Object.class) - ); - - } catch (NoSuchMethodException e) { - currentClass = currentClass.getSuperclass(); - } - } - - int modifiers = firePropertyChange != null ? - firePropertyChange.getModifiers() : 0; - if (isPublic(modifiers)) { - // we have all the support we need - return; - } - if (isProtected(modifiers)) { - - // there is property change support but the firePropertyChange method is protected - javaFile.addMethod(FIRE_PROPERTY_CHANGE_METHOD); - } else { - - addField(javaFile, PROPERTY_CHANGE_SUPPORT_FIELD); - addMethod(javaFile, GET_PROPERTY_CHANGE_SUPPORT_METHOD, - PropertyChangeSupport.class.getName()); - addMethod(javaFile, ADD_PROPERTY_CHANGE_SUPPORT_METHOD); - addMethod(javaFile, ADD_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD); - addMethod(javaFile, REMOVE_PROPERTY_CHANGE_SUPPORT_METHOD); - addMethod(javaFile, REMOVE_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD); - addMethod(javaFile, FIRE_PROPERTY_CHANGE_NAMED_METHOD); - } - } - - protected void addInitialize_01_createComponents(JAXXCompiler compiler, JavaFile javaFile) { - StringBuilder body = new StringBuilder(); - body.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); - String eol = JAXXCompiler.getLineSeparator(); - if (javaFile.isSuperclassIsJAXXObject()) { - body.append(String.format("super.%s();", METHOD_NAME_$INITIALIZE_01_CREATE_COMPONENTS)).append(eol); - } - - CompiledObject root = compiler.getRootObject(); - - String rootId = root.getId(); - body.append(FIELD_NAME_$OBJECT_MAP + ".put(").append(TypeManager.getJavaCode(rootId)).append(", ").append(rootId).append(");").append(eol); - - Iterator<CompiledObject> i = compiler.getObjectCreationOrder(); - boolean lastWasMethodCall = false; - //TODO-TC20091025 should do init of root first ? -// root.getDecorator().createInitializer(compiler, root, root, code, lastWasMethodCall); - while (i.hasNext()) { - CompiledObject object = i.next(); - if (object == root) { - continue; - } - CompiledObjectDecorator decorator = object.getDecorator(); - lastWasMethodCall = decorator.createInitializer(compiler, - root, - object, - body, - lastWasMethodCall - ); - } - root.getDecorator().createInitializer(compiler, - root, - root, - body, - lastWasMethodCall - ); - if (compiler.getInitializer().length() > 0) { - body.append(compiler.getInitializer()); - } - JavaMethod method = newMethod(PROTECTED, - TYPE_VOID, - METHOD_NAME_$INITIALIZE_01_CREATE_COMPONENTS, - body.toString(), - javaFile.isSuperclassIsJAXXObject() - ); - javaFile.addMethod(method); - } - - protected void addInitialize_02_registerDataBindings(JAXXCompiler compiler, JavaFile javaFile) { - StringBuilder body = new StringBuilder(); - body.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); - String eol = JAXXCompiler.getLineSeparator(); - if (javaFile.isSuperclassIsJAXXObject()) { - body.append(String.format("super.%s();", METHOD_NAME_$INITIALIZE_02_REGISTER_DATA_BINDINGS)).append(eol); - } - JavaFileGenerator generator = new JavaFileGenerator(eol, true); - //TODO use optimized writer for simple cases - - for (JAXXBindingWriter<?> writer : bindingWriters) { - writer.reset(); - } - - // add import on each type of JAXXBinding used - - for (JAXXBindingWriter<?> writer : bindingWriters) { - if (writer.isUsed()) { - compiler.getJavaFile().addImport(writer.getType()); - } - } - - DataBinding[] bindings = compiler.getBindingHelper().getDataBindings(); - body.append("// register "); - body.append(bindings.length); - body.append(" data bindings"); - body.append(eol); - - for (DataBinding binding : bindings) { - - for (JAXXBindingWriter<?> writer : bindingWriters) { - if (writer.accept(binding)) { - writer.write(binding, generator, body); - break; - } - } - } - JavaMethod method = newMethod(PROTECTED, - TYPE_VOID, - METHOD_NAME_$INITIALIZE_02_REGISTER_DATA_BINDINGS, - body.toString(), - javaFile.isSuperclassIsJAXXObject() - ); - javaFile.addMethod(method); - } - - protected void addInitialize_03_finalizeCreateComponents(JAXXCompiler compiler, JavaFile javaFile) { - - StringBuilder body = new StringBuilder(); - body.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); - String eol = JAXXCompiler.getLineSeparator(); - if (javaFile.isSuperclassIsJAXXObject()) { - body.append(String.format("super.%s();", METHOD_NAME_$INITIALIZE_03_FINALIZE_CREATE_COMPONENTS)).append(eol); - } - for (CompiledObject object : compiler.getObjects().values()) { - CompiledObjectDecorator decorator = object.getDecorator(); - body.append(decorator.createCompleteSetupMethod(compiler, - object, - javaFile) - ); - } - JavaMethod method = newMethod(PROTECTED, - TYPE_VOID, - METHOD_NAME_$INITIALIZE_03_FINALIZE_CREATE_COMPONENTS, - body.toString(), - javaFile.isSuperclassIsJAXXObject() - ); - javaFile.addMethod(method); - } - - protected void addInitialize_04_applyDataBindings(JAXXCompiler compiler, JavaFile javaFile) { - StringBuilder body = new StringBuilder(); - String eol = JAXXCompiler.getLineSeparator(); - body.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); - if (javaFile.isSuperclassIsJAXXObject()) { - body.append(String.format("super.%s();", METHOD_NAME_$INITIALIZE_04_APPLY_DATA_BINDINGS)).append(eol); - } - DataBinding[] bindings = compiler.getBindingHelper().getDataBindings(); - if (bindings.length > 0) { - - body.append(eol); - body.append("// apply "); - body.append(bindings.length); - body.append(" data bindings"); - body.append(eol); - body.append(JAXXUtil.class.getSimpleName()); - body.append("." + METHOD_NAME_APPLY_DATA_BINDING + "(this, " + FIELD_NAME_$BINDINGS + ".keySet());"); - body.append(eol); - - } - JavaMethod method = newMethod(PROTECTED, - TYPE_VOID, - METHOD_NAME_$INITIALIZE_04_APPLY_DATA_BINDINGS, - body.toString(), - javaFile.isSuperclassIsJAXXObject() - ); - javaFile.addMethod(method); - } - - protected void addInitialize_05_setProperties(JAXXCompiler compiler, JavaFile javaFile) { - StringBuilder body = new StringBuilder(); - String eol = JAXXCompiler.getLineSeparator(); - body.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); - if (javaFile.isSuperclassIsJAXXObject()) { - body.append(String.format("super.%s();", METHOD_NAME_$INITIALIZE_05_SET_PROPERTIES)).append(eol); - } - DataBinding[] bindings = compiler.getBindingHelper().getSimpleBindings(); - if (bindings.length > 0) { - - StringBuilder initCode = new StringBuilder(); - - for (DataBinding binding : bindings) { - - String binding1 = binding.getInitDataBinding(); - if (binding1 != null && !binding1.trim().isEmpty()) { - initCode.append(binding1); - } - } - - if (initCode.length() > 0) { - - body.append(eol); - body.append("// apply "); - body.append(bindings.length); - body.append(" property setters"); - body.append(eol); - body.append(initCode.toString().trim()); - - } - } - - if (compiler.getLateInitializer().length() > 0) { - body.append("// late initializer").append(eol); - body.append(compiler.getLateInitializer()).append(eol); - } - JavaMethod method = newMethod(PROTECTED, - TYPE_VOID, - METHOD_NAME_$INITIALIZE_05_SET_PROPERTIES, - body.toString(), - javaFile.isSuperclassIsJAXXObject() - ); - javaFile.addMethod(method); - } - - protected void addInitialize_06_finalizeInitialize(JAXXCompiler compiler, JavaFile javaFile) { - StringBuilder body = new StringBuilder(); - body.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); - String eol = JAXXCompiler.getLineSeparator(); - if (javaFile.isSuperclassIsJAXXObject()) { - body.append(String.format("super.%s();", METHOD_NAME_$INITIALIZE_06_FINALIZE_INITIALIZE)).append(eol); - } - JavaMethod method = newMethod(PROTECTED, - TYPE_VOID, - METHOD_NAME_$INITIALIZE_06_FINALIZE_INITIALIZE, - body.toString(), - javaFile.isSuperclassIsJAXXObject() - ); - javaFile.addMethod(method); - } - - protected void addEventHandlers(JAXXCompiler compiler, - JavaFile javaFile) { - - for (Map.Entry<String, Map<ClassDescriptor, List<EventHandler>>> e1 : compiler.getEventHandlers().entrySet()) { - - // outer loop is iterating over different objects (well, technically, different Java expressions) - for (Map.Entry<ClassDescriptor, List<EventHandler>> e2 : e1.getValue().entrySet()) { - - // iterate over different types of listeners for this particular object (MouseListener, ComponentListener, etc.) - for (EventHandler handler : e2.getValue()) { - - // iterate over individual event handlers of a single type - String methodName = compiler.getEventHandlerMethodName(handler); - MethodDescriptor listenerMethod = handler.getListenerMethod(); - if (listenerMethod.getParameterTypes().length != 1) { - throw new CompilerException( - "Expected event handler " + - listenerMethod.getName() + " of class " + - handler.getListenerClass() + - " to have exactly one argument" - ); - } - - ClassDescriptor eventType = - listenerMethod.getParameterTypes()[0]; - - JavaArgument argument = - JavaElementFactory.newArgument( - JAXXCompiler.getCanonicalName(eventType), - "event" - ); - - String body = JavaFileGenerator.addDebugLoggerInvocation(compiler, "event"); - body += handler.getJavaCode(); - javaFile.addMethod(JavaElementFactory.newMethod( - PUBLIC, - TYPE_VOID, - methodName, - body, - false, - argument) - ); - } - } - } - } - - public JavaMethod addInitializerMethod(JAXXCompiler compiler, JavaFile javaFile) { - - String eol = JAXXCompiler.getLineSeparator(); - StringBuilder code = new StringBuilder(); - code.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); - code.append(compiler.getRootObject().getId()).append(" = this;").append(eol); - - boolean useHandler = compiler.isUseHandler(); - - if (useHandler) { - String handler = compiler.getUiHandler(); - String handlerType = compiler.getImportedType(handler); - code.append("handler = new ").append(handlerType).append("();").append(eol); - code.append("handler." + METHOD_NAME$BEFORE_INIT + "(this);").append(eol); - } - - if (javaFile.isSuperclassIsJAXXObject()) { - code.append("super." + METHOD_NAME_$INITIALIZE + "();").append(eol); - } else { - code.append(METHOD_NAME_$INITIALIZE_01_CREATE_COMPONENTS + "();"); - code.append(eol); - - code.append(METHOD_NAME_$INITIALIZE_02_REGISTER_DATA_BINDINGS + "();"); - code.append(eol); - - code.append(METHOD_NAME_$INITIALIZE_03_FINALIZE_CREATE_COMPONENTS + "();"); - code.append(eol); - - code.append(METHOD_NAME_$INITIALIZE_04_APPLY_DATA_BINDINGS + "();"); - code.append(eol); - code.append(METHOD_NAME_$INITIALIZE_05_SET_PROPERTIES + "();"); - code.append(eol); - code.append(METHOD_NAME_$INITIALIZE_06_FINALIZE_INITIALIZE + "();"); - code.append(eol); - } - - if (useHandler) { - code.append("handler." + METHOD_NAME$AFTER_INIT + "(this);").append(eol); - } - JavaMethod method = JavaElementFactory.newMethod(PROTECTED, - TYPE_VOID, - METHOD_NAME_$INITIALIZE, - code.toString(), - javaFile.isSuperclassIsJAXXObject() - ); - javaFile.addMethod(method); - return method; - } - - protected JavaMethod createApplyDataBindingMethod() { - StringBuilder buffer = new StringBuilder(); - String eol = JAXXCompiler.getLineSeparator(); - - buffer.append("if (" + FIELD_NAME_$BINDINGS + ".containsKey(" + PARAMETER_NAME_$BINDING + ")) {"); - buffer.append(eol); - buffer.append(" getDataBinding(" + PARAMETER_NAME_$BINDING + ")." + METHOD_NAME_APPLY_DATA_BINDING + "();"); - buffer.append(eol); - buffer.append("}"); - buffer.append(eol); - buffer.append(METHOD_NAME_PROCESS_DATA_BINDING + "(" + PARAMETER_NAME_$BINDING + ");"); - return JavaElementFactory.newMethod( - PUBLIC, - TYPE_VOID, - METHOD_NAME_APPLY_DATA_BINDING, - buffer.toString(), - true, - JavaElementFactory.newArgument(TYPE_STRING, PARAMETER_NAME_$BINDING) - ); - } - - protected JavaMethod createRemoveDataBindingMethod() { - StringBuilder buffer = new StringBuilder(); - String eol = JAXXCompiler.getLineSeparator(); - - buffer.append("if (" + FIELD_NAME_$BINDINGS + ".containsKey(" + PARAMETER_NAME_$BINDING + ")) {"); - buffer.append(eol); - buffer.append(" getDataBinding(" + PARAMETER_NAME_$BINDING + ")." + METHOD_NAME_REMOVE_DATA_BINDING + "();"); - buffer.append(eol); - buffer.append("}"); - return JavaElementFactory.newMethod( - PUBLIC, - TYPE_VOID, - METHOD_NAME_REMOVE_DATA_BINDING, - buffer.toString(), - true, - JavaElementFactory.newArgument(TYPE_STRING, PARAMETER_NAME_$BINDING) - ); - } - - protected JavaMethod createProcessDataBindingMethod() { - StringBuilder code = new StringBuilder(); - String eol = JAXXCompiler.getLineSeparator(); - - // the force parameter forces the update to happen even if it is already in activeBindings. This - // is used on superclass invocations b/c by the time the call gets to the superclass, it is already - // marked active and would otherwise be skipped - - code.append(" if (!$force && " + FIELD_NAME_$ACTIVE_BINDINGS + ".contains(" + PARAMETER_NAME_$BINDING + ")) { "); - code.append(eol); - code.append(" return;"); - code.append(eol); - code.append("}").append(eol); - code.append(FIELD_NAME_$ACTIVE_BINDINGS + ".add(" + PARAMETER_NAME_$BINDING + ");"); - code.append(eol); - code.append("try {").append(eol); - code.append(" if (" + FIELD_NAME_$BINDINGS + ".containsKey(" + PARAMETER_NAME_$BINDING + ")) {"); - code.append(eol); - code.append(" getDataBinding(" + PARAMETER_NAME_$BINDING + ")." + METHOD_NAME_PROCESS_DATA_BINDING + "();"); - code.append(eol); - code.append(" }").append(eol); - code.append("} finally {").append(eol); - code.append(" " + FIELD_NAME_$ACTIVE_BINDINGS + ".remove(" + PARAMETER_NAME_$BINDING + ");"); - code.append(eol); - code.append("}").append(eol); - return JavaElementFactory.newMethod( - PUBLIC, - TYPE_VOID, - METHOD_NAME_PROCESS_DATA_BINDING, - code.toString(), - true, - newArgument(TYPE_STRING, PARAMETER_NAME_$BINDING), - newArgument(TYPE_BOOLEAN, "$force") - ); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/JAXXCompilerFinalizer.java b/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/JAXXCompilerFinalizer.java deleted file mode 100644 index 40c2b31..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/JAXXCompilerFinalizer.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.finalizers; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.java.JavaFile; - -/** - * Contract of any object to interact with a {@link JAXXCompiler} before the - * generation pass. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.0 - */ -public interface JAXXCompilerFinalizer { - - String TYPE_STRING = "String"; - - String TYPE_VOID = "void"; - - String TYPE_BOOLEAN = "boolean"; - - String TYPE_OBJECT = "Object"; - - /** - * Test if the finalizer must be apply on the given {@code compiler}. - * - * @param compiler the compiler - * @return {@code true} if the finalizer must be apply of compiler - */ - boolean accept(JAXXCompiler compiler); - - /** - * Finalize compiler for a given compiler on the finalizer pass before any - * generation. - * - * @param root the root object - * @param compiler the current compiler - * @param javaFile the java file to generate - * @param packageName the package name of the file to generate - * @param className the class name of the file to generate - * @throws Exception if any pb - */ - void finalizeCompiler(CompiledObject root, - JAXXCompiler compiler, - JavaFile javaFile, - String packageName, - String className) throws Exception; - - /** - * Prepare java file after any compiler finalizer pass, says the last - * action before generation. - * - * @param root the root object - * @param compiler the current compiler - * @param javaFile the java file to generate - * @param packageName the package name of the file to generate - * @param className the class name of the file to generate - * @throws Exception if any pb - */ - void prepareJavaFile(CompiledObject root, - JAXXCompiler compiler, - JavaFile javaFile, - String packageName, - String className) throws Exception; -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/SwingFinalizer.java b/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/SwingFinalizer.java deleted file mode 100644 index bf58823..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/SwingFinalizer.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.finalizers; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.java.JavaElementFactory; -import jaxx.compiler.java.JavaFile; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.runtime.swing.Application; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.SwingUtilities; -import java.lang.reflect.Modifier; - -/** - * @author Tony Chemit - chemit@codelutin.com - * @plexus.component role-hint="swing" role="jaxx.compiler.finalizers.JAXXCompilerFinalizer" - */ -public class SwingFinalizer extends AbstractFinalizer { - - /** Logger. */ - protected static final Log log = LogFactory.getLog(DefaultFinalizer.class); - - @Override - public boolean accept(JAXXCompiler compiler) { - - ClassDescriptor descriptor = - ClassDescriptorHelper.getClassDescriptor(Application.class); - CompiledObject root = compiler.getRootObject(); - return descriptor.isAssignableFrom(root.getObjectClass()); - } - - @Override - public void finalizeCompiler(CompiledObject root, - JAXXCompiler compiler, - JavaFile javaFile, - String packageName, - String className) { - } - - @Override - public void prepareJavaFile(CompiledObject root, - JAXXCompiler compiler, - JavaFile javaFile, - String packageName, - String className) throws ClassNotFoundException { - - if (compiler.isMainDeclared()) { - - // main method was already defined, can not generate this method. - return; - } - - javaFile.addImport(SwingUtilities.class); - String code = "SwingUtilities.invokeLater(new Runnable() { " + - "public void run() { new " + className + - "().setVisible(true); } });"; - javaFile.addMethod(JavaElementFactory.newMethod( - Modifier.PUBLIC | Modifier.STATIC, - TYPE_VOID, - "main", - code, - false, - JavaElementFactory.newArgument("String[]", "arg"))); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/ValidatorFinalizer.java b/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/ValidatorFinalizer.java deleted file mode 100644 index 3452736..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/ValidatorFinalizer.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.finalizers; - -import com.google.common.base.Joiner; -import com.google.common.collect.Lists; -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompiledObject.ChildRef; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.java.JavaElement; -import jaxx.compiler.java.JavaElementFactory; -import jaxx.compiler.java.JavaField; -import jaxx.compiler.java.JavaFile; -import jaxx.compiler.tags.validator.BeanValidatorHandler; -import jaxx.compiler.tags.validator.BeanValidatorHandler.CompiledBeanValidator; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.JAXXValidator; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.validator.swing.SwingValidator; -import jaxx.runtime.validator.swing.SwingValidatorUtil; -import jaxx.runtime.validator.swing.meta.Validator; -import jaxx.runtime.validator.swing.meta.ValidatorField; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * To finalize validators fields. - * - * @author Tony Chemit - chemit@codelutin.com - * @plexus.component role-hint="validators" role="jaxx.compiler.finalizers.JAXXCompilerFinalizer" - */ -public class ValidatorFinalizer extends AbstractFinalizer { - - /** Logger. */ - static Log log = LogFactory.getLog(ValidatorFinalizer.class); - - protected static final JavaField VALIDATOR_IDS_FIELD = - JavaElementFactory.newField( - Modifier.PROTECTED, - List.class.getName() + "<String>", - "validatorIds", - true, - "new %s<String>()", - ArrayList.class.getName() - ); - - @Override - public boolean accept(JAXXCompiler compiler) { - - //use this finalizer if compiler is validation aware - return BeanValidatorHandler.hasValidator(compiler); - } - - @Override - public void finalizeCompiler(CompiledObject root, - JAXXCompiler compiler, - JavaFile javaFile, - String packageName, - String className) { - - for (CompiledObject object : compiler.getObjects().values()) { - List<ChildRef> childs = object.getChilds(); - if (childs == null || childs.isEmpty()) { - continue; - } - for (ChildRef child : childs) { - String javaCode = child.getChildJavaCode(); - - // some validators are defined on this object - boolean found = - BeanValidatorHandler.isComponentUsedByValidator( - compiler, - child.getChild().getId() - ); - - if (found) { -// compiler.setNeedSwingUtil(true); - String type = - compiler.getImportedType(SwingUtil.class); - // box the child component in a JxLayer - child.setChildJavaCode( - type + - ".boxComponentWithJxLayer(" + javaCode + ")"); - } - } - } - String eol = JAXXCompiler.getLineSeparator(); - StringBuilder builder = new StringBuilder(); - // register validators - List<CompiledBeanValidator> validators = - BeanValidatorHandler.getValidators(compiler); -// javaFile.addImport(Validator.class); -// javaFile.addImport(ValidatorField.class); -// javaFile.addImport(SwingValidatorUtil.class); - String validatorUtilPrefix = - compiler.getImportedType(SwingValidatorUtil.class) + - "."; - - compiler.getJavaFile().addMethod(JavaElementFactory.newMethod( - Modifier.PUBLIC, - TYPE_VOID, - "registerValidatorFields", - validatorUtilPrefix + "detectValidatorFields(this);", - true) - ); - builder.append("// register "); - builder.append(validators.size()); - builder.append(" validator(s)"); - builder.append(eol); - - builder.append("validatorIds = "); - builder.append(validatorUtilPrefix).append("detectValidators(this);"); - builder.append(eol); - - builder.append(validatorUtilPrefix).append("installUI(this);"); - builder.append(eol); - compiler.appendLateInitializer(builder.toString()); - - for (CompiledBeanValidator validator : validators) { - - registerValidator(validator, compiler, javaFile); - } - } - - @Override - public void prepareJavaFile(CompiledObject root, - JAXXCompiler compiler, - JavaFile javaFile, - String packageName, - String className) throws ClassNotFoundException { - Class<?> validatorClass = SwingValidator.class; - - Class<?> validatorInterface = JAXXValidator.class; - - boolean parentIsValidator = - compiler.isSuperClassAware(validatorInterface); - - if (parentIsValidator) { - - // nothing to generate (use the parent directly) - return; - } - - // add JAXXValidator interface - javaFile.addInterface(JAXXCompiler.getCanonicalName(validatorInterface)); - - // implements JAXXValidator - addField(javaFile, VALIDATOR_IDS_FIELD); - - String type = compiler.getImportedType(validatorClass); - - String initializer = "return (" + type + - "<?>) (validatorIds.contains(validatorId) ? " + - "getObjectById(validatorId) : null);"; - - - javaFile.addMethod(JavaElementFactory.newMethod( - Modifier.PUBLIC, - type + "<?>", - "getValidator", - initializer, - true, - JavaElementFactory.newArgument(TYPE_STRING, "validatorId")) - ); - } - - public void registerValidator(CompiledBeanValidator validator, - JAXXCompiler compiler, - JavaFile javaFile) { - - JavaField validatorField = javaFile.getField(validator.getId()); - - String validatorId = TypeManager.getJavaCode(validator.getId()); - - String type = compiler.getImportedType(Validator.class); - String fieldType = compiler.getImportedType(ValidatorField.class); - - String validatorAnnotation = type + - "( validatorId = " + validatorId + ")"; - validatorField.addAnnotation(validatorAnnotation); -// Map<String, String> fields = validator.getFields(); - - for (String component : validator.getFieldEditors()) { - - Collection<String> propertyNames = validator.getFieldPropertyNames(component); - List<String> keyCodes = - Lists.newArrayListWithCapacity(propertyNames.size()); - for (String propertyName : propertyNames) { - if (!validator.checkBeanProperty(compiler, propertyName)) { - // property not find on bean - continue; - } - String keyCode = TypeManager.getJavaCode(propertyName); - keyCodes.add(keyCode); - } - - if (keyCodes.isEmpty()) { - // no property - continue; - } - String keyCode = Joiner.on(", ").join(keyCodes); - if (keyCodes.size() > 1) { - keyCode = "{ " + keyCode + " }"; - } - -// String keyCode = TypeManager.getJavaCode(propertyName); - String editorCode = TypeManager.getJavaCode(component); - JavaElement editor = javaFile.getField(component); - if (editor == null) { - if (log.isDebugEnabled()) { - String message = "Could not find editor [" + component + - "] for property(ies) [" + propertyNames + - "] for file " + javaFile.getName(); - log.debug(message); - } - - // find in the compiler the object - CompiledObject compiledObject = - compiler.getCompiledObject(component); - - if (compiledObject == null) { - - // this is an error, editor is unknown (this case should - // never happen) - - String errorMessage = - "Could not find editor [" + component + - "] for property(ies) [" + propertyNames + - "] for file " + javaFile.getName(); - - throw new CompilerException(errorMessage); - } - - // now must add a getter in the javaFile - String fqn = JAXXCompiler.getCanonicalName(compiledObject); - - editor = javaFile.addGetterMethod(component, - Modifier.PUBLIC, - fqn, - true, - true - ); - } - - String annotation = fieldType + - "( validatorId = " + validatorId + "," + - " propertyName = " + keyCode + "," + - " editorName = " + editorCode + "" + ")"; - editor.addAnnotation(annotation); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaArgument.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaArgument.java deleted file mode 100644 index bede7b5..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaArgument.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.java; - -/** - * Represents an argument to a <code>JavaMethod</code>. - * - * @see JavaMethod - */ -public class JavaArgument extends JavaElement { - - private String type; - - private boolean isFinal; - - /** - * Creates a new <code>JavaArgument</code> with the specified name and type. For example, the method <code>main()</code> - * might have a <code>JavaArgument</code> with a name of <code>"arg"</code> and a type of <code>"java.lang.String[]"</code>. - * - * @param type the argument's type, as it would appear in Java source code - * @param name the argument's name - */ - JavaArgument(String type, String name) { - this(type, name, false); - } - - /** - * Creates a new <code>JavaArgument</code> with the specified name, type, and finality. For example, the method <code>main()</code> - * might have a <code>JavaArgument</code> with a name of <code>"arg"</code> and a type of <code>"java.lang.String[]"</code>. The - * <code>isFinal</code> parameter allows the presence of the <code>final</code> keyword on the argument to be controlled. - * - * @param type the argument's type, as it would appear in Java source code - * @param name the argument's name - * @param isFinal <code>true</code> if the argument should be marked final - */ - JavaArgument(String type, String name, boolean isFinal) { - super(0, name); - this.type = type; - this.isFinal = isFinal; - } - - /** - * Returns the argument's type as it would be represented in Java source code. - * - * @return the argument's type - */ - public String getType() { - return type; - } - - /** - * Returns <code>true</code> if the <code>final</code> keyword should appear before the argument. - * - * @return <code>true</code> if the argument is final - */ - public boolean isFinal() { - return isFinal; - } - - public void setType(String type) { - this.type = type; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaConstructor.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaConstructor.java deleted file mode 100644 index 8bc718f..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaConstructor.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.java; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Modifier; - -/** - * To mirror a {@link Constructor}. - * - * In a constructor we need to keep all parameters types as fqn since when - * a jaxx object inheritates from anohter one, it is painfull (even impossible?) - * to find out from a simple name his fqn. - * - * So when using constructor, always keep fqn types. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.4 - */ -public class JavaConstructor extends JavaElement { - - /** arguments of the method (can be empty) */ - private JavaArgument[] arguments; - - /** exceptions thrown by the method (can be empty) */ - private String[] exceptions; - - /** body of the method (can be empty) */ - private String body; - - /** - * Constructs a new <code>JavaMethod</code> containing the specified body code. The <code>modifiers</code> parameter - * is a bit mask of the constants from {@link Modifier}, and the <code>returnType</code> and - * <code>exceptions</code> of the method should be represented as they would appear in Java source code (<code>null</code> - * for a constructor). The method body is initially empty. - * - * @param modifiers the modifier keywords that should appear as part of the method's declaration - * @param name the method's name - * @param arguments the method's arguments - * @param exceptions a list of exceptions the methods can throw, as they would be represented in Java source code - * @param bodyCode Java source code which should appear in the method body - */ - JavaConstructor(int modifiers, - String name, - JavaArgument[] arguments, - String[] exceptions, - String bodyCode) { - super(modifiers, name); - this.arguments = arguments; - this.exceptions = exceptions; - body = bodyCode == null ? "" : bodyCode; - } - - /** - * Returns a list of the method's arguments. - * - * @return the method's arguments - */ - public JavaArgument[] getArguments() { - return arguments; - } - - /** - * Returns a list of exceptions the method can throw. - * - * @return the method's exceptions - */ - public String[] getExceptions() { - return exceptions; - } - - public String getBody() { - return body; - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaElement.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaElement.java deleted file mode 100644 index c4a2e9a..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaElement.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.java; - -import org.apache.commons.collections4.CollectionUtils; - -import java.lang.reflect.Modifier; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Set; -import java.util.regex.Pattern; - -/** - * Base Java element - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.0 - */ -public abstract class JavaElement { - - // private String lineSeparator; - private String name; - - private int modifiers; - - /** - * List of annoations. - * - * @since 2.3 - */ - private Set<String> annotations; - - public JavaElement(int modifiers, String name) { - this.modifiers = modifiers; - this.name = name; - } - - public final int getModifiers() { - return modifiers; - } - - public final void setModifiers(int modifiers) { - this.modifiers = modifiers; - } - - public final String getName() { - return name; - } - - public final void setName(String name) { - this.name = name; - } - - public final String getModifiersText() { - if (modifiers == 0) { - return ""; - } else { - return Modifier.toString(modifiers) + ' '; - } - } - - public Set<String> getAnnotations() { - if (annotations == null) { - annotations = new HashSet<>(); - } - return annotations; - } - - public boolean hasAnnotations() { - return CollectionUtils.isNotEmpty(annotations); - } - - public void addAnnotation(String annotation) { - getAnnotations().add(annotation); - } - - public static final Comparator<JavaElement> JavaElementComparator = new Comparator<JavaElement>() { - - final Pattern NAME_PATTERN = Pattern.compile("(.+)([0-9]+)"); - - @Override - public int compare(JavaElement o1, JavaElement o2) { - - String n1 = o1.getName(); - String n2 = o2.getName(); - - //FIXME-tchemit-2012-07-02 (see https://forge.nuiton.org/issues/2154) -// Matcher matcher1 = NAME_PATTERN.matcher(n1); -// Matcher matcher2 = NAME_PATTERN.matcher(n2); -// if (matcher1.matches() && matcher2.matches()) { -// // les deux noms finissent par un nombre -// String p1 = matcher1.group(1); -// String p2 = matcher1.group(2); -// int i = p1.compareTo(p2); -// if (i != 0) { -// // on est sur des noms de prefix différents, donc pas de tri sur les suffixes -// return i; -// } -// // les deux noms doivent être triés sur les suffixes entiers -// int i1 = Integer.valueOf(matcher1.group(2)); -// int i2 = Integer.valueOf(matcher2.group(2)); -// return i1 - i2; -// } - - // les deux noms sont simplement comparé en alpha - return n1.compareTo(n2); - } - }; -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaElementFactory.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaElementFactory.java deleted file mode 100644 index 59ffb08..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaElementFactory.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.java; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.util.StringUtil; - -/** - * Factory of any element in a {@link JavaFile}. - * - * Always pass by this factory to have common behaviour (imports,...) - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.4 - */ -public class JavaElementFactory { - - /** Logger. */ - static private final Log log = LogFactory.getLog(JavaElementFactory.class); - - public static JavaFile newFile(int modifiers, String className) { - return new JavaFile(modifiers, className); - } - - public static JavaArgument newArgument(String type, - String name) { - return newArgument(type, name, false); - } - - public static JavaArgument newArgument(String type, - String name, - boolean isFinal) { - return new JavaArgument(type, name, isFinal); - } - - public static JavaField newField(int modifiers, - String returnType, - String name, - boolean override) { - return newField(modifiers, returnType, name, override, null); - } - - public static JavaField newField(int modifiers, - String returnType, - String name, - boolean override, - String initializer, - String... initializerTypes) { - return new JavaField(modifiers, - returnType, - name, - override, - initializer, - initializerTypes - ); - } - - public static JavaConstructor newConstructor(int modifiers, - String name, - String body, - String[] exceptions, - JavaArgument... arguments) { - return new JavaConstructor(modifiers, - name, - arguments, - exceptions, - body - ); - } - - public static JavaConstructor newConstructor(int modifiers, - String name, - String body, - JavaArgument... arguments) { - return newConstructor(modifiers, - name, - body, - StringUtil.EMPTY_STRING_ARRAY, - arguments - ); - } - - public static JavaMethod newMethod(int modifiers, - String returnType, - String name, - String body, - boolean override, - String[] exceptions, - JavaArgument... arguments) { - if (log.isDebugEnabled()) { - log.debug(name + " returns : " + returnType); - } - return new JavaMethod(modifiers, - returnType, - name, - arguments, - exceptions, - body, - override - ); - } - - public static JavaMethod newMethod(int modifiers, - String returnType, - String name, - String body, - boolean override, - JavaArgument... arguments) { - return newMethod(modifiers, - returnType, - name, - body, - override, - StringUtil.EMPTY_STRING_ARRAY, - arguments - ); - } - - public static JavaField cloneField(JavaField field) { - return newField( - field.getModifiers(), - field.getType(), - field.getName(), - field.isOverride(), - field.getInitializer(), - field.getInitializerTypes()); - } - - public static JavaMethod cloneMethod(JavaMethod method) { - - String[] incomingExceptions = method.getExceptions(); - String[] exceptions = new String[incomingExceptions.length]; - System.arraycopy(incomingExceptions, 0, exceptions, 0, exceptions.length); - - JavaArgument[] oldArguments = method.getArguments(); - int nbArguments = oldArguments.length; - JavaArgument[] arguments = new JavaArgument[nbArguments]; - for (int i = 0; i < nbArguments; i++) { - JavaArgument argument = oldArguments[i]; - arguments[i] = cloneArgument(argument); - } - return newMethod( - method.getModifiers(), - method.getReturnType(), - method.getName(), - method.getBody(), - method.isOverride(), - exceptions, - arguments); - } - - public static JavaArgument cloneArgument(JavaArgument argument) { - return newArgument( - argument.getType(), - argument.getName(), - argument.isFinal() - ); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaField.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaField.java deleted file mode 100644 index 3c64027..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaField.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.java; - -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumMap; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.List; - -/** - * Represents a field in a Java source file being generated for output. <code>JavaFields</code> are created - * and added to a {@link JavaFile}, which can then output Java source code. - */ -public class JavaField extends JavaElement implements Comparable<JavaField> { - - /** type of field (fqn) */ - private String type; - - /** initializer of field (can be null) */ - private String initializer; - - /** - * Types to apply to the initializer to try use simple type names. - * - * @since 2.4 - */ - private String[] initializerTypes; - - - /** flag to known where a field overrides a super-field */ - private boolean override; - - /** - * Constructs a new <code>JavaField</code>. The <code>modifiers</code> parameter is a bit mask of the - * constants from {@link Modifier}, and the <code>type</code> of the field should be - * represented as it would appear in Java source code. - * - * @param modifiers the modifier keywords that should appear as part of the field's declaration - * @param type the type of the field as it would appear in Java source code - * @param name the field's name - * @param override flag to add @Override annotation on getter and setter - */ - JavaField(int modifiers, - String type, - String name, - boolean override) { - this(modifiers, type, name, override, null); - } - - /** - * Constructs a new <code>JavaField</code>. The <code>modifiers</code> parameter is a bit mask of the - * constants from <code>java.lang.reflect.Modifier</code>, and the <code>type</code> of the field should be - * represented as it would appear in Java source code. The <code>initializer</code> is the initial - * value of the field as it would appear in Java source code, or <code>null</code> to leave it at the - * default value. - * - * @param modifiers the modifier keywords that should appear as part of the field's declaration - * @param type the type of the field as it would appear in Java source code - * @param name the field's name - * @param override {@code true} if method should be marked as overriden - * @param initializer the initial value of the field, as it would appear in Java source code - * @param initializerTypes initializer types to use - */ - JavaField(int modifiers, - String type, - String name, - boolean override, - String initializer, - String... initializerTypes) { - super(modifiers, name); - this.type = type; - this.initializer = initializer; - this.initializerTypes = initializerTypes; - this.override = override; - } - - /** - * Returns the field's type, as it would be represented in Java source code. - * - * @return the field's type - */ - public String getType() { - return type; - } - - public boolean isOverride() { - return override; - } - - public String getInitializer() { - return initializer; - } - - public String[] getInitializerTypes() { - return initializerTypes; - } - - public boolean hasInitializerTypes() { - return initializerTypes != null && initializerTypes.length > 0; - } - - @Override - public int compareTo(JavaField o) { - return JavaElementComparator.compare(this, o); - } - - @Override - public String toString() { - return super.toString() + " " + getName() + ", type:" + - getType() + ", modifiers:" + Modifier.toString(getModifiers()); - } - - public void setType(String type) { - this.type = type; - } - - public void setInitializer(String initializer) { - this.initializer = initializer; - } - - public enum FieldOrder { - - staticsBean(Modifier.STATIC | Modifier.PUBLIC, - "Constants for all javaBean properties") { - @Override - public boolean accept(JavaField field) { - return field.getName().startsWith("PROPERTY_"); - } - }, - - staticsPublicBindings(Modifier.STATIC | Modifier.PUBLIC, - "Constants for all public bindings") { - @Override - public boolean accept(JavaField field) { - return field.getName().startsWith("BINDING_") && - Modifier.isPublic(field.getModifiers()); - } - }, - - staticsPrivateBindings(Modifier.STATIC | Modifier.PRIVATE, - "Constants for all none public bindings") { - @Override - public boolean accept(JavaField field) { - return field.getName().startsWith("BINDING_$") && - Modifier.isPrivate(field.getModifiers()); - } - }, - - staticsOthers(Modifier.STATIC, "Other static fields"), - - internalFields(Modifier.PROTECTED | Modifier.PRIVATE, - "Internal states") { - - private final List<String> fields = Arrays.asList( - "delegateContext", - "$previousValues", - "$bindingSources", - "$objectMap", - "$activeBindings", - "$bindings", - "$propertyChangeSupport"); - - @Override - public boolean accept(JavaField field) { - return fields.contains(field.getName()); - } - }, - publicFields(Modifier.PUBLIC, "Public components"), - protectedFields(Modifier.PROTECTED, "Protected components"), - privateFields(Modifier.PRIVATE, "Private components"), - otherFields(0, "Other fields") { - @Override - public boolean accept(JavaField field) { - return true; - } - }; - - private final String header; - - private int modifier; - - FieldOrder(int modifier, String header) { - this.header = JavaFileGenerator.getHeader(header); - this.modifier = modifier; - } - - public String getHeader() { - return header; - } - - public boolean accept(JavaField field) { - return true; - } - - public boolean accept(int mod) { - return (mod & modifier) != 0; - } - - public boolean accept(int mod, JavaField method) { - return accept(mod) && accept(method); - } - - public static FieldOrder valueOf(JavaField method, int scope) { - for (FieldOrder o : values()) { - if (o.accept(scope, method)) { - return o; - } - } - throw new IllegalArgumentException( - "could not find a " + FieldOrder.class + - " for method " + method); - } - } - - public static EnumMap<FieldOrder, List<JavaField>> getSortedFields(List<JavaField> fields) { - - EnumMap<FieldOrder, List<JavaField>> result = - new EnumMap<>(FieldOrder.class); - for (FieldOrder fieldOrder : FieldOrder.values()) { - result.put(fieldOrder, new ArrayList<JavaField>()); - } - - EnumSet<FieldOrder> allConstants = EnumSet.allOf(FieldOrder.class); - List<JavaField> allFields = new ArrayList<>(fields); - int[] scopes = new int[]{Modifier.STATIC, - Modifier.PUBLIC, - Modifier.PROTECTED, - Modifier.PRIVATE - }; - for (int scope : scopes) { - EnumSet<FieldOrder> constants = - getFieldOrderScope(allConstants, scope); - - Iterator<JavaField> itMethods = allFields.iterator(); - while (itMethods.hasNext()) { - JavaField method = itMethods.next(); - for (FieldOrder constant : constants) { - if (constant.accept(method.getModifiers(), method)) { - result.get(constant).add(method); - itMethods.remove(); - break; - } - } - } - constants.clear(); - } - - if (!allFields.isEmpty()) { - - // probably package locale fields - result.get(FieldOrder.otherFields).addAll(allFields); - } - - for (FieldOrder fieldOrder : FieldOrder.values()) { - // sort fields - Collections.sort(result.get(fieldOrder)); - } - return result; - } - - public static EnumSet<FieldOrder> getFieldOrderScope(EnumSet<FieldOrder> allConstants, int scope) { - EnumSet<FieldOrder> constants = EnumSet.noneOf(FieldOrder.class); - for (FieldOrder order : allConstants) { - if (order.accept(scope)) { - constants.add(order); - } - } - return constants; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaFile.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaFile.java deleted file mode 100644 index fdb4570..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaFile.java +++ /dev/null @@ -1,518 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.java; - -import jaxx.compiler.finalizers.JAXXCompilerFinalizer; -import jaxx.compiler.types.TypeManager; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.eugene.java.extension.ImportsManager; - -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * A Java source file being generated for output. Once the class is completely initialized, use the - * {@link #toString} method to generate source code for it. - */ -public class JavaFile extends JavaElement { - - /** Logger. */ - static Log log = LogFactory.getLog(JavaFile.class); - - protected static final String GETTER_PATTERN = "return %1$s;"; - - protected static final String BOOLEAN_GETTER_PATTERN = "return %1$s !=null && %1$s;"; - - protected static final String SETTER_PATTERN = "%1$s oldValue = this.%2$s;\nthis.%2$s = %2$s;\nfirePropertyChange(%3$s, oldValue, %2$s);"; - - private Set<String> imports = new HashSet<>(); - - private List<JavaField> fields = new ArrayList<>(); - - private List<JavaMethod> methods = new ArrayList<>(); - - private List<JavaConstructor> constructors = new ArrayList<>(); - - private List<JavaFile> innerClasses = new ArrayList<>(); - - private String superClass; - - private List<String> interfaces; - - private StringBuilder rawBodyCode = new StringBuilder(); - - private boolean superclassIsJAXXObject; - - private boolean abstractClass; - - private String genericType; - - private String superGenericType; - - private final ImportsManager importManager; - - private String simpleName; - - JavaFile(int modifiers, String className) { - super(modifiers, className); - importManager = new ImportsManager(); - // add the fqn before all in the import manager to deal with alias classes - importManager.addImport(className); - } - - /** @deprecated since 2.4, never be used */ - @Deprecated - JavaFile() { - this(0, ""); - } - - /** - * @param modifiers - * @param className - * @param superClass - * @deprecated since 2.4, never be used - */ - @Deprecated - JavaFile(int modifiers, String className, String superClass) { - this(modifiers, className, superClass, null); - } - - /** - * @param modifiers - * @param className - * @param superClass - * @param interfaces - * @deprecated since 2.4, never be used - */ - @Deprecated - JavaFile(int modifiers, - String className, - String superClass, - List<String> interfaces) { - this(modifiers, className); - setSuperClass(superClass); - if (CollectionUtils.isNotEmpty(interfaces)) { - addInterface(interfaces.toArray(new String[interfaces.size()])); - } - } - - public String getPackageName() { - String name = getName(); - - String packageName; - if (name.contains(".")) { - packageName = name.substring(0, name.lastIndexOf(".")); - } else { - packageName = null; - } - return packageName; - } - - public ImportsManager getImportManager() { - return importManager; - } - - public String getImportedType(Class<?> type) { - return getImportManager().getType(type); - } - - public String getImportedType(String type) { - return getImportManager().getType(type); - } - - public String[] getImports() { - List<String> result = new ArrayList<>(imports); - Collections.sort(result); - return result.toArray(new String[result.size()]); - } - - public List<String> getImportsList() { - List<String> result = new ArrayList<>(imports); - Collections.sort(result); - return result; - } - - public String getSuperClass() { - return superClass; - } - - public List<String> getInterfaces() { - if (interfaces == null) { - interfaces = new ArrayList<>(); - } - return interfaces; - } - - public List<JavaMethod> getMethods() { - return methods; - } - - public List<JavaField> getFields() { - return fields; - } - - public boolean isAbstractClass() { - return abstractClass; - } - - public String getGenericType() { - return genericType; - } - - public List<JavaFile> getInnerClasses() { - return innerClasses; - } - - public StringBuilder getRawBodyCode() { - return rawBodyCode; - } - - public String getSuperGenericType() { - return superGenericType; - } - - public boolean isSuperclassIsJAXXObject() { - return superclassIsJAXXObject; - } - - public String getSimpleName() { - return simpleName; - } - - public JavaField getField(String componentId) { - for (JavaField field : fields) { - if (componentId.equals(field.getName())) { - return field; - } - } - return null; - } - - public void addImport(String importString) { - try { - importManager.addImport(importString); - } catch (Exception e) { - log.error("Could not determine simple name of import " + importString); - } - } - - public void addImport(Class<?> importString) { - addImport(importString.getName()); - } - - public void setImports(Collection<String> imports) { - this.imports = new HashSet<>(imports); - } - - public void setGenericType(String genericType) { - this.genericType = genericType; - } - - public void setSuperClass(String superClass) { - this.superClass = superClass; - } - - public void addInterface(String... canonicalNames) { - if (canonicalNames == null) { - return; - } - for (String canonicalName : canonicalNames) { - if (interfaces == null || !interfaces.contains(canonicalName)) { - getInterfaces().add(canonicalName); - } - } - } - - public void setInterfaces(List<String> interfaces) { - List<String> simpleInterfaces = new ArrayList<>(); - for (String anInterface : interfaces) { - try { - anInterface = importManager.getType(anInterface); - } catch (Exception e) { - log.error("Could not determine simple name of interface " + - anInterface); - } - simpleInterfaces.add(anInterface); - } - this.interfaces = simpleInterfaces; - } - - public void addConstructor(JavaConstructor constructor) { - constructors.add(constructor); - } - - public void addMethod(JavaMethod method) { - String returnType = method.getReturnType(); - try { - String type = importManager.getReturnType(returnType); - method.setReturnType(type); - } catch (Exception e) { - log.error("Could not determine simple name of return type " + - returnType + " for method " + method.getName()); - } - for (JavaArgument argument : method.getArguments()) { - String argumentType = argument.getType(); - try { - String type = importManager.getType(argumentType); - argument.setType(type); - } catch (Exception e) { - log.error("Could not determine simple name of argument type " + - argumentType + " of argument " + argument.getName() + - " for method " + method.getName()); - } - } - - String[] exceptions = method.getExceptions(); - for (int i = 0, length = exceptions.length; i < length; i++) { - String exception = exceptions[i]; - try { - String exceptionSimple = importManager.getType(exception); - exceptions[i] = exceptionSimple; - } catch (Exception e) { - log.error("Could not determine simple name of exception " + - exception + " for method " + method.getName()); - } - - } - - // this is a mreal method - methods.add(method); - } - - public void addField(JavaField field) { - - addField(field, false); - } - - public JavaMethod addGetterMethod(String id, - int modifiers, - String type, - boolean overridde, - boolean useOverride) { - - String capitalizedName = StringUtils.capitalize(id); - String methodName = "get" + capitalizedName; - String bodyCode; - if (useOverride) { - bodyCode = "super." + methodName + "()"; - } else { - bodyCode = id; - } - String content = String.format(GETTER_PATTERN, bodyCode); - JavaMethod method = JavaElementFactory.newMethod(modifiers, - type, - methodName, - content, - overridde - ); - addMethod(method); - return method; - } - - public JavaMethod addOverrideGetterMethod(String id, - int modifiers, - String type, - boolean useOverride) { - - String capitalizedName = StringUtils.capitalize(id); - String methodName = "get" + capitalizedName; - String bodyCode; - if (useOverride) { - bodyCode = "super." + methodName + "()"; - } else { - bodyCode = id; - } - bodyCode = "(" + type + ")" + bodyCode; - String content = String.format(GETTER_PATTERN, bodyCode); - JavaMethod method = JavaElementFactory.newMethod(modifiers, - type, - methodName, - content, - true - ); - addMethod(method); - return method; - } - - public void addField(JavaField field, boolean javaBean) { - addSimpleField(field); - String id = field.getName(); - String capitalizedName = StringUtils.capitalize(id); - - // add accessor method - int modifiers = Modifier.isProtected(field.getModifiers()) ? - Modifier.PUBLIC : Modifier.PROTECTED; - - addGetterMethod(id, - modifiers, - field.getType(), - field.isOverride(), - false - ); - - if (javaBean) { - // add full javabean support accessor + mutator + constant with - // name of property to make it easier to use - // compute the property constant - String constantId = TypeManager.convertVariableNameToConstantName( - "property" + capitalizedName); - addSimpleField(JavaElementFactory.newField( - Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL, - JAXXCompilerFinalizer.TYPE_STRING, - constantId, false, "\"" + id + "\"") - ); - - if (Boolean.class.getSimpleName().equals(field.getType())) { - String content = String.format(BOOLEAN_GETTER_PATTERN, id); - JavaMethod method = JavaElementFactory.newMethod( - Modifier.PUBLIC, - field.getType(), - "is" + capitalizedName, - content, - field.isOverride() - ); - addMethod(method); - } - String content = String.format(SETTER_PATTERN, - field.getType(), - id, - constantId - ); - JavaArgument arg = JavaElementFactory.newArgument(field.getType(), - id); - JavaMethod method = JavaElementFactory.newMethod( - Modifier.PUBLIC, - JAXXCompilerFinalizer.TYPE_VOID, - "set" + capitalizedName, - content, - field.isOverride(), - arg); - addMethod(method); - } - } - - public void addSimpleField(JavaField field) { - if (log.isDebugEnabled()) { - log.debug("[" + getName() + "] Add field " + field.getName()); - } - String fieldType = field.getType(); - try { - String type = importManager.getType(fieldType); - field.setType(type); - } catch (Exception e) { - log.error("Could not determine simple name of field [" + - field.getName() + "] type " + fieldType); - } - if (field.hasInitializerTypes()) { - String code = simplifyCode(field.getInitializer(), - field.getInitializerTypes()); - if (log.isDebugEnabled()) { - log.debug("Use simplify text : " + code); - } - field.setInitializer(code); - } - fields.add(field); - } - - public void setSuperclassIsJAXXObject(boolean superclassIsJAXXObject) { - this.superclassIsJAXXObject = superclassIsJAXXObject; - } - - public void setAbstractClass(boolean abstractClass) { - this.abstractClass = abstractClass; - } - - public void setSuperGenericType(String superGenericType) { - this.superGenericType = superGenericType; - } - - public void addBodyCode(String bodyCode) { - rawBodyCode.append(bodyCode); - } - - /** - * Try to use a simple type fro the given {@code type} and apply it on the - * given {@code pattern}. - * - * Example : - * <pre> - * type = java.io.File, pattern = new %s(""); - * returns : new File("") or new java.io.File("") if importManager can - * not import java.io.File - * </pre> - * - * @param types the types to simplify - * @param pattern the pattern where to apply simple types - * @return the input pattern with most simplest types - * @since 2.4 - */ - public String simplifyCode(String pattern, - String... types) { - String[] simpleTypes = new String[types.length]; - for (int i = 0; i < types.length; i++) { - String type = types[i]; - String simpleType = importManager.getType(type); - simpleTypes[i] = simpleType; - } - return String.format(pattern, (Object[]) simpleTypes); - } - - public void clear() { - importManager.clearImports(); - if (interfaces != null) { - interfaces.clear(); - interfaces = null; - } - if (methods != null) { - methods.clear(); - methods = null; - } - if (constructors != null) { - constructors.clear(); - constructors = null; - } - if (fields != null) { - fields.clear(); - fields = null; - } - if (imports != null) { - imports.clear(); - } - } - - public List<JavaConstructor> getConstructors() { - return constructors; - } - - public void setSimpleName(String simpleName) { - this.simpleName = simpleName; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaFileGenerator.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaFileGenerator.java deleted file mode 100644 index 740f1ea..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaFileGenerator.java +++ /dev/null @@ -1,453 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.java; - -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.java.JavaMethod.MethodOrder; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumMap; -import java.util.List; -import java.util.Map.Entry; - -/** - * Java file generator. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.0 - */ -public class JavaFileGenerator { - - /** Logger. */ - static private final Log log = LogFactory.getLog(JavaFileGenerator.class); - - public static String getHeader(String header) { - String all = "/*-----------------------------------------------------------------------*/"; - int size = header.length(); - if (size % 2 == 0) { - size++; - header = header + " "; - } - int semi = (all.length() - size) / 2 - 5; - char[] prefix = new char[semi]; - Arrays.fill(prefix, '-'); - - String eol = JAXXCompiler.getLineSeparator(); - - return all + eol + "/*--" + new String(prefix) + - " " + header + " " + new String(prefix) + "--*/" + eol + all + - eol; - } - - /** End of line */ - protected final String eol; - - /** verbose flag when generates */ - protected final boolean verbose; - - /** current prefix indent size */ - protected int indentationLevel; - - public JavaFileGenerator(String eol, boolean verbose) { - this.eol = eol; - this.verbose = verbose && log.isDebugEnabled(); - } - - public static String addDebugLoggerInvocation(JAXXCompiler compiler, - String call) { - String eol = JAXXCompiler.getLineSeparator(); - StringBuilder builder = new StringBuilder(); - if (!compiler.getConfiguration().isAddLogger()) { - return ""; - } else { - builder.append("if (log.isDebugEnabled()) {"); - builder.append(eol); - builder.append(" log.debug(").append(call).append(");"); - builder.append(eol); - builder.append("}"); - builder.append(eol); - } - return builder.toString(); - } - - public String generateImport(String anImport) { - return "import " + anImport + ';' + eol; - } - - public void generateFile(JavaFile f, PrintWriter result) { - String name = f.getName(); - if (verbose) { - log.info(name); - } - indentationLevel = 0; - String packageName = f.getPackageName(); -// if (name.contains(".")) { - if (packageName != null) { -// packageName = name.substring(0, name.lastIndexOf(".")); - result.append("package "); - result.append(packageName); - result.append(";"); - result.append(eol).append(eol); - } - - generateImports(f, result); - - result.append(generateClass(f)); - } - - public void generateImports(JavaFile f, PrintWriter result) { - - List<String> imports = f.getImportsList(); - - boolean addImports = CollectionUtils.isNotEmpty(imports); - for (String anImport : imports) { - result.append(generateImport(anImport)); - } - - if (addImports) { - result.append(eol); - } - } - - public String generateClass(JavaFile f) { - if (verbose) { - log.info(f.getName()); - } - - StringBuilder result = new StringBuilder(); - String genericType = f.getGenericType(); - - result.append(f.getModifiersText()); - if (f.isAbstractClass()) { - result.append("abstract "); - } - result.append("class "); - result.append(f.getName().substring(f.getName().lastIndexOf(".") + 1)); - if (genericType != null) { - result.append('<').append(genericType).append('>'); - } - result.append(" extends "); - result.append(f.getSuperClass()); - if (f.getSuperGenericType() != null) { - result.append('<').append(f.getSuperGenericType()).append('>'); - } - List<String> interfaces = f.getInterfaces(); - - if (interfaces != null && !interfaces.isEmpty()) { - result.append(" implements ").append(interfaces.get(0)); - for (int i = 1; i < interfaces.size(); i++) { - result.append(", ").append(interfaces.get(i)); - } - } - result.append(" {").append(eol); - - // generate fields - - List<JavaField> fields = f.getFields(); - - if (!fields.isEmpty()) { - - EnumMap<JavaField.FieldOrder, List<JavaField>> map = - JavaField.getSortedFields(fields); - for (Entry<JavaField.FieldOrder, List<JavaField>> entry : - map.entrySet()) { - - List<JavaField> list = entry.getValue(); - - // sort fields - Collections.sort(list); - - if (!list.isEmpty()) { - - // add field group header - result.append(eol); - result.append( - addIndentation(entry.getKey().getHeader(), 4, eol)); - result.append(eol); - result.append(eol); - - // add all fields of group - for (JavaField method : list) { - String txt = generateField(method); - result.append(addIndentation(txt, 4, eol)).append(eol); - } - } - list.clear(); - } - map.clear(); - result.append(eol); - } - - // generate raw body - - StringBuilder rawBodyCode = f.getRawBodyCode(); - - if (rawBodyCode.length() > 0) { - result.append(addIndentation( - getHeader("Raw body code from script"), 4, eol)); - result.append(eol); - String s = rawBodyCode.toString(); - if (!s.startsWith(eol)) { - result.append(eol); - } - result.append(addIndentation(s, 4, eol)).append(eol).append(eol); - } - - // generate inner classes - - List<JavaFile> innerClasses = f.getInnerClasses(); - for (JavaFile innerClass : innerClasses) { - indentationLevel += 4; - try { - String txt = generateClass(innerClass); - result.append(addIndentation(txt, 4, eol)); - result.append(eol); - result.append(eol); - } finally { - indentationLevel -= 4; - } - } - - - // add constructors : - - result.append(addIndentation(MethodOrder.constructors.getHeader(), 4, eol)); - result.append(eol); - result.append(eol); - - // add all constructors - for (JavaConstructor method : f.getConstructors()) { - String txt = generateConstructor(method); - result.append(addIndentation(txt, 4, eol)); - result.append(eol); - result.append(eol); - } - - // generate methods - EnumMap<MethodOrder, List<JavaMethod>> map = - JavaMethod.getSortedMethods(f.getMethods()); - - for (Entry<MethodOrder, List<JavaMethod>> entry : map.entrySet()) { - List<JavaMethod> list = entry.getValue(); - if (!list.isEmpty()) { - - // sort methods - Collections.sort(list); - - // add method group header - result.append(addIndentation(entry.getKey().getHeader(), 4, eol)); - result.append(eol); - result.append(eol); - - // add all methods of group - for (JavaMethod method : list) { - String txt = generateMethod(method); - result.append(addIndentation(txt, 4, eol)); - result.append(eol); - result.append(eol); - } - } - list.clear(); - } - map.clear(); - result.append("}"); - return result.toString(); - } - - public String generateField(JavaField f) { - if (verbose) { - if (log.isDebugEnabled()) { - log.debug(f.getName()); - } - } - StringBuilder result = new StringBuilder(); - generateAnnotations(f, result, eol); - result.append(f.getModifiersText()); - result.append(f.getType()).append(' ').append(f.getName()); - if (f.getInitializer() != null) { - result.append(" = ").append(f.getInitializer()); - } - result.append(';').append(eol); - return result.toString(); - } - - protected void generateAnnotations(JavaElement element, - StringBuilder result, - String separator) { - if (element.hasAnnotations()) { - for (String annotation : element.getAnnotations()) { - if (!annotation.startsWith("@")) { - result.append("@"); - } - result.append(annotation).append(separator); - } - } - } - - public String generateConstructor(JavaConstructor m) { - if (verbose) { - log.info(m.getName()); - } - - StringBuilder result = new StringBuilder(); - - generateAnnotations(m, result, eol); - result.append(m.getModifiersText()); - result.append(m.getName()); - result.append('('); - JavaArgument[] arguments = m.getArguments(); - - // adding arguments - - if (arguments != null && arguments.length > 0) { - result.append(generateArgument(arguments[0])); - for (int i = 1; i < arguments.length; i++) { - result.append(", ").append(generateArgument(arguments[i])); - } - } - result.append(")"); - - // adding exceptions - - String[] exceptions = m.getExceptions(); - if (exceptions != null && exceptions.length > 0) { - result.append(" throws ").append(exceptions[0]); - for (int i = 1; i < exceptions.length; i++) { - result.append(", ").append(exceptions[i]); - } - } - result.append(" {"); - result.append(eol); - - // adding body - - String body = m.getBody(); - - if (body != null) { - String formattedBodyCode = addIndentation(body.trim(), 4, eol); - if (formattedBodyCode.length() > 0) { - result.append(formattedBodyCode).append(eol); - } - } - result.append("}"); - return result.toString(); - - } - - public String generateMethod(JavaMethod m) { - if (verbose) { - log.info(m.getName()); - } - - StringBuilder result = new StringBuilder(); - if (m.isOverride()) { - m.addAnnotation(Override.class.getSimpleName()); - } - generateAnnotations(m, result, eol); - result.append(m.getModifiersText()); - if (m.getReturnType() != null) { - result.append(m.getReturnType()); - result.append(' '); - } - result.append(m.getName()); - result.append('('); - JavaArgument[] arguments = m.getArguments(); - - // adding arguments - - if (arguments != null && arguments.length > 0) { - result.append(generateArgument(arguments[0])); - for (int i = 1; i < arguments.length; i++) { - result.append(", ").append(generateArgument(arguments[i])); - } - } - result.append(")"); - - // adding exceptions - - String[] exceptions = m.getExceptions(); - if (exceptions != null && exceptions.length > 0) { - result.append(" throws ").append(exceptions[0]); - for (int i = 1; i < exceptions.length; i++) { - result.append(", ").append(exceptions[i]); - } - } - result.append(" {"); - result.append(eol); - - // adding body - - String body = m.getBody(); - - if (body != null) { - String formattedBodyCode = addIndentation(body.trim(), 4, eol); - if (formattedBodyCode.length() > 0) { - result.append(formattedBodyCode).append(eol); - } - } - result.append("}"); - return result.toString(); - - } - - public String generateArgument(JavaArgument argument) { - String result = argument.getType() + ' ' + argument.getName(); - return argument.isFinal() ? "final " + result : result; - } - - public String addIndentation(String source, - int indentation, - String lineSeparator) { - return indent(source, - indentationLevel + indentation, - false, - lineSeparator - ); - } - - public static String indent(String source, - int indentation, - boolean trim, - String lineSeparator) { - if (trim) { - source = source.trim(); - } - char[] spaces = new char[indentation]; - Arrays.fill(spaces, ' '); - StringBuilder result = new StringBuilder(); - String[] lines = source.split(lineSeparator + "|\n"); - for (int i = 0; i < lines.length; i++) { - if (i > 0) { - result.append(lineSeparator); - } - result.append(spaces); - result.append(trim ? lines[i].trim() : lines[i]); - } - return result.toString(); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaMethod.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaMethod.java deleted file mode 100644 index 4896759..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaMethod.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.java; - -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumMap; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.List; - -/** - * Represents a method in a Java source file being generated for output. <code>JavaMethods</code> are created - * and added to a {@link JavaFile}, which can then output Java source code. In addition to normal methods, a - * <code>JavaMethod</code> can represent a constructor -- constructors should be named after their containing - * classes and have a return type of <code>null</code>. - */ -public class JavaMethod extends JavaElement implements Comparable<JavaMethod> { - - /** return type of the method (null for constructors) */ - private String returnType; - - /** arguments of the method (can be empty) */ - private JavaArgument[] arguments; - - /** exceptions thrown by the method (can be empty) */ - private String[] exceptions; - - /** body of the method (can be empty) */ - private String body; - - /** flag to known if the method overrids a super-method */ - private boolean override; - - /** - * Constructs a new <code>JavaMethod</code> containing the specified body code. The <code>modifiers</code> parameter - * is a bit mask of the constants from {@link Modifier}, and the <code>returnType</code> and - * <code>exceptions</code> of the method should be represented as they would appear in Java source code (<code>null</code> - * for a constructor). The method body is initially empty. - * - * @param modifiers the modifier keywords that should appear as part of the method's declaration - * @param returnType the return type of the method as it would appear in Java source code - * @param name the method's name - * @param arguments the method's arguments - * @param exceptions a list of exceptions the methods can throw, as they would be represented in Java source code - * @param bodyCode Java source code which should appear in the method body - * @param override flag with {@code true} value when the method overrides (or implements) a super class method - */ - JavaMethod(int modifiers, - String returnType, - String name, - JavaArgument[] arguments, - String[] exceptions, - String bodyCode, - boolean override) { - super(modifiers, name); - this.returnType = returnType; - this.override = override; - this.arguments = arguments; - this.exceptions = exceptions; - body = bodyCode == null ? "" : bodyCode; - } - - /** - * Returns the method's return type, as it would be represented - * in Java source code. - * - * @return the method's return type - */ - public String getReturnType() { - return returnType; - } - - /** - * Returns a list of the method's arguments. - * - * @return the method's arguments - */ - public JavaArgument[] getArguments() { - return arguments; - } - - /** - * Returns a list of exceptions the method can throw. - * - * @return the method's exceptions - */ - public String[] getExceptions() { - return exceptions; - } - - public boolean isOverride() { - return override; - } - - public String getBody() { - return body; - } - - public void setBody(String body) { - this.body = body; - } - - @Override - public int compareTo(JavaMethod o) { - return JavaElementComparator.compare(this, o); - } - - public void setReturnType(String returnType) { - this.returnType = returnType; - } - - public enum MethodOrder { - - statics(Modifier.STATIC, "Statics methods"), - - constructors(Modifier.PUBLIC, "Constructors") { - @Override - public boolean accept(JavaMethod method) { - return method.returnType == null; - } - }, - JAXXObject(Modifier.PUBLIC, "JAXXObject implementation") { - - private final List<String> methods = Arrays.asList( - "applyDataBinding", - "firePropertyChange", - "getObjectById", - "get$objectMap", - "processDataBinding", - "removeDataBinding", - "registerDataBinding", - "getDataBindings", - "getDataBinding"); - - @Override - public boolean accept(JavaMethod method) { - return methods.contains(method.getName()); - } - }, - JAXXContext(Modifier.PUBLIC, "JAXXContext implementation") { - - private final List<String> methods = Arrays.asList( - "getContextValue", - "getDelegateContext", - "getParentContainer", - "removeContextValue", - "setContextValue"); - - @Override - public boolean accept(JavaMethod method) { - return methods.contains(method.getName()); - } - }, - JAXXValidation(Modifier.PUBLIC, "JAXXValidator implementation") { - - private final List<String> methods = - Arrays.asList("getValidator", "getValidatorIds", "registerValidatorFields"); - - @Override - public boolean accept(JavaMethod method) { - boolean contains = methods.contains(method.getName()); - if (contains && method.getName().equals("getValidator")) { - // only accept the method getValidator(String) and not anything else... - // since user can have a validator field which is a validator, but not part of the - // JAXXValidatator contract - return method.getArguments().length == 1; - } - return contains; - } - }, - events(Modifier.PUBLIC, "Event methods") { - @Override - public boolean accept(JavaMethod method) { - return method.getName().startsWith("do") && - method.getName().contains("__"); - } - }, - publicGetters(Modifier.PUBLIC, "Public acessor methods") { - @Override - public boolean accept(JavaMethod method) { - return method.getName().startsWith("get") || - method.getName().startsWith("is"); - } - }, - publicSetters(Modifier.PUBLIC, "Public mutator methods") { - @Override - public boolean accept(JavaMethod method) { - return method.getName().startsWith("set"); - } - }, - otherPublic(Modifier.PUBLIC, "Other methods") { - @Override - public boolean accept(int mod) { - return super.accept(mod) && !Modifier.isStatic(mod); - } - }, - protectedGetters(Modifier.PROTECTED, "Protected acessors methods") { - @Override - public boolean accept(JavaMethod method) { - return method.getName().startsWith("get") || - method.getName().startsWith("is"); - } - }, - createMethod(Modifier.PROTECTED | Modifier.PRIVATE, - "Components creation methods") { - @Override - public boolean accept(JavaMethod method) { - return method.getName().startsWith("create") || - method.getName().startsWith("add"); - } - }, - internalMethod(Modifier.PROTECTED, "Internal jaxx methods") { - private final List<String> methods = Arrays.asList( - "$initialize", - "$initialize_01_createComponents", - "$initialize_02_registerDataBindings", - "$initialize_03_finalizeCreateComponents", - "$initialize_04_applyDataBindings", - "$initialize_05_setProperties", - "$initialize_06_finalizeInitialize"); - - @Override - public boolean accept(JavaMethod method) { - return methods.contains(method.getName()); - } - }, - protecteds(Modifier.PROTECTED, "Other protected methods") { - }, - packageLocal(0, "Package methods") { - @Override - public boolean accept(int mod) { - return !Modifier.isStatic(mod) && - !Modifier.isPublic(mod) && - !Modifier.isProtected(mod); - } - }, - privates(Modifier.PRIVATE, "Other private methods"); - - private final String header; - - private int modifier; - - MethodOrder(int modifier, String header) { - this.header = JavaFileGenerator.getHeader(header); - this.modifier = modifier; - } - - public String getHeader() { - return header; - } - - public boolean accept(JavaMethod method) { - return true; - } - - public boolean accept(int mod) { - return (mod & modifier) != 0; - } - - public boolean accept(int mod, JavaMethod method) { - return accept(mod) && accept(method); - } - - public static MethodOrder valueOf(JavaMethod method, int scope) { - for (MethodOrder o : values()) { - if (o.accept(scope, method)) { - return o; - } - } - throw new IllegalArgumentException( - "could not find a " + MethodOrder.class + - " for method " + method); - } - } - - public static EnumMap<MethodOrder, List<JavaMethod>> getSortedMethods(List<JavaMethod> methods) { - - EnumMap<MethodOrder, List<JavaMethod>> result = - new EnumMap<>(MethodOrder.class); - for (MethodOrder methodOrder : MethodOrder.values()) { - result.put(methodOrder, new ArrayList<JavaMethod>()); - } - - EnumSet<MethodOrder> allConstants = EnumSet.allOf(MethodOrder.class); - List<JavaMethod> allMethods = new ArrayList<>(methods); - int[] scopes = new int[]{Modifier.STATIC, - Modifier.PUBLIC, - Modifier.PROTECTED, - Modifier.PRIVATE - }; - for (int scope : scopes) { - EnumSet<MethodOrder> constants = - getMethodOrderScope(allConstants, scope); - - Iterator<JavaMethod> itMethods = allMethods.iterator(); - while (itMethods.hasNext()) { - JavaMethod method = itMethods.next(); - for (MethodOrder constant : constants) { - if (constant.accept(method.getModifiers(), method)) { - result.get(constant).add(method); - itMethods.remove(); - break; - } - } - } - constants.clear(); - } - - if (!allMethods.isEmpty()) { - throw new IllegalArgumentException( - "could not find a " + MethodOrder.class + - " for method " + allMethods); - } - - for (MethodOrder methodOrder : MethodOrder.values()) { - // sort methods - Collections.sort(result.get(methodOrder)); - } - return result; - } - - public static EnumSet<MethodOrder> getMethodOrderScope(EnumSet<MethodOrder> allConstants, int scope) { - EnumSet<MethodOrder> constants = EnumSet.noneOf(MethodOrder.class); - for (MethodOrder order : allConstants) { - if (order.accept(scope)) { - constants.add(order); - } - } - return constants; - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JJTJavaParserState.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JJTJavaParserState.java deleted file mode 100644 index 08bf924..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JJTJavaParserState.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JJTree: Do not edit this line. .\JJTJavaParserState.java */ - - -package jaxx.compiler.java.parser; - -class JJTJavaParserState { - private java.util.Stack<Node> nodes; - - private java.util.Stack<Integer> marks; - - private int sp; // number of nodes on stack - - private int mk; // current mark - - private boolean node_created; - - JJTJavaParserState() { - nodes = new java.util.Stack<>(); - marks = new java.util.Stack<>(); - sp = 0; - mk = 0; - } - - /* Determines whether the current node was actually closed and - pushed. This should only be called in the final user action of a - node scope. */ - boolean nodeCreated() { - return node_created; - } - - /* Call this to reinitialize the node stack. It is called -automatically by the parser's ReInit() method. */ - void reset() { - nodes.removeAllElements(); - marks.removeAllElements(); - sp = 0; - mk = 0; - } - - /* Returns the root node of the AST. It only makes sense to call -this after a successful parse. */ - Node rootNode() { - return nodes.elementAt(0); - } - - /* Pushes a node on to the stack. */ - void pushNode(Node n) { - nodes.push(n); - ++sp; - } - - /* Returns the node on the top of the stack, and remove it from the - stack. */ - Node popNode() { - if (--sp < mk) { - mk = marks.pop(); - } - return nodes.pop(); - } - - /* Returns the node currently on the top of the stack. */ - Node peekNode() { - return nodes.peek(); - } - - /* Returns the number of children on the stack in the current node - scope. */ - int nodeArity() { - return sp - mk; - } - - - void clearNodeScope(Node n) { - while (sp > mk) { - popNode(); - } - mk = marks.pop(); - } - - - void openNodeScope(Node n) { - marks.push(mk); - mk = sp; - n.jjtOpen(); - } - - - /* A definite node is constructed from a specified number of -children. That number of nodes are popped from the stack and -made the children of the definite node. Then the definite node -is pushed on to the stack. */ - void closeNodeScope(Node n, int num) { - mk = marks.pop(); - while (num-- > 0) { - Node c = popNode(); - c.jjtSetParent(n); - n.jjtAddChild(c, num); - } - n.jjtClose(); - pushNode(n); - node_created = true; - } - - - /* A conditional node is constructed if its condition is true. All -the nodes that have been pushed since the node was opened are -made children of the the conditional node, which is then pushed -on to the stack. If the condition is false the node is not -constructed and they are left on the stack. */ - void closeNodeScope(Node n, boolean condition) { - if (condition) { - int a = nodeArity(); - mk = marks.pop(); - while (a-- > 0) { - Node c = popNode(); - c.jjtSetParent(n); - n.jjtAddChild(c, a); - } - n.jjtClose(); - pushNode(n); - node_created = true; - } else { - mk = marks.pop(); - node_created = false; - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaCharStream.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaCharStream.java deleted file mode 100644 index 7902fde..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaCharStream.java +++ /dev/null @@ -1,560 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JavaCC: Do not edit this line. JavaCharStream.java Version 4.0 */ - -package jaxx.compiler.java.parser; - -/** - * An implementation of interface CharStream, where the stream is assumed to - * contain only ASCII characters (with java-like unicode escape processing). - */ - -public class JavaCharStream { - public static final boolean staticFlag = false; - - static int hexval(char c) throws java.io.IOException { - switch (c) { - case '0': - return 0; - case '1': - return 1; - case '2': - return 2; - case '3': - return 3; - case '4': - return 4; - case '5': - return 5; - case '6': - return 6; - case '7': - return 7; - case '8': - return 8; - case '9': - return 9; - - case 'a': - case 'A': - return 10; - case 'b': - case 'B': - return 11; - case 'c': - case 'C': - return 12; - case 'd': - case 'D': - return 13; - case 'e': - case 'E': - return 14; - case 'f': - case 'F': - return 15; - } - - throw new java.io.IOException(); // Should never come here - } - - public int bufpos = -1; - - int bufsize; - - int available; - - int tokenBegin; - - protected int bufline[]; - - protected int bufcolumn[]; - - protected int column = 0; - - protected int line = 1; - - protected boolean prevCharIsCR = false; - - protected boolean prevCharIsLF = false; - - protected java.io.Reader inputStream; - - protected char[] nextCharBuf; - - protected char[] buffer; - - protected int maxNextCharInd = 0; - - protected int nextCharInd = -1; - - protected int inBuf = 0; - - protected int tabSize = 8; - - protected void setTabSize(int i) { - tabSize = i; - } - - protected int getTabSize(int i) { - return tabSize; - } - - protected void ExpandBuff(boolean wrapAround) { - char[] newbuffer = new char[bufsize + 2048]; - int newbufline[] = new int[bufsize + 2048]; - int newbufcolumn[] = new int[bufsize + 2048]; - - try { - if (wrapAround) { - System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); - System.arraycopy(buffer, 0, newbuffer, - bufsize - tokenBegin, bufpos); - buffer = newbuffer; - - System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); - System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); - bufline = newbufline; - - System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); - System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); - bufcolumn = newbufcolumn; - - bufpos += (bufsize - tokenBegin); - } else { - System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); - buffer = newbuffer; - - System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); - bufline = newbufline; - - System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); - bufcolumn = newbufcolumn; - - bufpos -= tokenBegin; - } - } catch (Throwable t) { - throw new Error(t.getMessage()); - } - - available = (bufsize += 2048); - tokenBegin = 0; - } - - protected void FillBuff() throws java.io.IOException { - int i; - if (maxNextCharInd == 4096) - maxNextCharInd = nextCharInd = 0; - - try { - if ((i = inputStream.read(nextCharBuf, maxNextCharInd, - 4096 - maxNextCharInd)) == -1) { - inputStream.close(); - throw new java.io.IOException(); - } else { - maxNextCharInd += i; - } - } catch (java.io.IOException e) { - if (bufpos != 0) { - --bufpos; - backup(0); - } else { - bufline[bufpos] = line; - bufcolumn[bufpos] = column; - } - throw e; - } - } - - protected char ReadByte() throws java.io.IOException { - if (++nextCharInd >= maxNextCharInd) - FillBuff(); - - return nextCharBuf[nextCharInd]; - } - - public char BeginToken() throws java.io.IOException { - if (inBuf > 0) { - --inBuf; - - if (++bufpos == bufsize) { - bufpos = 0; - } - - tokenBegin = bufpos; - return buffer[bufpos]; - } - - tokenBegin = 0; - bufpos = -1; - - return readChar(); - } - - protected void AdjustBuffSize() { - if (available == bufsize) { - if (tokenBegin > 2048) { - bufpos = 0; - available = tokenBegin; - } else - ExpandBuff(false); - } else if (available > tokenBegin) - available = bufsize; - else if ((tokenBegin - available) < 2048) - ExpandBuff(true); - else - available = tokenBegin; - } - - protected void UpdateLineColumn(char c) { - column++; - - if (prevCharIsLF) { - prevCharIsLF = false; - line += (column = 1); - } else if (prevCharIsCR) { - prevCharIsCR = false; - if (c == '\n') { - prevCharIsLF = true; - } else - line += (column = 1); - } - - switch (c) { - case '\r': - prevCharIsCR = true; - break; - case '\n': - prevCharIsLF = true; - break; - case '\t': - column--; - column += (tabSize - (column % tabSize)); - break; - default: - break; - } - - bufline[bufpos] = line; - bufcolumn[bufpos] = column; - } - - public char readChar() throws java.io.IOException { - if (inBuf > 0) { - --inBuf; - - if (++bufpos == bufsize) - bufpos = 0; - - return buffer[bufpos]; - } - - char c; - - if (++bufpos == available) - AdjustBuffSize(); - - if ((buffer[bufpos] = c = ReadByte()) == '\\') { - UpdateLineColumn(c); - - int backSlashCnt = 1; - - for (; ; ) // Read all the backslashes - { - if (++bufpos == available) - AdjustBuffSize(); - - try { - if ((buffer[bufpos] = c = ReadByte()) != '\\') { - UpdateLineColumn(c); - // found a non-backslash char. - if ((c == 'u') && ((backSlashCnt & 1) == 1)) { - if (--bufpos < 0) - bufpos = bufsize - 1; - - break; - } - - backup(backSlashCnt); - return '\\'; - } - } catch (java.io.IOException e) { - if (backSlashCnt > 1) - backup(backSlashCnt); - - return '\\'; - } - - UpdateLineColumn(c); - backSlashCnt++; - } - - // Here, we have seen an odd number of backslash's followed by a 'u' - try { - while ((c = ReadByte()) == 'u') - ++column; - - buffer[bufpos] = c = (char) (hexval(c) << 12 | - hexval(ReadByte()) << 8 | - hexval(ReadByte()) << 4 | - hexval(ReadByte())); - - column += 4; - } catch (java.io.IOException e) { - throw new Error("Invalid escape character at line " + line + - " column " + column + "."); - } - - if (backSlashCnt == 1) - return c; - else { - backup(backSlashCnt - 1); - return '\\'; - } - } else { - UpdateLineColumn(c); - return (c); - } - } - - /** - * @return column index - * @see #getEndColumn - * @deprecated - */ - - public int getColumn() { - return bufcolumn[bufpos]; - } - - /** - * @return line type ??? - * @see #getEndLine - * @deprecated - */ - - public int getLine() { - return bufline[bufpos]; - } - - public int getEndColumn() { - return bufcolumn[bufpos]; - } - - public int getEndLine() { - return bufline[bufpos]; - } - - public int getBeginColumn() { - return bufcolumn[tokenBegin]; - } - - public int getBeginLine() { - return bufline[tokenBegin]; - } - - public void backup(int amount) { - - inBuf += amount; - if ((bufpos -= amount) < 0) - bufpos += bufsize; - } - - public JavaCharStream(java.io.Reader dstream, - int startline, int startcolumn, int buffersize) { - inputStream = dstream; - line = startline; - column = startcolumn - 1; - - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - nextCharBuf = new char[4096]; - } - - public JavaCharStream(java.io.Reader dstream, - int startline, int startcolumn) { - this(dstream, startline, startcolumn, 4096); - } - - public JavaCharStream(java.io.Reader dstream) { - this(dstream, 1, 1, 4096); - } - - public void ReInit(java.io.Reader dstream, - int startline, int startcolumn, int buffersize) { - inputStream = dstream; - line = startline; - column = startcolumn - 1; - - if (buffer == null || buffersize != buffer.length) { - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - nextCharBuf = new char[4096]; - } - prevCharIsLF = prevCharIsCR = false; - tokenBegin = inBuf = maxNextCharInd = 0; - nextCharInd = bufpos = -1; - } - - public void ReInit(java.io.Reader dstream, - int startline, int startcolumn) { - ReInit(dstream, startline, startcolumn, 4096); - } - - public void ReInit(java.io.Reader dstream) { - ReInit(dstream, 1, 1, 4096); - } - - public JavaCharStream(java.io.InputStream dstream, String encoding, int startline, - int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { - this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); - } - - public JavaCharStream(java.io.InputStream dstream, int startline, - int startcolumn, int buffersize) { - this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096); - } - - public JavaCharStream(java.io.InputStream dstream, String encoding, int startline, - int startcolumn) throws java.io.UnsupportedEncodingException { - this(dstream, encoding, startline, startcolumn, 4096); - } - - public JavaCharStream(java.io.InputStream dstream, int startline, - int startcolumn) { - this(dstream, startline, startcolumn, 4096); - } - - public JavaCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { - this(dstream, encoding, 1, 1, 4096); - } - - public JavaCharStream(java.io.InputStream dstream) { - this(dstream, 1, 1, 4096); - } - - public void ReInit(java.io.InputStream dstream, String encoding, int startline, - int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { - ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); - } - - public void ReInit(java.io.InputStream dstream, int startline, - int startcolumn, int buffersize) { - ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); - } - - public void ReInit(java.io.InputStream dstream, String encoding, int startline, - int startcolumn) throws java.io.UnsupportedEncodingException { - ReInit(dstream, encoding, startline, startcolumn, 4096); - } - - public void ReInit(java.io.InputStream dstream, int startline, - int startcolumn) { - ReInit(dstream, startline, startcolumn, 4096); - } - - public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { - ReInit(dstream, encoding, 1, 1, 4096); - } - - public void ReInit(java.io.InputStream dstream) { - ReInit(dstream, 1, 1, 4096); - } - - public String GetImage() { - if (bufpos >= tokenBegin) - return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); - else - return new String(buffer, tokenBegin, bufsize - tokenBegin) + - new String(buffer, 0, bufpos + 1); - } - - public char[] GetSuffix(int len) { - char[] ret = new char[len]; - - if ((bufpos + 1) >= len) - System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); - else { - System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, - len - bufpos - 1); - System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); - } - - return ret; - } - - public void Done() { - nextCharBuf = null; - buffer = null; - bufline = null; - bufcolumn = null; - } - - /** - * Method to adjust line and column numbers for the start of a token. - * - * @param newLine line number ? - * @param newCol column number ? - */ - public void adjustBeginLineColumn(int newLine, int newCol) { - int start = tokenBegin; - int len; - - if (bufpos >= tokenBegin) { - len = bufpos - tokenBegin + inBuf + 1; - } else { - len = bufsize - tokenBegin + bufpos + 1 + inBuf; - } - - int i = 0, j = 0, k; - int nextColDiff, columnDiff = 0; - - while (i < len && - bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) { - bufline[j] = newLine; - nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; - bufcolumn[j] = newCol + columnDiff; - columnDiff = nextColDiff; - i++; - } - - if (i < len) { - bufline[j] = newLine++; - bufcolumn[j] = newCol + columnDiff; - - while (i++ < len) { - if (bufline[j = start % bufsize] != bufline[++start % bufsize]) - bufline[j] = newLine++; - else - bufline[j] = newLine; - } - } - - line = bufline[j]; - column = bufcolumn[j]; - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParser.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParser.java deleted file mode 100644 index 02e65b5..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParser.java +++ /dev/null @@ -1,10117 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JJTree&JavaCC: Do not edit this line. JavaParser.java */ - -package jaxx.compiler.java.parser; - -import java.io.File; -import java.io.FileInputStream; - -/** - * Grammar to parse Java version 1.5 - * - * @author Sreenivasa Viswanadha - Simplified and enhanced for 1.5 - */ -public class JavaParser/*@bgen(jjtree)*/ implements JavaParserTreeConstants, JavaParserConstants {/*@bgen(jjtree)*/ - - protected JJTJavaParserState jjtree = new JJTJavaParserState(); - - /** Class to hold modifiers. */ - static public final class ModifierSet { - /* Definitions of the bits in the modifiers field. */ - public static final int PUBLIC = 0x0001; - - public static final int PROTECTED = 0x0002; - - public static final int PRIVATE = 0x0004; - - public static final int ABSTRACT = 0x0008; - - public static final int STATIC = 0x0010; - - public static final int FINAL = 0x0020; - - public static final int SYNCHRONIZED = 0x0040; - - public static final int NATIVE = 0x0080; - - public static final int TRANSIENT = 0x0100; - - public static final int VOLATILE = 0x0200; - - public static final int STRICTFP = 0x1000; - - /** - * A set of accessors that indicate whether the specified modifier - * is in the set. - */ - - public boolean isPublic(int modifiers) { - return (modifiers & PUBLIC) != 0; - } - - public boolean isProtected(int modifiers) { - return (modifiers & PROTECTED) != 0; - } - - public boolean isPrivate(int modifiers) { - return (modifiers & PRIVATE) != 0; - } - - public boolean isStatic(int modifiers) { - return (modifiers & STATIC) != 0; - } - - public boolean isAbstract(int modifiers) { - return (modifiers & ABSTRACT) != 0; - } - - public boolean isFinal(int modifiers) { - return (modifiers & FINAL) != 0; - } - - public boolean isNative(int modifiers) { - return (modifiers & NATIVE) != 0; - } - - public boolean isStrictfp(int modifiers) { - return (modifiers & STRICTFP) != 0; - } - - public boolean isSynchronized(int modifiers) { - return (modifiers & SYNCHRONIZED) != 0; - } - - public boolean isTransient(int modifiers) { - return (modifiers & TRANSIENT) != 0; - } - - public boolean isVolatile(int modifiers) { - return (modifiers & VOLATILE) != 0; - } - - /** Removes the given modifier. */ - static int removeModifier(int modifiers, int mod) { - return modifiers & ~mod; - } - } - - public JavaParser(String fileName) { - this(fileName, false); - } - - public JavaParser(String fileName, boolean parseMethodBody) { - this(System.in, parseMethodBody); - try { - ReInit(new FileInputStream(new File(fileName))); - } catch (Exception e) { - e.printStackTrace(); - } - } - - void jjtreeOpenNodeScope(Node n) { - ((SimpleNode) n).firstToken = getToken(1); - } - - void jjtreeCloseNodeScope(Node n) { - ((SimpleNode) n).lastToken = getToken(0); - } - - public SimpleNode popNode() { - if (jjtree.nodeArity() > 0) // number of child nodes - return (SimpleNode) jjtree.popNode(); - else - return null; - } - - public static void main(String args[]) { - JavaParser parser; - if (args.length == 0) { - System.out.println("Java Parser Version 1.1: Reading from standard input . . ."); - parser = new JavaParser(System.in, true); - } else if (args.length == 1) { - System.out.println("Java Parser Version 1.1: Reading from file " + args[0] + " . . ."); - try { - parser = new JavaParser(new java.io.FileInputStream(args[0]), true); - } catch (java.io.FileNotFoundException e) { - System.out.println("Java Parser Version 1.1: File " + args[0] + " not found."); - return; - } - } else { - System.out.println("Java Parser Version 1.1: Usage is one of:"); - System.out.println(" java JavaParser < inputfile"); - System.out.println("OR"); - System.out.println(" java JavaParser inputfile"); - return; - } - try { - parser.CompilationUnit(); - System.out.println("Java Parser Version 1.1: Java program parsed successfully."); - } catch (ParseException e) { - System.out.println(e.getMessage()); - System.out.println("Java Parser Version 1.1: Encountered errors during parse."); - } - } - - final public boolean Line() throws ParseException { - /*@bgen(jjtree) Line */ - SimpleNode jjtn000 = new SimpleNode(JJTLINE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - int modifiers; - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case 0: - jj_consume_token(0); - jjtree.closeNodeScope(jjtn000, true); - jjtc000 = false; - jjtreeCloseNodeScope(jjtn000); - { - if (true) return true; - } - break; - default: - if (jj_2_1(2147483647)) { - BlockStatement(); - jjtree.closeNodeScope(jjtn000, true); - jjtc000 = false; - jjtreeCloseNodeScope(jjtn000); - { - if (true) return false; - } - } else if (jj_2_2(2147483647)) { - ClassOrInterfaceBodyDeclaration(false); - jjtree.closeNodeScope(jjtn000, true); - jjtc000 = false; - jjtreeCloseNodeScope(jjtn000); - { - if (true) return false; - } - } else if (jj_2_3(2147483647)) { - ClassOrInterfaceBodyDeclaration(false); - jjtree.closeNodeScope(jjtn000, true); - jjtc000 = false; - jjtreeCloseNodeScope(jjtn000); - { - if (true) return false; - } - } else if (jj_2_4(2147483647)) { - Expression(); - jjtree.closeNodeScope(jjtn000, true); - jjtc000 = false; - jjtreeCloseNodeScope(jjtn000); - { - if (true) return false; - } - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IMPORT: - ImportDeclaration(); - jjtree.closeNodeScope(jjtn000, true); - jjtc000 = false; - jjtreeCloseNodeScope(jjtn000); - { - if (true) return false; - } - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - throw new Error("Missing return statement in function"); - } - - /** - * ************************************** - * THE JAVA LANGUAGE GRAMMAR STARTS HERE * - * *************************************** - */ - -/* - * Program structuring syntax follows. - */ - final public void CompilationUnit() throws ParseException { - /*@bgen(jjtree) CompilationUnit */ - SimpleNode jjtn000 = new SimpleNode(JJTCOMPILATIONUNIT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (jj_2_5(2147483647)) { - PackageDeclaration(); - } else { - ; - } - label_1: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IMPORT: - ; - break; - default: - break label_1; - } - ImportDeclaration(); - } - label_2: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ABSTRACT: - case CLASS: - case ENUM: - case FINAL: - case INTERFACE: - case NATIVE: - case PRIVATE: - case PROTECTED: - case PUBLIC: - case STATIC: - case STRICTFP: - case SYNCHRONIZED: - case TRANSIENT: - case VOLATILE: - case SEMICOLON: - case AT: - ; - break; - default: - break label_2; - } - TypeDeclaration(); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case 123: - jj_consume_token(123); - break; - default: - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case STUFF_TO_IGNORE: - jj_consume_token(STUFF_TO_IGNORE); - break; - default: - ; - } - jj_consume_token(0); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void PackageDeclaration() throws ParseException { - /*@bgen(jjtree) PackageDeclaration */ - SimpleNode jjtn000 = new SimpleNode(JJTPACKAGEDECLARATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - Modifiers(); - jj_consume_token(PACKAGE); - Name(); - jj_consume_token(SEMICOLON); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ImportDeclaration() throws ParseException { - /*@bgen(jjtree) ImportDeclaration */ - SimpleNode jjtn000 = new SimpleNode(JJTIMPORTDECLARATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(IMPORT); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case STATIC: - jj_consume_token(STATIC); - break; - default: - ; - } - Name(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case DOT: - jj_consume_token(DOT); - jj_consume_token(STAR); - break; - default: - ; - } - jj_consume_token(SEMICOLON); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - /* - * Modifiers. We match all modifiers in a single rule to reduce the chances of - * syntax errors for simple modifier mistakes. It will also enable us to give - * better error messages. - */ - final public int Modifiers() throws ParseException { - /*@bgen(jjtree) Modifiers */ - SimpleNode jjtn000 = new SimpleNode(JJTMODIFIERS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - int modifiers = 0; - try { - label_3: - while (true) { - if (jj_2_6(2)) { - ; - } else { - break label_3; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PUBLIC: - jj_consume_token(PUBLIC); - modifiers |= ModifierSet.PUBLIC; - break; - case STATIC: - jj_consume_token(STATIC); - modifiers |= ModifierSet.STATIC; - break; - case PROTECTED: - jj_consume_token(PROTECTED); - modifiers |= ModifierSet.PROTECTED; - break; - case PRIVATE: - jj_consume_token(PRIVATE); - modifiers |= ModifierSet.PRIVATE; - break; - case FINAL: - jj_consume_token(FINAL); - modifiers |= ModifierSet.FINAL; - break; - case ABSTRACT: - jj_consume_token(ABSTRACT); - modifiers |= ModifierSet.ABSTRACT; - break; - case SYNCHRONIZED: - jj_consume_token(SYNCHRONIZED); - modifiers |= ModifierSet.SYNCHRONIZED; - break; - case NATIVE: - jj_consume_token(NATIVE); - modifiers |= ModifierSet.NATIVE; - break; - case TRANSIENT: - jj_consume_token(TRANSIENT); - modifiers |= ModifierSet.TRANSIENT; - break; - case VOLATILE: - jj_consume_token(VOLATILE); - modifiers |= ModifierSet.VOLATILE; - break; - case STRICTFP: - jj_consume_token(STRICTFP); - modifiers |= ModifierSet.STRICTFP; - break; - case AT: - Annotation(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - jjtree.closeNodeScope(jjtn000, true); - jjtc000 = false; - jjtreeCloseNodeScope(jjtn000); - { - if (true) return modifiers; - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - throw new Error("Missing return statement in function"); - } - - /* - * Declaration syntax follows. - */ - final public void TypeDeclaration() throws ParseException { - /*@bgen(jjtree) TypeDeclaration */ - SimpleNode jjtn000 = new SimpleNode(JJTTYPEDECLARATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - int modifiers; - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SEMICOLON: - jj_consume_token(SEMICOLON); - break; - case ABSTRACT: - case CLASS: - case ENUM: - case FINAL: - case INTERFACE: - case NATIVE: - case PRIVATE: - case PROTECTED: - case PUBLIC: - case STATIC: - case STRICTFP: - case SYNCHRONIZED: - case TRANSIENT: - case VOLATILE: - case AT: - modifiers = Modifiers(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case CLASS: - case INTERFACE: - ClassOrInterfaceDeclaration(modifiers); - break; - case ENUM: - EnumDeclaration(modifiers); - break; - case AT: - AnnotationTypeDeclaration(modifiers); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ClassOrInterfaceDeclaration(int modifiers) throws ParseException { - /*@bgen(jjtree) ClassOrInterfaceDeclaration */ - SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACEDECLARATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - boolean isInterface = false; - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case CLASS: - jj_consume_token(CLASS); - break; - case INTERFACE: - jj_consume_token(INTERFACE); - isInterface = true; - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - jj_consume_token(IDENTIFIER); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LT: - TypeParameters(); - break; - default: - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case EXTENDS: - ExtendsList(isInterface); - break; - default: - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IMPLEMENTS: - ImplementsList(isInterface); - break; - default: - ; - } - ClassOrInterfaceBody(isInterface); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ExtendsList(boolean isInterface) throws ParseException { - /*@bgen(jjtree) ExtendsList */ - SimpleNode jjtn000 = new SimpleNode(JJTEXTENDSLIST); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - boolean extendsMoreThanOne = false; - try { - jj_consume_token(EXTENDS); - ClassOrInterfaceType(); - label_4: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - break label_4; - } - jj_consume_token(COMMA); - ClassOrInterfaceType(); - extendsMoreThanOne = true; - } - jjtree.closeNodeScope(jjtn000, true); - jjtc000 = false; - jjtreeCloseNodeScope(jjtn000); - if (extendsMoreThanOne && !isInterface) { - if (true) - throw new ParseException("A class cannot extend more than one other class"); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ImplementsList(boolean isInterface) throws ParseException { - /*@bgen(jjtree) ImplementsList */ - SimpleNode jjtn000 = new SimpleNode(JJTIMPLEMENTSLIST); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(IMPLEMENTS); - ClassOrInterfaceType(); - label_5: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - break label_5; - } - jj_consume_token(COMMA); - ClassOrInterfaceType(); - } - jjtree.closeNodeScope(jjtn000, true); - jjtc000 = false; - jjtreeCloseNodeScope(jjtn000); - if (isInterface) { - if (true) - throw new ParseException("An interface cannot implement other interfaces"); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void EnumDeclaration(int modifiers) throws ParseException { - /*@bgen(jjtree) EnumDeclaration */ - SimpleNode jjtn000 = new SimpleNode(JJTENUMDECLARATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(ENUM); - jj_consume_token(IDENTIFIER); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IMPLEMENTS: - ImplementsList(false); - break; - default: - ; - } - EnumBody(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void EnumBody() throws ParseException { - /*@bgen(jjtree) EnumBody */ - SimpleNode jjtn000 = new SimpleNode(JJTENUMBODY); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(LBRACE); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ABSTRACT: - case FINAL: - case NATIVE: - case PRIVATE: - case PROTECTED: - case PUBLIC: - case STATIC: - case STRICTFP: - case SYNCHRONIZED: - case TRANSIENT: - case VOLATILE: - case IDENTIFIER: - case AT: - EnumConstant(); - label_6: - while (true) { - if (jj_2_7(2)) { - ; - } else { - break label_6; - } - jj_consume_token(COMMA); - EnumConstant(); - } - break; - default: - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - jj_consume_token(COMMA); - break; - default: - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SEMICOLON: - jj_consume_token(SEMICOLON); - label_7: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ABSTRACT: - case BOOLEAN: - case BYTE: - case CHAR: - case CLASS: - case DOUBLE: - case ENUM: - case FINAL: - case FLOAT: - case INT: - case INTERFACE: - case LONG: - case NATIVE: - case PRIVATE: - case PROTECTED: - case PUBLIC: - case SHORT: - case STATIC: - case STRICTFP: - case SYNCHRONIZED: - case TRANSIENT: - case VOID: - case VOLATILE: - case IDENTIFIER: - case LBRACE: - case SEMICOLON: - case AT: - case LT: - ; - break; - default: - break label_7; - } - ClassOrInterfaceBodyDeclaration(false); - } - break; - default: - ; - } - jj_consume_token(RBRACE); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void EnumConstant() throws ParseException { - /*@bgen(jjtree) EnumConstant */ - SimpleNode jjtn000 = new SimpleNode(JJTENUMCONSTANT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - Modifiers(); - jj_consume_token(IDENTIFIER); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LPAREN: - Arguments(); - break; - default: - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACE: - ClassOrInterfaceBody(false); - break; - default: - ; - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void TypeParameters() throws ParseException { - /*@bgen(jjtree) TypeParameters */ - SimpleNode jjtn000 = new SimpleNode(JJTTYPEPARAMETERS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(LT); - TypeParameter(); - label_8: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - break label_8; - } - jj_consume_token(COMMA); - TypeParameter(); - } - jj_consume_token(GT); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void TypeParameter() throws ParseException { - /*@bgen(jjtree) TypeParameter */ - SimpleNode jjtn000 = new SimpleNode(JJTTYPEPARAMETER); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(IDENTIFIER); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case EXTENDS: - TypeBound(); - break; - default: - ; - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void TypeBound() throws ParseException { - /*@bgen(jjtree) TypeBound */ - SimpleNode jjtn000 = new SimpleNode(JJTTYPEBOUND); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(EXTENDS); - ClassOrInterfaceType(); - label_9: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BIT_AND: - ; - break; - default: - break label_9; - } - jj_consume_token(BIT_AND); - ClassOrInterfaceType(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ClassOrInterfaceBody(boolean isInterface) throws ParseException { - /*@bgen(jjtree) ClassOrInterfaceBody */ - SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACEBODY); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(LBRACE); - label_10: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ABSTRACT: - case BOOLEAN: - case BYTE: - case CHAR: - case CLASS: - case DOUBLE: - case ENUM: - case FINAL: - case FLOAT: - case INT: - case INTERFACE: - case LONG: - case NATIVE: - case PRIVATE: - case PROTECTED: - case PUBLIC: - case SHORT: - case STATIC: - case STRICTFP: - case SYNCHRONIZED: - case TRANSIENT: - case VOID: - case VOLATILE: - case IDENTIFIER: - case LBRACE: - case SEMICOLON: - case AT: - case LT: - ; - break; - default: - break label_10; - } - ClassOrInterfaceBodyDeclaration(isInterface); - } - jj_consume_token(RBRACE); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ClassOrInterfaceBodyDeclaration(boolean isInterface) throws ParseException { - /*@bgen(jjtree) ClassOrInterfaceBodyDeclaration */ - SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACEBODYDECLARATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - boolean isNestedInterface = false; - int modifiers; - try { - if (jj_2_10(2)) { - Initializer(); - jjtree.closeNodeScope(jjtn000, true); - jjtc000 = false; - jjtreeCloseNodeScope(jjtn000); - if (isInterface) { - if (true) - throw new ParseException("An interface cannot have initializers"); - } - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ABSTRACT: - case BOOLEAN: - case BYTE: - case CHAR: - case CLASS: - case DOUBLE: - case ENUM: - case FINAL: - case FLOAT: - case INT: - case INTERFACE: - case LONG: - case NATIVE: - case PRIVATE: - case PROTECTED: - case PUBLIC: - case SHORT: - case STATIC: - case STRICTFP: - case SYNCHRONIZED: - case TRANSIENT: - case VOID: - case VOLATILE: - case IDENTIFIER: - case AT: - case LT: - modifiers = Modifiers(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case CLASS: - case INTERFACE: - ClassOrInterfaceDeclaration(modifiers); - break; - case ENUM: - EnumDeclaration(modifiers); - break; - default: - if (jj_2_8(2147483647)) { - ConstructorDeclaration(); - } else if (jj_2_9(2147483647)) { - FieldDeclaration(modifiers); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FLOAT: - case INT: - case LONG: - case SHORT: - case VOID: - case IDENTIFIER: - case LT: - MethodDeclaration(modifiers); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } - break; - case SEMICOLON: - jj_consume_token(SEMICOLON); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void FieldDeclaration(int modifiers) throws ParseException { - /*@bgen(jjtree) FieldDeclaration */ - SimpleNode jjtn000 = new SimpleNode(JJTFIELDDECLARATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - Type(); - VariableDeclarator(); - label_11: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - break label_11; - } - jj_consume_token(COMMA); - VariableDeclarator(); - } - jj_consume_token(SEMICOLON); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void VariableDeclarator() throws ParseException { - /*@bgen(jjtree) VariableDeclarator */ - SimpleNode jjtn000 = new SimpleNode(JJTVARIABLEDECLARATOR); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - VariableDeclaratorId(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ASSIGN: - jj_consume_token(ASSIGN); - VariableInitializer(); - break; - default: - ; - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void VariableDeclaratorId() throws ParseException { - /*@bgen(jjtree) VariableDeclaratorId */ - SimpleNode jjtn000 = new SimpleNode(JJTVARIABLEDECLARATORID); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(IDENTIFIER); - label_12: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACKET: - ; - break; - default: - break label_12; - } - jj_consume_token(LBRACKET); - jj_consume_token(RBRACKET); - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void VariableInitializer() throws ParseException { - /*@bgen(jjtree) VariableInitializer */ - SimpleNode jjtn000 = new SimpleNode(JJTVARIABLEINITIALIZER); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACE: - ArrayInitializer(); - break; - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FALSE: - case FLOAT: - case INT: - case LONG: - case NEW: - case NULL: - case SHORT: - case SUPER: - case THIS: - case TRUE: - case VOID: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case BANG: - case TILDE: - case INCR: - case DECR: - case PLUS: - case MINUS: - Expression(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ArrayInitializer() throws ParseException { - /*@bgen(jjtree) ArrayInitializer */ - SimpleNode jjtn000 = new SimpleNode(JJTARRAYINITIALIZER); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(LBRACE); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FALSE: - case FLOAT: - case INT: - case LONG: - case NEW: - case NULL: - case SHORT: - case SUPER: - case THIS: - case TRUE: - case VOID: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case LBRACE: - case BANG: - case TILDE: - case INCR: - case DECR: - case PLUS: - case MINUS: - VariableInitializer(); - label_13: - while (true) { - if (jj_2_11(2)) { - ; - } else { - break label_13; - } - jj_consume_token(COMMA); - VariableInitializer(); - } - break; - default: - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - jj_consume_token(COMMA); - break; - default: - ; - } - jj_consume_token(RBRACE); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void MethodDeclaration(int modifiers) throws ParseException { - /*@bgen(jjtree) MethodDeclaration */ - SimpleNode jjtn000 = new SimpleNode(JJTMETHODDECLARATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LT: - TypeParameters(); - break; - default: - ; - } - ResultType(); - MethodDeclarator(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case THROWS: - jj_consume_token(THROWS); - NameList(); - break; - default: - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACE: - - if (parseMethodBody) { - - Block(); - - } else { - - // We do not want to parse inside a method implementation, we just need to get method prototypes - // See https://forge.nuiton.org/issues/3667 - - int nbBlocks = 0; - do { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACE: - nbBlocks++; - break; - case RBRACE: - nbBlocks--; - break; - } - jj_consume_token(jj_ntk); - } while (nbBlocks > 0); - - } - break; - case SEMICOLON: - jj_consume_token(SEMICOLON); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void MethodDeclarator() throws ParseException { - /*@bgen(jjtree) MethodDeclarator */ - SimpleNode jjtn000 = new SimpleNode(JJTMETHODDECLARATOR); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(IDENTIFIER); - FormalParameters(); - label_14: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACKET: - ; - break; - default: - break label_14; - } - jj_consume_token(LBRACKET); - jj_consume_token(RBRACKET); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void FormalParameters() throws ParseException { - /*@bgen(jjtree) FormalParameters */ - SimpleNode jjtn000 = new SimpleNode(JJTFORMALPARAMETERS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(LPAREN); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ABSTRACT: - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FINAL: - case FLOAT: - case INT: - case LONG: - case NATIVE: - case PRIVATE: - case PROTECTED: - case PUBLIC: - case SHORT: - case STATIC: - case STRICTFP: - case SYNCHRONIZED: - case TRANSIENT: - case VOLATILE: - case IDENTIFIER: - case AT: - FormalParameter(); - label_15: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - break label_15; - } - jj_consume_token(COMMA); - FormalParameter(); - } - break; - default: - ; - } - jj_consume_token(RPAREN); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void FormalParameter() throws ParseException { - /*@bgen(jjtree) FormalParameter */ - SimpleNode jjtn000 = new SimpleNode(JJTFORMALPARAMETER); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - Modifiers(); - Type(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ELLIPSIS: - jj_consume_token(ELLIPSIS); - break; - default: - ; - } - VariableDeclaratorId(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ConstructorDeclaration() throws ParseException { - /*@bgen(jjtree) ConstructorDeclaration */ - SimpleNode jjtn000 = new SimpleNode(JJTCONSTRUCTORDECLARATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LT: - TypeParameters(); - break; - default: - ; - } - jj_consume_token(IDENTIFIER); - FormalParameters(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case THROWS: - jj_consume_token(THROWS); - NameList(); - break; - default: - ; - } - jj_consume_token(LBRACE); - if (jj_2_12(2147483647)) { - ExplicitConstructorInvocation(); - } else { - ; - } - - // >>> -------------------------- Only keep one node with text for constructor body - - StringBuilder constructoRawBody = new StringBuilder(); - // We do not care about what is inside the constructor, let's allow java 8 lambdas! - int lbraceNb = 1;// 1 left brace consumed - // while all the left braces have not been closed - SimpleNode jjtBody = new SimpleNode(JJTSTATEMENT); - jjtree.openNodeScope(jjtBody); - jjtreeOpenNodeScope(jjtBody); - - while (lbraceNb > 0) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACE: // new left brace opened - lbraceNb++; - break; - case RBRACE: // left brace closed - lbraceNb--; - break; - default: - break; - } - Token token = jj_consume_token(jj_ntk); - if (lbraceNb > 0) { - if (token.specialToken !=null) { - constructoRawBody.append(token.specialToken); - } - constructoRawBody.append(token.image); - } - } - Token bodyToken = new Token(); - bodyToken.image = constructoRawBody.toString(); - jjtBody.firstToken = bodyToken; - - jjtree.closeNodeScope(jjtBody, true); - jjtreeCloseNodeScope(jjtBody); - - // <<< -------------------------- Only keep one node with text for constructor body - - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ExplicitConstructorInvocation() throws ParseException { - /*@bgen(jjtree) ExplicitConstructorInvocation */ - SimpleNode jjtn000 = new SimpleNode(JJTEXPLICITCONSTRUCTORINVOCATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - label_17: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENTIFIER: - ; - break; - default: - break label_17; - } - jj_consume_token(IDENTIFIER); - jj_consume_token(DOT); - } - if (jj_2_13(2)) { - jj_consume_token(THIS); - jj_consume_token(DOT); - } else { - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LT: - TypeArguments(); - break; - default: - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case THIS: - jj_consume_token(THIS); - break; - case SUPER: - jj_consume_token(SUPER); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - Arguments(); - jj_consume_token(SEMICOLON); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void Initializer() throws ParseException { - /*@bgen(jjtree) Initializer */ - SimpleNode jjtn000 = new SimpleNode(JJTINITIALIZER); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case STATIC: - jj_consume_token(STATIC); - break; - default: - ; - } - Block(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - /* - * Type, name and expression syntax follows. - */ - final public void Type() throws ParseException { - /*@bgen(jjtree) Type */ - SimpleNode jjtn000 = new SimpleNode(JJTTYPE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (jj_2_14(2)) { - ReferenceType(); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FLOAT: - case INT: - case LONG: - case SHORT: - PrimitiveType(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ReferenceType() throws ParseException { - /*@bgen(jjtree) ReferenceType */ - SimpleNode jjtn000 = new SimpleNode(JJTREFERENCETYPE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FLOAT: - case INT: - case LONG: - case SHORT: - PrimitiveType(); - label_18: - while (true) { - jj_consume_token(LBRACKET); - jj_consume_token(RBRACKET); - if (jj_2_15(2)) { - ; - } else { - break label_18; - } - } - break; - case IDENTIFIER: - ClassOrInterfaceType(); - label_19: - while (true) { - if (jj_2_16(2)) { - ; - } else { - break label_19; - } - jj_consume_token(LBRACKET); - jj_consume_token(RBRACKET); - } - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ClassOrInterfaceType() throws ParseException { - /*@bgen(jjtree) ClassOrInterfaceType */ - SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACETYPE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(IDENTIFIER); - if (jj_2_17(2)) { - TypeArguments(); - } else { - ; - } - label_20: - while (true) { - if (jj_2_18(2)) { - ; - } else { - break label_20; - } - jj_consume_token(DOT); - jj_consume_token(IDENTIFIER); - if (jj_2_19(2)) { - TypeArguments(); - } else { - ; - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void TypeArguments() throws ParseException { - /*@bgen(jjtree) TypeArguments */ - SimpleNode jjtn000 = new SimpleNode(JJTTYPEARGUMENTS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(LT); - TypeArgument(); - label_21: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - break label_21; - } - jj_consume_token(COMMA); - TypeArgument(); - } - jj_consume_token(GT); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void TypeArgumentsForAllocation() throws ParseException { - /*@bgen(jjtree) TypeArguments */ - SimpleNode jjtn000 = new SimpleNode(JJTTYPEARGUMENTS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(LT); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case GT: - // Diamond expression (jdk7) - jj_consume_token(GT); - return; - } - TypeArgument(); - label_21: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - break label_21; - } - jj_consume_token(COMMA); - TypeArgument(); - } - jj_consume_token(GT); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void TypeArgument() throws ParseException { - /*@bgen(jjtree) TypeArgument */ - SimpleNode jjtn000 = new SimpleNode(JJTTYPEARGUMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FLOAT: - case INT: - case LONG: - case SHORT: - case IDENTIFIER: - ReferenceType(); - break; - case HOOK: - jj_consume_token(HOOK); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case EXTENDS: - case SUPER: - WildcardBounds(); - break; - default: - ; - } - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void WildcardBounds() throws ParseException { - /*@bgen(jjtree) WildcardBounds */ - SimpleNode jjtn000 = new SimpleNode(JJTWILDCARDBOUNDS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case EXTENDS: - jj_consume_token(EXTENDS); - ReferenceType(); - break; - case SUPER: - jj_consume_token(SUPER); - ReferenceType(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void PrimitiveType() throws ParseException { - /*@bgen(jjtree) PrimitiveType */ - SimpleNode jjtn000 = new SimpleNode(JJTPRIMITIVETYPE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BOOLEAN: - jj_consume_token(BOOLEAN); - break; - case CHAR: - jj_consume_token(CHAR); - break; - case BYTE: - jj_consume_token(BYTE); - break; - case SHORT: - jj_consume_token(SHORT); - break; - case INT: - jj_consume_token(INT); - break; - case LONG: - jj_consume_token(LONG); - break; - case FLOAT: - jj_consume_token(FLOAT); - break; - case DOUBLE: - jj_consume_token(DOUBLE); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ResultType() throws ParseException { - /*@bgen(jjtree) ResultType */ - SimpleNode jjtn000 = new SimpleNode(JJTRESULTTYPE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case VOID: - jj_consume_token(VOID); - break; - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FLOAT: - case INT: - case LONG: - case SHORT: - case IDENTIFIER: - Type(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void Name() throws ParseException { - /*@bgen(jjtree) Name */ - SimpleNode jjtn000 = new SimpleNode(JJTNAME); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(IDENTIFIER); - label_22: - while (true) { - if (jj_2_20(2)) { - ; - } else { - break label_22; - } - jj_consume_token(DOT); - jj_consume_token(IDENTIFIER); - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void NameList() throws ParseException { - /*@bgen(jjtree) NameList */ - SimpleNode jjtn000 = new SimpleNode(JJTNAMELIST); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - Name(); - label_23: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - break label_23; - } - jj_consume_token(COMMA); - Name(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - /* - * Expression syntax follows. - */ - final public void Expression() throws ParseException { - /*@bgen(jjtree) Expression */ - SimpleNode jjtn000 = new SimpleNode(JJTEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - ConditionalExpression(); - if (jj_2_21(2)) { - AssignmentOperator(); - Expression(); - } else { - ; - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void AssignmentOperator() throws ParseException { - /*@bgen(jjtree) AssignmentOperator */ - SimpleNode jjtn000 = new SimpleNode(JJTASSIGNMENTOPERATOR); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ASSIGN: - jj_consume_token(ASSIGN); - break; - case STARASSIGN: - jj_consume_token(STARASSIGN); - break; - case SLASHASSIGN: - jj_consume_token(SLASHASSIGN); - break; - case REMASSIGN: - jj_consume_token(REMASSIGN); - break; - case PLUSASSIGN: - jj_consume_token(PLUSASSIGN); - break; - case MINUSASSIGN: - jj_consume_token(MINUSASSIGN); - break; - case LSHIFTASSIGN: - jj_consume_token(LSHIFTASSIGN); - break; - case RSIGNEDSHIFTASSIGN: - jj_consume_token(RSIGNEDSHIFTASSIGN); - break; - case RUNSIGNEDSHIFTASSIGN: - jj_consume_token(RUNSIGNEDSHIFTASSIGN); - break; - case ANDASSIGN: - jj_consume_token(ANDASSIGN); - break; - case XORASSIGN: - jj_consume_token(XORASSIGN); - break; - case ORASSIGN: - jj_consume_token(ORASSIGN); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void AssignmentExpression() throws ParseException { - /*@bgen(jjtree) AssignmentExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTASSIGNMENTEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - PrimaryExpression(); - AssignmentOperator(); - Expression(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ConditionalExpression() throws ParseException { - /*@bgen(jjtree) ConditionalExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTCONDITIONALEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - ConditionalOrExpression(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case HOOK: - jj_consume_token(HOOK); - Expression(); - jj_consume_token(COLON); - Expression(); - break; - default: - ; - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ConditionalOrExpression() throws ParseException { - /*@bgen(jjtree) ConditionalOrExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTCONDITIONALOREXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - ConditionalAndExpression(); - label_24: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SC_OR: - ; - break; - default: - break label_24; - } - jj_consume_token(SC_OR); - ConditionalAndExpression(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ConditionalAndExpression() throws ParseException { - /*@bgen(jjtree) ConditionalAndExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTCONDITIONALANDEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - InclusiveOrExpression(); - label_25: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SC_AND: - ; - break; - default: - break label_25; - } - jj_consume_token(SC_AND); - InclusiveOrExpression(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void InclusiveOrExpression() throws ParseException { - /*@bgen(jjtree) InclusiveOrExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTINCLUSIVEOREXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - ExclusiveOrExpression(); - label_26: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BIT_OR: - ; - break; - default: - break label_26; - } - jj_consume_token(BIT_OR); - ExclusiveOrExpression(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ExclusiveOrExpression() throws ParseException { - /*@bgen(jjtree) ExclusiveOrExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTEXCLUSIVEOREXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - AndExpression(); - label_27: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case XOR: - ; - break; - default: - break label_27; - } - jj_consume_token(XOR); - AndExpression(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void AndExpression() throws ParseException { - /*@bgen(jjtree) AndExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTANDEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - EqualityExpression(); - label_28: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BIT_AND: - ; - break; - default: - break label_28; - } - jj_consume_token(BIT_AND); - EqualityExpression(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void EqualityExpression() throws ParseException { - /*@bgen(jjtree) EqualityExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTEQUALITYEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - InstanceOfExpression(); - label_29: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case EQ: - case NE: - ; - break; - default: - break label_29; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case EQ: - jj_consume_token(EQ); - break; - case NE: - jj_consume_token(NE); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - InstanceOfExpression(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void InstanceOfExpression() throws ParseException { - /*@bgen(jjtree) InstanceOfExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTINSTANCEOFEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - RelationalExpression(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INSTANCEOF: - jj_consume_token(INSTANCEOF); - Type(); - break; - default: - ; - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void RelationalExpression() throws ParseException { - /*@bgen(jjtree) RelationalExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTRELATIONALEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - ShiftExpression(); - label_30: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LT: - case LE: - case GE: - case GT: - ; - break; - default: - break label_30; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LT: - jj_consume_token(LT); - break; - case GT: - jj_consume_token(GT); - break; - case LE: - jj_consume_token(LE); - break; - case GE: - jj_consume_token(GE); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - ShiftExpression(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ShiftExpression() throws ParseException { - /*@bgen(jjtree) ShiftExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTSHIFTEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - AdditiveExpression(); - label_31: - while (true) { - if (jj_2_22(1)) { - ; - } else { - break label_31; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LSHIFT: - jj_consume_token(LSHIFT); - break; - default: - if (jj_2_23(1)) { - RSIGNEDSHIFT(); - } else if (jj_2_24(1)) { - RUNSIGNEDSHIFT(); - } else { - jj_consume_token(-1); - throw new ParseException(); - } - } - AdditiveExpression(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void AdditiveExpression() throws ParseException { - /*@bgen(jjtree) AdditiveExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTADDITIVEEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - MultiplicativeExpression(); - label_32: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case MINUS: - ; - break; - default: - break label_32; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - jj_consume_token(PLUS); - break; - case MINUS: - jj_consume_token(MINUS); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - MultiplicativeExpression(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void MultiplicativeExpression() throws ParseException { - /*@bgen(jjtree) MultiplicativeExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTMULTIPLICATIVEEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - UnaryExpression(); - label_33: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case STAR: - case SLASH: - case REM: - ; - break; - default: - break label_33; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case STAR: - jj_consume_token(STAR); - break; - case SLASH: - jj_consume_token(SLASH); - break; - case REM: - jj_consume_token(REM); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - UnaryExpression(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void UnaryExpression() throws ParseException { - /*@bgen(jjtree) UnaryExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTUNARYEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - case MINUS: - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case PLUS: - jj_consume_token(PLUS); - break; - case MINUS: - jj_consume_token(MINUS); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - UnaryExpression(); - break; - case INCR: - PreIncrementExpression(); - break; - case DECR: - PreDecrementExpression(); - break; - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FALSE: - case FLOAT: - case INT: - case LONG: - case NEW: - case NULL: - case SHORT: - case SUPER: - case THIS: - case TRUE: - case VOID: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case BANG: - case TILDE: - UnaryExpressionNotPlusMinus(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void PreIncrementExpression() throws ParseException { - /*@bgen(jjtree) PreIncrementExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTPREINCREMENTEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(INCR); - PrimaryExpression(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void PreDecrementExpression() throws ParseException { - /*@bgen(jjtree) PreDecrementExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTPREDECREMENTEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(DECR); - PrimaryExpression(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void UnaryExpressionNotPlusMinus() throws ParseException { - /*@bgen(jjtree) UnaryExpressionNotPlusMinus */ - SimpleNode jjtn000 = new SimpleNode(JJTUNARYEXPRESSIONNOTPLUSMINUS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BANG: - case TILDE: - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case TILDE: - jj_consume_token(TILDE); - break; - case BANG: - jj_consume_token(BANG); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - UnaryExpression(); - break; - default: - if (jj_2_25(2147483647)) { - CastExpression(); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FALSE: - case FLOAT: - case INT: - case LONG: - case NEW: - case NULL: - case SHORT: - case SUPER: - case THIS: - case TRUE: - case VOID: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - PostfixExpression(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - -// This production is to determine lookahead only. The LOOKAHEAD specifications -// below are not used, but they are there just to indicate that we know about - - // this. - final public void CastLookahead() throws ParseException { - /*@bgen(jjtree) CastLookahead */ - SimpleNode jjtn000 = new SimpleNode(JJTCASTLOOKAHEAD); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (jj_2_26(2)) { - jj_consume_token(LPAREN); - PrimitiveType(); - } else if (jj_2_27(2147483647)) { - jj_consume_token(LPAREN); - Type(); - jj_consume_token(LBRACKET); - jj_consume_token(RBRACKET); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LPAREN: - jj_consume_token(LPAREN); - Type(); - jj_consume_token(RPAREN); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case TILDE: - jj_consume_token(TILDE); - break; - case BANG: - jj_consume_token(BANG); - break; - case LPAREN: - jj_consume_token(LPAREN); - break; - case IDENTIFIER: - jj_consume_token(IDENTIFIER); - break; - case THIS: - jj_consume_token(THIS); - break; - case SUPER: - jj_consume_token(SUPER); - break; - case NEW: - jj_consume_token(NEW); - break; - case FALSE: - case NULL: - case TRUE: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - Literal(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void PostfixExpression() throws ParseException { - /*@bgen(jjtree) PostfixExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTPOSTFIXEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - PrimaryExpression(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INCR: - case DECR: - PostfixOperator(); - break; - default: - ; - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void PostfixOperator() throws ParseException { - /*@bgen(jjtree) PostfixOperator */ - SimpleNode jjtn000 = new SimpleNode(JJTPOSTFIXOPERATOR); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INCR: - jj_consume_token(INCR); - break; - case DECR: - jj_consume_token(DECR); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void CastExpression() throws ParseException { - /*@bgen(jjtree) CastExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTCASTEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (jj_2_28(2147483647)) { - jj_consume_token(LPAREN); - Type(); - jj_consume_token(RPAREN); - UnaryExpression(); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LPAREN: - jj_consume_token(LPAREN); - Type(); - jj_consume_token(RPAREN); - UnaryExpressionNotPlusMinus(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void PrimaryExpression() throws ParseException { - /*@bgen(jjtree) PrimaryExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTPRIMARYEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - PrimaryPrefix(); - label_34: - while (true) { - if (jj_2_29(2)) { - ; - } else { - break label_34; - } - PrimarySuffix(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void MemberSelector() throws ParseException { - /*@bgen(jjtree) MemberSelector */ - SimpleNode jjtn000 = new SimpleNode(JJTMEMBERSELECTOR); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(DOT); - TypeArguments(); - jj_consume_token(IDENTIFIER); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void PrimaryPrefix() throws ParseException { - /*@bgen(jjtree) PrimaryPrefix */ - SimpleNode jjtn000 = new SimpleNode(JJTPRIMARYPREFIX); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case FALSE: - case NULL: - case TRUE: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - Literal(); - break; - default: - if (jj_2_30(2147483647)) { - label_35: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENTIFIER: - ; - break; - default: - break label_35; - } - jj_consume_token(IDENTIFIER); - jj_consume_token(DOT); - } - jj_consume_token(THIS); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case SUPER: - jj_consume_token(SUPER); - jj_consume_token(DOT); - jj_consume_token(IDENTIFIER); - break; - case LPAREN: - jj_consume_token(LPAREN); - Expression(); - jj_consume_token(RPAREN); - break; - case NEW: - AllocationExpression(); - break; - default: - if (jj_2_31(2147483647)) { - ResultType(); - jj_consume_token(DOT); - jj_consume_token(CLASS); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENTIFIER: - Name(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void PrimarySuffix() throws ParseException { - /*@bgen(jjtree) PrimarySuffix */ - SimpleNode jjtn000 = new SimpleNode(JJTPRIMARYSUFFIX); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (jj_2_32(2147483647)) { - jj_consume_token(DOT); - jj_consume_token(SUPER); - } else if (jj_2_33(2147483647)) { - jj_consume_token(DOT); - jj_consume_token(THIS); - } else if (jj_2_34(2)) { - jj_consume_token(DOT); - AllocationExpression(); - } else if (jj_2_35(3)) { - MemberSelector(); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACKET: - jj_consume_token(LBRACKET); - Expression(); - jj_consume_token(RBRACKET); - break; - case DOT: - jj_consume_token(DOT); - jj_consume_token(IDENTIFIER); - break; - case LPAREN: - Arguments(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void Literal() throws ParseException { - /*@bgen(jjtree) Literal */ - SimpleNode jjtn000 = new SimpleNode(JJTLITERAL); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INTEGER_LITERAL: - jj_consume_token(INTEGER_LITERAL); - break; - case FLOATING_POINT_LITERAL: - jj_consume_token(FLOATING_POINT_LITERAL); - break; - case CHARACTER_LITERAL: - jj_consume_token(CHARACTER_LITERAL); - break; - case STRING_LITERAL: - jj_consume_token(STRING_LITERAL); - break; - case FALSE: - case TRUE: - BooleanLiteral(); - break; - case NULL: - NullLiteral(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void BooleanLiteral() throws ParseException { - /*@bgen(jjtree) BooleanLiteral */ - SimpleNode jjtn000 = new SimpleNode(JJTBOOLEANLITERAL); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case TRUE: - jj_consume_token(TRUE); - break; - case FALSE: - jj_consume_token(FALSE); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void NullLiteral() throws ParseException { - /*@bgen(jjtree) NullLiteral */ - SimpleNode jjtn000 = new SimpleNode(JJTNULLLITERAL); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(NULL); - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void Arguments() throws ParseException { - /*@bgen(jjtree) Arguments */ - SimpleNode jjtn000 = new SimpleNode(JJTARGUMENTS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(LPAREN); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FALSE: - case FLOAT: - case INT: - case LONG: - case NEW: - case NULL: - case SHORT: - case SUPER: - case THIS: - case TRUE: - case VOID: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case BANG: - case TILDE: - case INCR: - case DECR: - case PLUS: - case MINUS: - ArgumentList(); - break; - default: - ; - } - jj_consume_token(RPAREN); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ArgumentList() throws ParseException { - /*@bgen(jjtree) ArgumentList */ - SimpleNode jjtn000 = new SimpleNode(JJTARGUMENTLIST); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - Expression(); - label_36: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - break label_36; - } - jj_consume_token(COMMA); - Expression(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void AllocationExpression() throws ParseException { - /*@bgen(jjtree) AllocationExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTALLOCATIONEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (jj_2_36(2)) { - jj_consume_token(NEW); - PrimitiveType(); - ArrayDimsAndInits(); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case NEW: - jj_consume_token(NEW); - ClassOrInterfaceType(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LT: - TypeArgumentsForAllocation(); - break; - default: - ; - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACKET: - ArrayDimsAndInits(); - break; - case LPAREN: - Arguments(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACE: - ClassOrInterfaceBody(false); - break; - default: - ; - } - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - /* - * The third LOOKAHEAD specification below is to parse to PrimarySuffix - * if there is an expression between the "[...]". - */ - final public void ArrayDimsAndInits() throws ParseException { - /*@bgen(jjtree) ArrayDimsAndInits */ - SimpleNode jjtn000 = new SimpleNode(JJTARRAYDIMSANDINITS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (jj_2_39(2)) { - label_37: - while (true) { - jj_consume_token(LBRACKET); - Expression(); - jj_consume_token(RBRACKET); - if (jj_2_37(2)) { - ; - } else { - break label_37; - } - } - label_38: - while (true) { - if (jj_2_38(2)) { - ; - } else { - break label_38; - } - jj_consume_token(LBRACKET); - jj_consume_token(RBRACKET); - } - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACKET: - label_39: - while (true) { - jj_consume_token(LBRACKET); - jj_consume_token(RBRACKET); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case LBRACKET: - ; - break; - default: - break label_39; - } - } - ArrayInitializer(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - /* - * Statement syntax follows. - */ - final public void Statement() throws ParseException { - /*@bgen(jjtree) Statement */ - SimpleNode jjtn000 = new SimpleNode(JJTSTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (jj_2_40(2)) { - LabeledStatement(); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ASSERT: - AssertStatement(); - break; - case LBRACE: - Block(); - break; - case SEMICOLON: - EmptyStatement(); - break; - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FALSE: - case FLOAT: - case INT: - case LONG: - case NEW: - case NULL: - case SHORT: - case SUPER: - case THIS: - case TRUE: - case VOID: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case INCR: - case DECR: - StatementExpression(); - jj_consume_token(SEMICOLON); - break; - case SWITCH: - SwitchStatement(); - break; - case IF: - IfStatement(); - break; - case WHILE: - WhileStatement(); - break; - case DO: - DoStatement(); - break; - case FOR: - ForStatement(); - break; - case BREAK: - BreakStatement(); - break; - case CONTINUE: - ContinueStatement(); - break; - case RETURN: - ReturnStatement(); - break; - case THROW: - ThrowStatement(); - break; - case SYNCHRONIZED: - SynchronizedStatement(); - break; - case TRY: - TryStatement(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void AssertStatement() throws ParseException { - /*@bgen(jjtree) AssertStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTASSERTSTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(ASSERT); - Expression(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COLON: - jj_consume_token(COLON); - Expression(); - break; - default: - ; - } - jj_consume_token(SEMICOLON); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void LabeledStatement() throws ParseException { - /*@bgen(jjtree) LabeledStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTLABELEDSTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(IDENTIFIER); - jj_consume_token(COLON); - Statement(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void Block() throws ParseException { - /*@bgen(jjtree) Block */ - SimpleNode jjtn000 = new SimpleNode(JJTBLOCK); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(LBRACE); - label_40: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ABSTRACT: - case ASSERT: - case BOOLEAN: - case BREAK: - case BYTE: - case CHAR: - case CLASS: - case CONTINUE: - case DO: - case DOUBLE: - case FALSE: - case FINAL: - case FLOAT: - case FOR: - case IF: - case INT: - case INTERFACE: - case LONG: - case NATIVE: - case NEW: - case NULL: - case PRIVATE: - case PROTECTED: - case PUBLIC: - case RETURN: - case SHORT: - case STATIC: - case STRICTFP: - case SUPER: - case SWITCH: - case SYNCHRONIZED: - case THIS: - case THROW: - case TRANSIENT: - case TRUE: - case TRY: - case VOID: - case VOLATILE: - case WHILE: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case LBRACE: - case SEMICOLON: - case AT: - case INCR: - case DECR: - ; - break; - default: - break label_40; - } - BlockStatement(); - } - jj_consume_token(RBRACE); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void BlockStatement() throws ParseException { - /*@bgen(jjtree) BlockStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTBLOCKSTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (jj_2_41(2147483647)) { - LocalVariableDeclaration(); - jj_consume_token(SEMICOLON); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ASSERT: - case BOOLEAN: - case BREAK: - case BYTE: - case CHAR: - case CONTINUE: - case DO: - case DOUBLE: - case FALSE: - case FLOAT: - case FOR: - case IF: - case INT: - case LONG: - case NEW: - case NULL: - case RETURN: - case SHORT: - case SUPER: - case SWITCH: - case SYNCHRONIZED: - case THIS: - case THROW: - case TRUE: - case TRY: - case VOID: - case WHILE: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case LBRACE: - case SEMICOLON: - case INCR: - case DECR: - Statement(); - break; - case CLASS: - case INTERFACE: - ClassOrInterfaceDeclaration(0); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void LocalVariableDeclaration() throws ParseException { - /*@bgen(jjtree) LocalVariableDeclaration */ - SimpleNode jjtn000 = new SimpleNode(JJTLOCALVARIABLEDECLARATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - Modifiers(); - Type(); - VariableDeclarator(); - label_41: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - break label_41; - } - jj_consume_token(COMMA); - VariableDeclarator(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void EmptyStatement() throws ParseException { - /*@bgen(jjtree) EmptyStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTEMPTYSTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(SEMICOLON); - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void StatementExpression() throws ParseException { - /*@bgen(jjtree) StatementExpression */ - SimpleNode jjtn000 = new SimpleNode(JJTSTATEMENTEXPRESSION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case INCR: - PreIncrementExpression(); - break; - case DECR: - PreDecrementExpression(); - break; - default: - if (jj_2_42(2147483647)) { - AssignmentExpression(); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FALSE: - case FLOAT: - case INT: - case LONG: - case NEW: - case NULL: - case SHORT: - case SUPER: - case THIS: - case TRUE: - case VOID: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - PostfixExpression(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void SwitchStatement() throws ParseException { - /*@bgen(jjtree) SwitchStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTSWITCHSTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(SWITCH); - jj_consume_token(LPAREN); - Expression(); - jj_consume_token(RPAREN); - jj_consume_token(LBRACE); - label_42: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case CASE: - case _DEFAULT: - ; - break; - default: - break label_42; - } - SwitchLabel(); - label_43: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ABSTRACT: - case ASSERT: - case BOOLEAN: - case BREAK: - case BYTE: - case CHAR: - case CLASS: - case CONTINUE: - case DO: - case DOUBLE: - case FALSE: - case FINAL: - case FLOAT: - case FOR: - case IF: - case INT: - case INTERFACE: - case LONG: - case NATIVE: - case NEW: - case NULL: - case PRIVATE: - case PROTECTED: - case PUBLIC: - case RETURN: - case SHORT: - case STATIC: - case STRICTFP: - case SUPER: - case SWITCH: - case SYNCHRONIZED: - case THIS: - case THROW: - case TRANSIENT: - case TRUE: - case TRY: - case VOID: - case VOLATILE: - case WHILE: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case LBRACE: - case SEMICOLON: - case AT: - case INCR: - case DECR: - ; - break; - default: - break label_43; - } - BlockStatement(); - } - } - jj_consume_token(RBRACE); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void SwitchLabel() throws ParseException { - /*@bgen(jjtree) SwitchLabel */ - SimpleNode jjtn000 = new SimpleNode(JJTSWITCHLABEL); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case CASE: - jj_consume_token(CASE); - Expression(); - jj_consume_token(COLON); - break; - case _DEFAULT: - jj_consume_token(_DEFAULT); - jj_consume_token(COLON); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void IfStatement() throws ParseException { - /*@bgen(jjtree) IfStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTIFSTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(IF); - jj_consume_token(LPAREN); - Expression(); - jj_consume_token(RPAREN); - Statement(); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ELSE: - jj_consume_token(ELSE); - Statement(); - break; - default: - ; - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void WhileStatement() throws ParseException { - /*@bgen(jjtree) WhileStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTWHILESTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(WHILE); - jj_consume_token(LPAREN); - Expression(); - jj_consume_token(RPAREN); - Statement(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void DoStatement() throws ParseException { - /*@bgen(jjtree) DoStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTDOSTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(DO); - Statement(); - jj_consume_token(WHILE); - jj_consume_token(LPAREN); - Expression(); - jj_consume_token(RPAREN); - jj_consume_token(SEMICOLON); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ForStatement() throws ParseException { - /*@bgen(jjtree) ForStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTFORSTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(FOR); - jj_consume_token(LPAREN); - if (jj_2_43(2147483647)) { - Modifiers(); - Type(); - jj_consume_token(IDENTIFIER); - jj_consume_token(COLON); - Expression(); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ABSTRACT: - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FALSE: - case FINAL: - case FLOAT: - case INT: - case LONG: - case NATIVE: - case NEW: - case NULL: - case PRIVATE: - case PROTECTED: - case PUBLIC: - case SHORT: - case STATIC: - case STRICTFP: - case SUPER: - case SYNCHRONIZED: - case THIS: - case TRANSIENT: - case TRUE: - case VOID: - case VOLATILE: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case SEMICOLON: - case AT: - case INCR: - case DECR: - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ABSTRACT: - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FALSE: - case FINAL: - case FLOAT: - case INT: - case LONG: - case NATIVE: - case NEW: - case NULL: - case PRIVATE: - case PROTECTED: - case PUBLIC: - case SHORT: - case STATIC: - case STRICTFP: - case SUPER: - case SYNCHRONIZED: - case THIS: - case TRANSIENT: - case TRUE: - case VOID: - case VOLATILE: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case AT: - case INCR: - case DECR: - ForInit(); - break; - default: - ; - } - jj_consume_token(SEMICOLON); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FALSE: - case FLOAT: - case INT: - case LONG: - case NEW: - case NULL: - case SHORT: - case SUPER: - case THIS: - case TRUE: - case VOID: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case BANG: - case TILDE: - case INCR: - case DECR: - case PLUS: - case MINUS: - Expression(); - break; - default: - ; - } - jj_consume_token(SEMICOLON); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FALSE: - case FLOAT: - case INT: - case LONG: - case NEW: - case NULL: - case SHORT: - case SUPER: - case THIS: - case TRUE: - case VOID: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case INCR: - case DECR: - ForUpdate(); - break; - default: - ; - } - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - jj_consume_token(RPAREN); - Statement(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ForInit() throws ParseException { - /*@bgen(jjtree) ForInit */ - SimpleNode jjtn000 = new SimpleNode(JJTFORINIT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (jj_2_44(2147483647)) { - LocalVariableDeclaration(); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FALSE: - case FLOAT: - case INT: - case LONG: - case NEW: - case NULL: - case SHORT: - case SUPER: - case THIS: - case TRUE: - case VOID: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case INCR: - case DECR: - StatementExpressionList(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void StatementExpressionList() throws ParseException { - /*@bgen(jjtree) StatementExpressionList */ - SimpleNode jjtn000 = new SimpleNode(JJTSTATEMENTEXPRESSIONLIST); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - StatementExpression(); - label_44: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - break label_44; - } - jj_consume_token(COMMA); - StatementExpression(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ForUpdate() throws ParseException { - /*@bgen(jjtree) ForUpdate */ - SimpleNode jjtn000 = new SimpleNode(JJTFORUPDATE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - StatementExpressionList(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void BreakStatement() throws ParseException { - /*@bgen(jjtree) BreakStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTBREAKSTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(BREAK); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENTIFIER: - jj_consume_token(IDENTIFIER); - break; - default: - ; - } - jj_consume_token(SEMICOLON); - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ContinueStatement() throws ParseException { - /*@bgen(jjtree) ContinueStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTCONTINUESTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(CONTINUE); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENTIFIER: - jj_consume_token(IDENTIFIER); - break; - default: - ; - } - jj_consume_token(SEMICOLON); - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ReturnStatement() throws ParseException { - /*@bgen(jjtree) ReturnStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTRETURNSTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(RETURN); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FALSE: - case FLOAT: - case INT: - case LONG: - case NEW: - case NULL: - case SHORT: - case SUPER: - case THIS: - case TRUE: - case VOID: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case BANG: - case TILDE: - case INCR: - case DECR: - case PLUS: - case MINUS: - Expression(); - break; - default: - ; - } - jj_consume_token(SEMICOLON); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void ThrowStatement() throws ParseException { - /*@bgen(jjtree) ThrowStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTTHROWSTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(THROW); - Expression(); - jj_consume_token(SEMICOLON); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void SynchronizedStatement() throws ParseException { - /*@bgen(jjtree) SynchronizedStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTSYNCHRONIZEDSTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(SYNCHRONIZED); - jj_consume_token(LPAREN); - Expression(); - jj_consume_token(RPAREN); - Block(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void TryStatement() throws ParseException { - /*@bgen(jjtree) TryStatement */ - SimpleNode jjtn000 = new SimpleNode(JJTTRYSTATEMENT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(TRY); - Block(); - label_45: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case CATCH: - ; - break; - default: - break label_45; - } - jj_consume_token(CATCH); - jj_consume_token(LPAREN); - FormalParameter(); - jj_consume_token(RPAREN); - Block(); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case FINALLY: - jj_consume_token(FINALLY); - Block(); - break; - default: - ; - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - /* We use productions to match >>>, >> and > so that we can keep the - * type declaration syntax with generics clean - */ - final public void RUNSIGNEDSHIFT() throws ParseException { - /*@bgen(jjtree) RUNSIGNEDSHIFT */ - SimpleNode jjtn000 = new SimpleNode(JJTRUNSIGNEDSHIFT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (getToken(1).kind == GT && - ((Token.GTToken) getToken(1)).realKind == RUNSIGNEDSHIFT) { - - } else { - jj_consume_token(-1); - throw new ParseException(); - } - jj_consume_token(GT); - jj_consume_token(GT); - jj_consume_token(GT); - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void RSIGNEDSHIFT() throws ParseException { - /*@bgen(jjtree) RSIGNEDSHIFT */ - SimpleNode jjtn000 = new SimpleNode(JJTRSIGNEDSHIFT); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (getToken(1).kind == GT && - ((Token.GTToken) getToken(1)).realKind == RSIGNEDSHIFT) { - - } else { - jj_consume_token(-1); - throw new ParseException(); - } - jj_consume_token(GT); - jj_consume_token(GT); - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - /* Annotation syntax follows. */ - final public void Annotation() throws ParseException { - /*@bgen(jjtree) Annotation */ - SimpleNode jjtn000 = new SimpleNode(JJTANNOTATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - if (jj_2_45(2147483647)) { - NormalAnnotation(); - } else if (jj_2_46(2147483647)) { - SingleMemberAnnotation(); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case AT: - MarkerAnnotation(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void NormalAnnotation() throws ParseException { - /*@bgen(jjtree) NormalAnnotation */ - SimpleNode jjtn000 = new SimpleNode(JJTNORMALANNOTATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(AT); - Name(); - jj_consume_token(LPAREN); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case IDENTIFIER: - MemberValuePairs(); - break; - default: - ; - } - jj_consume_token(RPAREN); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void MarkerAnnotation() throws ParseException { - /*@bgen(jjtree) MarkerAnnotation */ - SimpleNode jjtn000 = new SimpleNode(JJTMARKERANNOTATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(AT); - Name(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void SingleMemberAnnotation() throws ParseException { - /*@bgen(jjtree) SingleMemberAnnotation */ - SimpleNode jjtn000 = new SimpleNode(JJTSINGLEMEMBERANNOTATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(AT); - Name(); - jj_consume_token(LPAREN); - MemberValue(); - jj_consume_token(RPAREN); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void MemberValuePairs() throws ParseException { - /*@bgen(jjtree) MemberValuePairs */ - SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUEPAIRS); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - MemberValuePair(); - label_46: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - ; - break; - default: - break label_46; - } - jj_consume_token(COMMA); - MemberValuePair(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void MemberValuePair() throws ParseException { - /*@bgen(jjtree) MemberValuePair */ - SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUEPAIR); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(IDENTIFIER); - jj_consume_token(ASSIGN); - MemberValue(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void MemberValue() throws ParseException { - /*@bgen(jjtree) MemberValue */ - SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case AT: - Annotation(); - break; - case LBRACE: - MemberValueArrayInitializer(); - break; - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FALSE: - case FLOAT: - case INT: - case LONG: - case NEW: - case NULL: - case SHORT: - case SUPER: - case THIS: - case TRUE: - case VOID: - case INTEGER_LITERAL: - case FLOATING_POINT_LITERAL: - case CHARACTER_LITERAL: - case STRING_LITERAL: - case IDENTIFIER: - case LPAREN: - case BANG: - case TILDE: - case INCR: - case DECR: - case PLUS: - case MINUS: - ConditionalExpression(); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void MemberValueArrayInitializer() throws ParseException { - /*@bgen(jjtree) MemberValueArrayInitializer */ - SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUEARRAYINITIALIZER); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(LBRACE); - MemberValue(); - label_47: - while (true) { - if (jj_2_47(2)) { - ; - } else { - break label_47; - } - jj_consume_token(COMMA); - MemberValue(); - } - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case COMMA: - jj_consume_token(COMMA); - break; - default: - ; - } - jj_consume_token(RBRACE); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - /* Annotation Types. */ - final public void AnnotationTypeDeclaration(int modifiers) throws ParseException { - /*@bgen(jjtree) AnnotationTypeDeclaration */ - SimpleNode jjtn000 = new SimpleNode(JJTANNOTATIONTYPEDECLARATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(AT); - jj_consume_token(INTERFACE); - jj_consume_token(IDENTIFIER); - AnnotationTypeBody(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void AnnotationTypeBody() throws ParseException { - /*@bgen(jjtree) AnnotationTypeBody */ - SimpleNode jjtn000 = new SimpleNode(JJTANNOTATIONTYPEBODY); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(LBRACE); - label_48: - while (true) { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ABSTRACT: - case BOOLEAN: - case BYTE: - case CHAR: - case CLASS: - case DOUBLE: - case ENUM: - case FINAL: - case FLOAT: - case INT: - case INTERFACE: - case LONG: - case NATIVE: - case PRIVATE: - case PROTECTED: - case PUBLIC: - case SHORT: - case STATIC: - case STRICTFP: - case SYNCHRONIZED: - case TRANSIENT: - case VOLATILE: - case IDENTIFIER: - case SEMICOLON: - case AT: - ; - break; - default: - break label_48; - } - AnnotationTypeMemberDeclaration(); - } - jj_consume_token(RBRACE); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void AnnotationTypeMemberDeclaration() throws ParseException { - /*@bgen(jjtree) AnnotationTypeMemberDeclaration */ - SimpleNode jjtn000 = new SimpleNode(JJTANNOTATIONTYPEMEMBERDECLARATION); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - int modifiers; - try { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case ABSTRACT: - case BOOLEAN: - case BYTE: - case CHAR: - case CLASS: - case DOUBLE: - case ENUM: - case FINAL: - case FLOAT: - case INT: - case INTERFACE: - case LONG: - case NATIVE: - case PRIVATE: - case PROTECTED: - case PUBLIC: - case SHORT: - case STATIC: - case STRICTFP: - case SYNCHRONIZED: - case TRANSIENT: - case VOLATILE: - case IDENTIFIER: - case AT: - modifiers = Modifiers(); - if (jj_2_48(2147483647)) { - Type(); - jj_consume_token(IDENTIFIER); - jj_consume_token(LPAREN); - jj_consume_token(RPAREN); - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case _DEFAULT: - DefaultValue(); - break; - default: - ; - } - jj_consume_token(SEMICOLON); - } else { - switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { - case CLASS: - case INTERFACE: - ClassOrInterfaceDeclaration(modifiers); - break; - case ENUM: - EnumDeclaration(modifiers); - break; - case AT: - AnnotationTypeDeclaration(modifiers); - break; - case BOOLEAN: - case BYTE: - case CHAR: - case DOUBLE: - case FLOAT: - case INT: - case LONG: - case SHORT: - case IDENTIFIER: - FieldDeclaration(modifiers); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } - break; - case SEMICOLON: - jj_consume_token(SEMICOLON); - break; - default: - jj_consume_token(-1); - throw new ParseException(); - } - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final public void DefaultValue() throws ParseException { - /*@bgen(jjtree) DefaultValue */ - SimpleNode jjtn000 = new SimpleNode(JJTDEFAULTVALUE); - boolean jjtc000 = true; - jjtree.openNodeScope(jjtn000); - jjtreeOpenNodeScope(jjtn000); - try { - jj_consume_token(_DEFAULT); - MemberValue(); - } catch (Throwable jjte000) { - if (jjtc000) { - jjtree.clearNodeScope(jjtn000); - jjtc000 = false; - } else { - jjtree.popNode(); - } - if (jjte000 instanceof RuntimeException) { - { - if (true) throw (RuntimeException) jjte000; - } - } - if (jjte000 instanceof ParseException) { - { - if (true) throw (ParseException) jjte000; - } - } - { - if (true) throw (Error) jjte000; - } - } finally { - if (jjtc000) { - jjtree.closeNodeScope(jjtn000, true); - jjtreeCloseNodeScope(jjtn000); - } - } - } - - final private boolean jj_2_1(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_1(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_2(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_2(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_3(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_3(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_4(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_4(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_5(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_5(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_6(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_6(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_7(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_7(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_8(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_8(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_9(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_9(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_10(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_10(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_11(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_11(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_12(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_12(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_13(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_13(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_14(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_14(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_15(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_15(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_16(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_16(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_17(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_17(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_18(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_18(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_19(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_19(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_20(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_20(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_21(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_21(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_22(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_22(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_23(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_23(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_24(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_24(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_25(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_25(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_26(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_26(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_27(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_27(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_28(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_28(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_29(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_29(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_30(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_30(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_31(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_31(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_32(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_32(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_33(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_33(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_34(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_34(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_35(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_35(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_36(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_36(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_37(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_37(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_38(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_38(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_39(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_39(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_40(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_40(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_41(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_41(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_42(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_42(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_43(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_43(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_44(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_44(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_45(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_45(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_46(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_46(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_47(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_47(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_2_48(int xla) { - jj_la = xla; - jj_lastpos = jj_scanpos = token; - try { - return !jj_3_48(); - } catch (LookaheadSuccess ls) { - return true; - } - } - - final private boolean jj_3R_56() { - if (jj_3R_101()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3_21()) jj_scanpos = xsp; - return false; - } - - final private boolean jj_3R_135() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_91()) return true; - return false; - } - - final private boolean jj_3R_99() { - if (jj_3R_91()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_135()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3_20() { - if (jj_scan_token(DOT)) return true; - if (jj_scan_token(IDENTIFIER)) return true; - return false; - } - - final private boolean jj_3R_91() { - if (jj_scan_token(IDENTIFIER)) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3_20()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_122() { - if (jj_3R_72()) return true; - return false; - } - - final private boolean jj_3R_86() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(58)) { - jj_scanpos = xsp; - if (jj_3R_122()) return true; - } - return false; - } - - final private boolean jj_3_19() { - if (jj_3R_78()) return true; - return false; - } - - final private boolean jj_3R_83() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(10)) { - jj_scanpos = xsp; - if (jj_scan_token(15)) { - jj_scanpos = xsp; - if (jj_scan_token(12)) { - jj_scanpos = xsp; - if (jj_scan_token(46)) { - jj_scanpos = xsp; - if (jj_scan_token(35)) { - jj_scanpos = xsp; - if (jj_scan_token(37)) { - jj_scanpos = xsp; - if (jj_scan_token(28)) { - jj_scanpos = xsp; - if (jj_scan_token(21)) return true; - } - } - } - } - } - } - } - return false; - } - - final private boolean jj_3R_194() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_112()) return true; - return false; - } - - final private boolean jj_3R_290() { - if (jj_scan_token(SUPER)) return true; - if (jj_3R_77()) return true; - return false; - } - - final private boolean jj_3_16() { - if (jj_scan_token(LBRACKET)) return true; - if (jj_scan_token(RBRACKET)) return true; - return false; - } - - final private boolean jj_3R_289() { - if (jj_scan_token(EXTENDS)) return true; - if (jj_3R_77()) return true; - return false; - } - - final private boolean jj_3R_277() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_289()) { - jj_scanpos = xsp; - if (jj_3R_290()) return true; - } - return false; - } - - final private boolean jj_3R_256() { - if (jj_3R_277()) return true; - return false; - } - - final private boolean jj_3R_151() { - if (jj_scan_token(HOOK)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_256()) jj_scanpos = xsp; - return false; - } - - final private boolean jj_3_17() { - if (jj_3R_78()) return true; - return false; - } - - final private boolean jj_3R_112() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_150()) { - jj_scanpos = xsp; - if (jj_3R_151()) return true; - } - return false; - } - - final private boolean jj_3R_150() { - if (jj_3R_77()) return true; - return false; - } - - final private boolean jj_3_15() { - if (jj_scan_token(LBRACKET)) return true; - if (jj_scan_token(RBRACKET)) return true; - return false; - } - - final private boolean jj_3R_78() { - if (jj_scan_token(LT)) return true; - if (jj_3R_112()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_194()) { - jj_scanpos = xsp; - break; - } - } - if (jj_scan_token(GT)) return true; - return false; - } - - final private boolean jj_3_18() { - if (jj_scan_token(DOT)) return true; - if (jj_scan_token(IDENTIFIER)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3_19()) jj_scanpos = xsp; - return false; - } - - final private boolean jj_3R_149() { - if (jj_scan_token(IDENTIFIER)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3_17()) jj_scanpos = xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3_18()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_111() { - if (jj_3R_149()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3_16()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_110() { - if (jj_3R_83()) return true; - Token xsp; - if (jj_3_15()) return true; - while (true) { - xsp = jj_scanpos; - if (jj_3_15()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_77() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_110()) { - jj_scanpos = xsp; - if (jj_3R_111()) return true; - } - return false; - } - - final private boolean jj_3_13() { - if (jj_scan_token(THIS)) return true; - if (jj_scan_token(DOT)) return true; - return false; - } - - final private boolean jj_3R_221() { - if (jj_scan_token(THROWS)) return true; - if (jj_3R_99()) return true; - return false; - } - - final private boolean jj_3R_103() { - if (jj_3R_83()) return true; - return false; - } - - final private boolean jj_3R_72() { - Token xsp; - xsp = jj_scanpos; - if (jj_3_14()) { - jj_scanpos = xsp; - if (jj_3R_103()) return true; - } - return false; - } - - final private boolean jj_3_14() { - if (jj_3R_77()) return true; - return false; - } - - final private boolean jj_3R_74() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(47)) jj_scanpos = xsp; - if (jj_3R_104()) return true; - return false; - } - - final private boolean jj_3_12() { - if (jj_3R_76()) return true; - return false; - } - - final private boolean jj_3R_108() { - if (jj_3R_78()) return true; - return false; - } - - final private boolean jj_3R_107() { - if (jj_scan_token(IDENTIFIER)) return true; - if (jj_scan_token(DOT)) return true; - return false; - } - - final private boolean jj_3R_252() { - if (jj_scan_token(LBRACKET)) return true; - if (jj_scan_token(RBRACKET)) return true; - return false; - } - - final private boolean jj_3R_76() { - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_107()) { - jj_scanpos = xsp; - break; - } - } - xsp = jj_scanpos; - if (jj_3_13()) jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_3R_108()) jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_scan_token(52)) { - jj_scanpos = xsp; - if (jj_scan_token(49)) return true; - } - if (jj_3R_109()) return true; - if (jj_scan_token(SEMICOLON)) return true; - return false; - } - - final private boolean jj_3R_134() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_133()) return true; - return false; - } - - final private boolean jj_3R_223() { - if (jj_3R_49()) return true; - return false; - } - - final private boolean jj_3R_222() { - if (jj_3R_76()) return true; - return false; - } - - final private boolean jj_3R_220() { - if (jj_3R_97()) return true; - return false; - } - - final private boolean jj_3R_186() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_220()) jj_scanpos = xsp; - if (jj_scan_token(IDENTIFIER)) return true; - if (jj_3R_53()) return true; - xsp = jj_scanpos; - if (jj_3R_221()) jj_scanpos = xsp; - if (jj_scan_token(LBRACE)) return true; - xsp = jj_scanpos; - if (jj_3R_222()) jj_scanpos = xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_223()) { - jj_scanpos = xsp; - break; - } - } - if (jj_scan_token(RBRACE)) return true; - return false; - } - - final private boolean jj_3_11() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_75()) return true; - return false; - } - - final private boolean jj_3R_227() { - if (jj_scan_token(THROWS)) return true; - if (jj_3R_99()) return true; - return false; - } - - final private boolean jj_3R_98() { - if (jj_3R_133()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_134()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_133() { - if (jj_3R_50()) return true; - if (jj_3R_72()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(119)) jj_scanpos = xsp; - if (jj_3R_184()) return true; - return false; - } - - final private boolean jj_3R_53() { - if (jj_scan_token(LPAREN)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_98()) jj_scanpos = xsp; - if (jj_scan_token(RPAREN)) return true; - return false; - } - - final private boolean jj_3_48() { - if (jj_3R_72()) return true; - if (jj_scan_token(IDENTIFIER)) return true; - if (jj_scan_token(LPAREN)) return true; - return false; - } - - final private boolean jj_3R_226() { - if (jj_scan_token(IDENTIFIER)) return true; - if (jj_3R_53()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_252()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_228() { - if (jj_3R_104()) return true; - return false; - } - - final private boolean jj_3R_225() { - if (jj_3R_97()) return true; - return false; - } - - final private boolean jj_3R_292() { - if (jj_3R_75()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3_11()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_188() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_225()) jj_scanpos = xsp; - if (jj_3R_86()) return true; - if (jj_3R_226()) return true; - xsp = jj_scanpos; - if (jj_3R_227()) jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_3R_228()) { - jj_scanpos = xsp; - if (jj_scan_token(81)) return true; - } - return false; - } - - final private boolean jj_3R_198() { - if (jj_scan_token(ASSIGN)) return true; - if (jj_3R_75()) return true; - return false; - } - - final private boolean jj_3R_224() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_161()) return true; - return false; - } - - final private boolean jj_3_47() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_93()) return true; - return false; - } - - final private boolean jj_3R_217() { - if (jj_scan_token(LBRACKET)) return true; - if (jj_scan_token(RBRACKET)) return true; - return false; - } - - final private boolean jj_3R_147() { - if (jj_scan_token(LBRACE)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_292()) jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_scan_token(82)) jj_scanpos = xsp; - if (jj_scan_token(RBRACE)) return true; - return false; - } - - final private boolean jj_3R_73() { - if (jj_scan_token(LBRACKET)) return true; - if (jj_scan_token(RBRACKET)) return true; - return false; - } - - final private boolean jj_3R_106() { - if (jj_3R_56()) return true; - return false; - } - - final private boolean jj_3R_105() { - if (jj_3R_147()) return true; - return false; - } - - final private boolean jj_3R_75() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_105()) { - jj_scanpos = xsp; - if (jj_3R_106()) return true; - } - return false; - } - - final private boolean jj_3R_184() { - if (jj_scan_token(IDENTIFIER)) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_217()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_160() { - if (jj_scan_token(LBRACE)) return true; - if (jj_3R_93()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3_47()) { - jj_scanpos = xsp; - break; - } - } - xsp = jj_scanpos; - if (jj_scan_token(82)) jj_scanpos = xsp; - if (jj_scan_token(RBRACE)) return true; - return false; - } - - final private boolean jj_3R_276() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_275()) return true; - return false; - } - - final private boolean jj_3R_161() { - if (jj_3R_184()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_198()) jj_scanpos = xsp; - return false; - } - - final private boolean jj_3R_127() { - if (jj_3R_101()) return true; - return false; - } - - final private boolean jj_3_9() { - if (jj_3R_72()) return true; - if (jj_scan_token(IDENTIFIER)) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_73()) { - jj_scanpos = xsp; - break; - } - } - xsp = jj_scanpos; - if (jj_scan_token(82)) { - jj_scanpos = xsp; - if (jj_scan_token(85)) { - jj_scanpos = xsp; - if (jj_scan_token(81)) return true; - } - } - return false; - } - - final private boolean jj_3R_126() { - if (jj_3R_160()) return true; - return false; - } - - final private boolean jj_3R_71() { - if (jj_3R_97()) return true; - return false; - } - - final private boolean jj_3R_93() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_125()) { - jj_scanpos = xsp; - if (jj_3R_126()) { - jj_scanpos = xsp; - if (jj_3R_127()) return true; - } - } - return false; - } - - final private boolean jj_3R_125() { - if (jj_3R_102()) return true; - return false; - } - - final private boolean jj_3_8() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_71()) jj_scanpos = xsp; - if (jj_scan_token(IDENTIFIER)) return true; - if (jj_scan_token(LPAREN)) return true; - return false; - } - - final private boolean jj_3R_187() { - if (jj_3R_72()) return true; - if (jj_3R_161()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_224()) { - jj_scanpos = xsp; - break; - } - } - if (jj_scan_token(SEMICOLON)) return true; - return false; - } - - final private boolean jj_3R_275() { - if (jj_scan_token(IDENTIFIER)) return true; - if (jj_scan_token(ASSIGN)) return true; - if (jj_3R_93()) return true; - return false; - } - - final private boolean jj_3R_140() { - if (jj_3R_188()) return true; - return false; - } - - final private boolean jj_3R_139() { - if (jj_3R_187()) return true; - return false; - } - - final private boolean jj_3R_249() { - if (jj_scan_token(BIT_AND)) return true; - if (jj_3R_149()) return true; - return false; - } - - final private boolean jj_3R_138() { - if (jj_3R_186()) return true; - return false; - } - - final private boolean jj_3R_255() { - if (jj_3R_275()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_276()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_231() { - if (jj_3R_255()) return true; - return false; - } - - final private boolean jj_3R_137() { - if (jj_3R_185()) return true; - return false; - } - - final private boolean jj_3R_92() { - if (jj_scan_token(IDENTIFIER)) return true; - if (jj_scan_token(ASSIGN)) return true; - return false; - } - - final private boolean jj_3R_136() { - if (jj_3R_130()) return true; - return false; - } - - final private boolean jj_3R_192() { - if (jj_scan_token(AT)) return true; - if (jj_3R_91()) return true; - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_93()) return true; - if (jj_scan_token(RPAREN)) return true; - return false; - } - - final private boolean jj_3R_286() { - if (jj_3R_182()) return true; - return false; - } - - final private boolean jj_3R_100() { - if (jj_3R_50()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_136()) { - jj_scanpos = xsp; - if (jj_3R_137()) { - jj_scanpos = xsp; - if (jj_3R_138()) { - jj_scanpos = xsp; - if (jj_3R_139()) { - jj_scanpos = xsp; - if (jj_3R_140()) return true; - } - } - } - } - return false; - } - - final private boolean jj_3R_193() { - if (jj_scan_token(AT)) return true; - if (jj_3R_91()) return true; - return false; - } - - final private boolean jj_3_46() { - if (jj_scan_token(AT)) return true; - if (jj_3R_91()) return true; - if (jj_scan_token(LPAREN)) return true; - return false; - } - - final private boolean jj_3_10() { - if (jj_3R_74()) return true; - return false; - } - - final private boolean jj_3R_55() { - Token xsp; - xsp = jj_scanpos; - if (jj_3_10()) { - jj_scanpos = xsp; - if (jj_3R_100()) { - jj_scanpos = xsp; - if (jj_scan_token(81)) return true; - } - } - return false; - } - - final private boolean jj_3R_191() { - if (jj_scan_token(AT)) return true; - if (jj_3R_91()) return true; - if (jj_scan_token(LPAREN)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_231()) jj_scanpos = xsp; - if (jj_scan_token(RPAREN)) return true; - return false; - } - - final private boolean jj_3_45() { - if (jj_scan_token(AT)) return true; - if (jj_3R_91()) return true; - if (jj_scan_token(LPAREN)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_92()) { - jj_scanpos = xsp; - if (jj_scan_token(76)) return true; - } - return false; - } - - final private boolean jj_3R_215() { - if (jj_3R_55()) return true; - return false; - } - - final private boolean jj_3R_132() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_131()) return true; - return false; - } - - final private boolean jj_3R_183() { - if (jj_3R_216()) return true; - return false; - } - - final private boolean jj_3R_285() { - if (jj_3R_109()) return true; - return false; - } - - final private boolean jj_3R_145() { - if (jj_3R_193()) return true; - return false; - } - - final private boolean jj_3R_182() { - if (jj_scan_token(LBRACE)) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_215()) { - jj_scanpos = xsp; - break; - } - } - if (jj_scan_token(RBRACE)) return true; - return false; - } - - final private boolean jj_3R_144() { - if (jj_3R_192()) return true; - return false; - } - - final private boolean jj_3R_113() { - return false; - } - - final private boolean jj_3R_102() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_143()) { - jj_scanpos = xsp; - if (jj_3R_144()) { - jj_scanpos = xsp; - if (jj_3R_145()) return true; - } - } - return false; - } - - final private boolean jj_3R_143() { - if (jj_3R_191()) return true; - return false; - } - - final private boolean jj_3R_216() { - if (jj_scan_token(EXTENDS)) return true; - if (jj_3R_149()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_249()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_131() { - if (jj_scan_token(IDENTIFIER)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_183()) jj_scanpos = xsp; - return false; - } - - final private boolean jj_3R_114() { - return false; - } - - final private boolean jj_3_7() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_70()) return true; - return false; - } - - final private boolean jj_3R_80() { - Token xsp; - xsp = jj_scanpos; - lookingAhead = true; - jj_semLA = getToken(1).kind == GT && - ((Token.GTToken) getToken(1)).realKind == RSIGNEDSHIFT; - lookingAhead = false; - if (!jj_semLA || jj_3R_113()) return true; - if (jj_scan_token(GT)) return true; - if (jj_scan_token(GT)) return true; - return false; - } - - final private boolean jj_3R_97() { - if (jj_scan_token(LT)) return true; - if (jj_3R_131()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_132()) { - jj_scanpos = xsp; - break; - } - } - if (jj_scan_token(GT)) return true; - return false; - } - - final private boolean jj_3R_272() { - if (jj_3R_55()) return true; - return false; - } - - final private boolean jj_3R_70() { - if (jj_3R_50()) return true; - if (jj_scan_token(IDENTIFIER)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_285()) jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_3R_286()) jj_scanpos = xsp; - return false; - } - - final private boolean jj_3R_81() { - Token xsp; - xsp = jj_scanpos; - lookingAhead = true; - jj_semLA = getToken(1).kind == GT && - ((Token.GTToken) getToken(1)).realKind == RUNSIGNEDSHIFT; - lookingAhead = false; - if (!jj_semLA || jj_3R_114()) return true; - if (jj_scan_token(GT)) return true; - if (jj_scan_token(GT)) return true; - if (jj_scan_token(GT)) return true; - return false; - } - - final private boolean jj_3R_251() { - if (jj_scan_token(SEMICOLON)) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_272()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_250() { - if (jj_3R_70()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3_7()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_246() { - if (jj_scan_token(FINALLY)) return true; - if (jj_3R_104()) return true; - return false; - } - - final private boolean jj_3R_219() { - if (jj_scan_token(LBRACE)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_250()) jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_scan_token(82)) jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_3R_251()) jj_scanpos = xsp; - if (jj_scan_token(RBRACE)) return true; - return false; - } - - final private boolean jj_3R_245() { - if (jj_scan_token(CATCH)) return true; - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_133()) return true; - if (jj_scan_token(RPAREN)) return true; - if (jj_3R_104()) return true; - return false; - } - - final private boolean jj_3R_212() { - if (jj_scan_token(TRY)) return true; - if (jj_3R_104()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_245()) { - jj_scanpos = xsp; - break; - } - } - xsp = jj_scanpos; - if (jj_3R_246()) jj_scanpos = xsp; - return false; - } - - final private boolean jj_3R_218() { - if (jj_3R_214()) return true; - return false; - } - - final private boolean jj_3R_185() { - if (jj_scan_token(ENUM)) return true; - if (jj_scan_token(IDENTIFIER)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_218()) jj_scanpos = xsp; - if (jj_3R_219()) return true; - return false; - } - - final private boolean jj_3R_211() { - if (jj_scan_token(SYNCHRONIZED)) return true; - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_56()) return true; - if (jj_scan_token(RPAREN)) return true; - if (jj_3R_104()) return true; - return false; - } - - final private boolean jj_3R_244() { - if (jj_3R_56()) return true; - return false; - } - - final private boolean jj_3R_248() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_149()) return true; - return false; - } - - final private boolean jj_3R_214() { - if (jj_scan_token(IMPLEMENTS)) return true; - if (jj_3R_149()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_248()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_210() { - if (jj_scan_token(THROW)) return true; - if (jj_3R_56()) return true; - if (jj_scan_token(SEMICOLON)) return true; - return false; - } - - final private boolean jj_3R_271() { - if (jj_3R_284()) return true; - return false; - } - - final private boolean jj_3R_299() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_201()) return true; - return false; - } - - final private boolean jj_3R_209() { - if (jj_scan_token(RETURN)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_244()) jj_scanpos = xsp; - if (jj_scan_token(SEMICOLON)) return true; - return false; - } - - final private boolean jj_3R_247() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_149()) return true; - return false; - } - - final private boolean jj_3R_213() { - if (jj_scan_token(EXTENDS)) return true; - if (jj_3R_149()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_247()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_208() { - if (jj_scan_token(CONTINUE)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(72)) jj_scanpos = xsp; - if (jj_scan_token(SEMICOLON)) return true; - return false; - } - - final private boolean jj_3R_178() { - if (jj_scan_token(INTERFACE)) return true; - return false; - } - - final private boolean jj_3R_207() { - if (jj_scan_token(BREAK)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(72)) jj_scanpos = xsp; - if (jj_scan_token(SEMICOLON)) return true; - return false; - } - - final private boolean jj_3R_181() { - if (jj_3R_214()) return true; - return false; - } - - final private boolean jj_3R_180() { - if (jj_3R_213()) return true; - return false; - } - - final private boolean jj_3R_179() { - if (jj_3R_97()) return true; - return false; - } - - final private boolean jj_3R_284() { - if (jj_3R_296()) return true; - return false; - } - - final private boolean jj_3R_270() { - if (jj_3R_56()) return true; - return false; - } - - final private boolean jj_3R_130() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(16)) { - jj_scanpos = xsp; - if (jj_3R_178()) return true; - } - if (jj_scan_token(IDENTIFIER)) return true; - xsp = jj_scanpos; - if (jj_3R_179()) jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_3R_180()) jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_3R_181()) jj_scanpos = xsp; - if (jj_3R_182()) return true; - return false; - } - - final private boolean jj_3_44() { - if (jj_3R_50()) return true; - if (jj_3R_72()) return true; - if (jj_scan_token(IDENTIFIER)) return true; - return false; - } - - final private boolean jj_3R_296() { - if (jj_3R_201()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_299()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_241() { - if (jj_scan_token(ELSE)) return true; - if (jj_3R_129()) return true; - return false; - } - - final private boolean jj_3R_295() { - if (jj_3R_296()) return true; - return false; - } - - final private boolean jj_3_43() { - if (jj_3R_50()) return true; - if (jj_3R_72()) return true; - if (jj_scan_token(IDENTIFIER)) return true; - if (jj_scan_token(COLON)) return true; - return false; - } - - final private boolean jj_3R_294() { - if (jj_3R_128()) return true; - return false; - } - - final private boolean jj_3R_283() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_294()) { - jj_scanpos = xsp; - if (jj_3R_295()) return true; - } - return false; - } - - final private boolean jj_3R_269() { - if (jj_3R_283()) return true; - return false; - } - - final private boolean jj_3R_243() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_269()) jj_scanpos = xsp; - if (jj_scan_token(SEMICOLON)) return true; - xsp = jj_scanpos; - if (jj_3R_270()) jj_scanpos = xsp; - if (jj_scan_token(SEMICOLON)) return true; - xsp = jj_scanpos; - if (jj_3R_271()) jj_scanpos = xsp; - return false; - } - - final private boolean jj_3R_242() { - if (jj_3R_50()) return true; - if (jj_3R_72()) return true; - if (jj_scan_token(IDENTIFIER)) return true; - if (jj_scan_token(COLON)) return true; - if (jj_3R_56()) return true; - return false; - } - - final private boolean jj_3R_54() { - if (jj_scan_token(THROWS)) return true; - if (jj_3R_99()) return true; - return false; - } - - final private boolean jj_3R_206() { - if (jj_scan_token(FOR)) return true; - if (jj_scan_token(LPAREN)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_242()) { - jj_scanpos = xsp; - if (jj_3R_243()) return true; - } - if (jj_scan_token(RPAREN)) return true; - if (jj_3R_129()) return true; - return false; - } - - final private boolean jj_3R_69() { - if (jj_3R_102()) return true; - return false; - } - - final private boolean jj_3R_205() { - if (jj_scan_token(DO)) return true; - if (jj_3R_129()) return true; - if (jj_scan_token(WHILE)) return true; - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_56()) return true; - if (jj_scan_token(RPAREN)) return true; - if (jj_scan_token(SEMICOLON)) return true; - return false; - } - - final private boolean jj_3R_68() { - if (jj_scan_token(STRICTFP)) return true; - return false; - } - - final private boolean jj_3R_67() { - if (jj_scan_token(VOLATILE)) return true; - return false; - } - - final private boolean jj_3R_66() { - if (jj_scan_token(TRANSIENT)) return true; - return false; - } - - final private boolean jj_3R_204() { - if (jj_scan_token(WHILE)) return true; - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_56()) return true; - if (jj_scan_token(RPAREN)) return true; - if (jj_3R_129()) return true; - return false; - } - - final private boolean jj_3R_65() { - if (jj_scan_token(NATIVE)) return true; - return false; - } - - final private boolean jj_3R_64() { - if (jj_scan_token(SYNCHRONIZED)) return true; - return false; - } - - final private boolean jj_3R_63() { - if (jj_scan_token(ABSTRACT)) return true; - return false; - } - - final private boolean jj_3R_268() { - if (jj_3R_49()) return true; - return false; - } - - final private boolean jj_3R_203() { - if (jj_scan_token(IF)) return true; - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_56()) return true; - if (jj_scan_token(RPAREN)) return true; - if (jj_3R_129()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_241()) jj_scanpos = xsp; - return false; - } - - final private boolean jj_3R_62() { - if (jj_scan_token(FINAL)) return true; - return false; - } - - final private boolean jj_3R_61() { - if (jj_scan_token(PRIVATE)) return true; - return false; - } - - final private boolean jj_3R_162() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_161()) return true; - return false; - } - - final private boolean jj_3R_60() { - if (jj_scan_token(PROTECTED)) return true; - return false; - } - - final private boolean jj_3R_59() { - if (jj_scan_token(STATIC)) return true; - return false; - } - - final private boolean jj_3R_58() { - if (jj_scan_token(PUBLIC)) return true; - return false; - } - - final private boolean jj_3R_282() { - if (jj_scan_token(_DEFAULT)) return true; - if (jj_scan_token(COLON)) return true; - return false; - } - - final private boolean jj_3_6() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_58()) { - jj_scanpos = xsp; - if (jj_3R_59()) { - jj_scanpos = xsp; - if (jj_3R_60()) { - jj_scanpos = xsp; - if (jj_3R_61()) { - jj_scanpos = xsp; - if (jj_3R_62()) { - jj_scanpos = xsp; - if (jj_3R_63()) { - jj_scanpos = xsp; - if (jj_3R_64()) { - jj_scanpos = xsp; - if (jj_3R_65()) { - jj_scanpos = xsp; - if (jj_3R_66()) { - jj_scanpos = xsp; - if (jj_3R_67()) { - jj_scanpos = xsp; - if (jj_3R_68()) { - jj_scanpos = xsp; - if (jj_3R_69()) return true; - } - } - } - } - } - } - } - } - } - } - } - return false; - } - - final private boolean jj_3R_281() { - if (jj_scan_token(CASE)) return true; - if (jj_3R_56()) return true; - if (jj_scan_token(COLON)) return true; - return false; - } - - final private boolean jj_3R_267() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_281()) { - jj_scanpos = xsp; - if (jj_3R_282()) return true; - } - return false; - } - - final private boolean jj_3R_50() { - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3_6()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_240() { - if (jj_3R_267()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_268()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3_42() { - if (jj_3R_90()) return true; - if (jj_3R_79()) return true; - return false; - } - - final private boolean jj_3R_202() { - if (jj_scan_token(SWITCH)) return true; - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_56()) return true; - if (jj_scan_token(RPAREN)) return true; - if (jj_scan_token(LBRACE)) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_240()) { - jj_scanpos = xsp; - break; - } - } - if (jj_scan_token(RBRACE)) return true; - return false; - } - - final private boolean jj_3R_239() { - if (jj_3R_266()) return true; - return false; - } - - final private boolean jj_3R_57() { - if (jj_3R_102()) return true; - return false; - } - - final private boolean jj_3R_52() { - if (jj_3R_86()) return true; - return false; - } - - final private boolean jj_3R_238() { - if (jj_3R_265()) return true; - return false; - } - - final private boolean jj_3_5() { - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_57()) { - jj_scanpos = xsp; - break; - } - } - if (jj_scan_token(PACKAGE)) return true; - return false; - } - - final private boolean jj_3R_237() { - if (jj_3R_264()) return true; - return false; - } - - final private boolean jj_3R_201() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_236()) { - jj_scanpos = xsp; - if (jj_3R_237()) { - jj_scanpos = xsp; - if (jj_3R_238()) { - jj_scanpos = xsp; - if (jj_3R_239()) return true; - } - } - } - return false; - } - - final private boolean jj_3R_236() { - if (jj_3R_263()) return true; - return false; - } - - final private boolean jj_3R_200() { - if (jj_scan_token(SEMICOLON)) return true; - return false; - } - - final private boolean jj_3_41() { - if (jj_3R_50()) return true; - if (jj_3R_72()) return true; - if (jj_scan_token(IDENTIFIER)) return true; - return false; - } - - final private boolean jj_3R_128() { - if (jj_3R_50()) return true; - if (jj_3R_72()) return true; - if (jj_3R_161()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_162()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_51() { - if (jj_3R_97()) return true; - return false; - } - - final private boolean jj_3R_235() { - if (jj_scan_token(COLON)) return true; - if (jj_3R_56()) return true; - return false; - } - - final private boolean jj_3R_96() { - if (jj_3R_130()) return true; - return false; - } - - final private boolean jj_3R_95() { - if (jj_3R_129()) return true; - return false; - } - - final private boolean jj_3_4() { - if (jj_3R_56()) return true; - return false; - } - - final private boolean jj_3R_94() { - if (jj_3R_128()) return true; - if (jj_scan_token(SEMICOLON)) return true; - return false; - } - - final private boolean jj_3R_49() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_94()) { - jj_scanpos = xsp; - if (jj_3R_95()) { - jj_scanpos = xsp; - if (jj_3R_96()) return true; - } - } - return false; - } - - final private boolean jj_3R_146() { - if (jj_3R_49()) return true; - return false; - } - - final private boolean jj_3_3() { - if (jj_3R_55()) return true; - return false; - } - - final private boolean jj_3R_104() { - if (jj_scan_token(LBRACE)) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_146()) { - jj_scanpos = xsp; - break; - } - } - if (jj_scan_token(RBRACE)) return true; - return false; - } - - final private boolean jj_3_2() { - if (jj_3R_50()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_51()) jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_3R_52()) jj_scanpos = xsp; - if (jj_scan_token(IDENTIFIER)) return true; - if (jj_3R_53()) return true; - xsp = jj_scanpos; - if (jj_3R_54()) jj_scanpos = xsp; - if (jj_scan_token(LBRACE)) return true; - return false; - } - - final private boolean jj_3R_89() { - if (jj_scan_token(IDENTIFIER)) return true; - if (jj_scan_token(COLON)) return true; - if (jj_3R_129()) return true; - return false; - } - - final private boolean jj_3_1() { - if (jj_3R_49()) return true; - return false; - } - - final private boolean jj_3R_199() { - if (jj_scan_token(ASSERT)) return true; - if (jj_3R_56()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_235()) jj_scanpos = xsp; - if (jj_scan_token(SEMICOLON)) return true; - return false; - } - - final private boolean jj_3R_177() { - if (jj_3R_212()) return true; - return false; - } - - final private boolean jj_3R_176() { - if (jj_3R_211()) return true; - return false; - } - - final private boolean jj_3_38() { - if (jj_scan_token(LBRACKET)) return true; - if (jj_scan_token(RBRACKET)) return true; - return false; - } - - final private boolean jj_3R_175() { - if (jj_3R_210()) return true; - return false; - } - - final private boolean jj_3R_174() { - if (jj_3R_209()) return true; - return false; - } - - final private boolean jj_3R_173() { - if (jj_3R_208()) return true; - return false; - } - - final private boolean jj_3R_172() { - if (jj_3R_207()) return true; - return false; - } - - final private boolean jj_3R_171() { - if (jj_3R_206()) return true; - return false; - } - - final private boolean jj_3R_170() { - if (jj_3R_205()) return true; - return false; - } - - final private boolean jj_3R_169() { - if (jj_3R_204()) return true; - return false; - } - - final private boolean jj_3R_168() { - if (jj_3R_203()) return true; - return false; - } - - final private boolean jj_3R_167() { - if (jj_3R_202()) return true; - return false; - } - - final private boolean jj_3R_166() { - if (jj_3R_201()) return true; - if (jj_scan_token(SEMICOLON)) return true; - return false; - } - - final private boolean jj_3R_165() { - if (jj_3R_200()) return true; - return false; - } - - final private boolean jj_3R_164() { - if (jj_3R_104()) return true; - return false; - } - - final private boolean jj_3R_163() { - if (jj_3R_199()) return true; - return false; - } - - final private boolean jj_3R_260() { - if (jj_3R_78()) return true; - return false; - } - - final private boolean jj_3_40() { - if (jj_3R_89()) return true; - return false; - } - - final private boolean jj_3R_129() { - Token xsp; - xsp = jj_scanpos; - if (jj_3_40()) { - jj_scanpos = xsp; - if (jj_3R_163()) { - jj_scanpos = xsp; - if (jj_3R_164()) { - jj_scanpos = xsp; - if (jj_3R_165()) { - jj_scanpos = xsp; - if (jj_3R_166()) { - jj_scanpos = xsp; - if (jj_3R_167()) { - jj_scanpos = xsp; - if (jj_3R_168()) { - jj_scanpos = xsp; - if (jj_3R_169()) { - jj_scanpos = xsp; - if (jj_3R_170()) { - jj_scanpos = xsp; - if (jj_3R_171()) { - jj_scanpos = xsp; - if (jj_3R_172()) { - jj_scanpos = xsp; - if (jj_3R_173()) { - jj_scanpos = xsp; - if (jj_3R_174()) { - jj_scanpos = xsp; - if (jj_3R_175()) { - jj_scanpos = xsp; - if (jj_3R_176()) { - jj_scanpos = xsp; - if (jj_3R_177()) - return true; - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - return false; - } - - final private boolean jj_3R_279() { - if (jj_3R_182()) return true; - return false; - } - - final private boolean jj_3R_291() { - if (jj_scan_token(LBRACKET)) return true; - if (jj_scan_token(RBRACKET)) return true; - return false; - } - - final private boolean jj_3R_278() { - Token xsp; - if (jj_3R_291()) return true; - while (true) { - xsp = jj_scanpos; - if (jj_3R_291()) { - jj_scanpos = xsp; - break; - } - } - if (jj_3R_147()) return true; - return false; - } - - final private boolean jj_3_37() { - if (jj_scan_token(LBRACKET)) return true; - if (jj_3R_56()) return true; - if (jj_scan_token(RBRACKET)) return true; - return false; - } - - final private boolean jj_3_39() { - Token xsp; - if (jj_3_37()) return true; - while (true) { - xsp = jj_scanpos; - if (jj_3_37()) { - jj_scanpos = xsp; - break; - } - } - while (true) { - xsp = jj_scanpos; - if (jj_3_38()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_259() { - Token xsp; - xsp = jj_scanpos; - if (jj_3_39()) { - jj_scanpos = xsp; - if (jj_3R_278()) return true; - } - return false; - } - - final private boolean jj_3R_262() { - if (jj_3R_109()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_279()) jj_scanpos = xsp; - return false; - } - - final private boolean jj_3R_232() { - if (jj_scan_token(COMMA)) return true; - if (jj_3R_56()) return true; - return false; - } - - final private boolean jj_3R_261() { - if (jj_3R_259()) return true; - return false; - } - - final private boolean jj_3R_123() { - if (jj_scan_token(NEW)) return true; - if (jj_3R_149()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_260()) jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_3R_261()) { - jj_scanpos = xsp; - if (jj_3R_262()) return true; - } - return false; - } - - final private boolean jj_3R_87() { - Token xsp; - xsp = jj_scanpos; - if (jj_3_36()) { - jj_scanpos = xsp; - if (jj_3R_123()) return true; - } - return false; - } - - final private boolean jj_3_36() { - if (jj_scan_token(NEW)) return true; - if (jj_3R_83()) return true; - if (jj_3R_259()) return true; - return false; - } - - final private boolean jj_3R_148() { - if (jj_3R_195()) return true; - return false; - } - - final private boolean jj_3R_195() { - if (jj_3R_56()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_232()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_109() { - if (jj_scan_token(LPAREN)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_148()) jj_scanpos = xsp; - if (jj_scan_token(RPAREN)) return true; - return false; - } - - final private boolean jj_3R_258() { - if (jj_scan_token(NULL)) return true; - return false; - } - - final private boolean jj_3R_257() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(56)) { - jj_scanpos = xsp; - if (jj_scan_token(25)) return true; - } - return false; - } - - final private boolean jj_3R_234() { - if (jj_3R_258()) return true; - return false; - } - - final private boolean jj_3R_233() { - if (jj_3R_257()) return true; - return false; - } - - final private boolean jj_3R_196() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(61)) { - jj_scanpos = xsp; - if (jj_scan_token(65)) { - jj_scanpos = xsp; - if (jj_scan_token(70)) { - jj_scanpos = xsp; - if (jj_scan_token(71)) { - jj_scanpos = xsp; - if (jj_3R_233()) { - jj_scanpos = xsp; - if (jj_3R_234()) return true; - } - } - } - } - } - return false; - } - - final private boolean jj_3R_152() { - if (jj_3R_196()) return true; - return false; - } - - final private boolean jj_3R_121() { - if (jj_3R_109()) return true; - return false; - } - - final private boolean jj_3R_120() { - if (jj_scan_token(DOT)) return true; - if (jj_scan_token(IDENTIFIER)) return true; - return false; - } - - final private boolean jj_3_33() { - if (jj_scan_token(DOT)) return true; - if (jj_scan_token(THIS)) return true; - return false; - } - - final private boolean jj_3R_119() { - if (jj_scan_token(LBRACKET)) return true; - if (jj_3R_56()) return true; - if (jj_scan_token(RBRACKET)) return true; - return false; - } - - final private boolean jj_3_32() { - if (jj_scan_token(DOT)) return true; - if (jj_scan_token(SUPER)) return true; - if (jj_scan_token(DOT)) return true; - return false; - } - - final private boolean jj_3_35() { - if (jj_3R_88()) return true; - return false; - } - - final private boolean jj_3_34() { - if (jj_scan_token(DOT)) return true; - if (jj_3R_87()) return true; - return false; - } - - final private boolean jj_3R_118() { - if (jj_scan_token(DOT)) return true; - if (jj_scan_token(THIS)) return true; - return false; - } - - final private boolean jj_3_31() { - if (jj_3R_86()) return true; - if (jj_scan_token(DOT)) return true; - if (jj_scan_token(CLASS)) return true; - return false; - } - - final private boolean jj_3R_117() { - if (jj_scan_token(DOT)) return true; - if (jj_scan_token(SUPER)) return true; - return false; - } - - final private boolean jj_3R_84() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_117()) { - jj_scanpos = xsp; - if (jj_3R_118()) { - jj_scanpos = xsp; - if (jj_3_34()) { - jj_scanpos = xsp; - if (jj_3_35()) { - jj_scanpos = xsp; - if (jj_3R_119()) { - jj_scanpos = xsp; - if (jj_3R_120()) { - jj_scanpos = xsp; - if (jj_3R_121()) return true; - } - } - } - } - } - } - return false; - } - - final private boolean jj_3R_85() { - if (jj_scan_token(IDENTIFIER)) return true; - if (jj_scan_token(DOT)) return true; - return false; - } - - final private boolean jj_3R_159() { - if (jj_3R_91()) return true; - return false; - } - - final private boolean jj_3_30() { - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_85()) { - jj_scanpos = xsp; - break; - } - } - if (jj_scan_token(THIS)) return true; - return false; - } - - final private boolean jj_3R_158() { - if (jj_3R_86()) return true; - if (jj_scan_token(DOT)) return true; - if (jj_scan_token(CLASS)) return true; - return false; - } - - final private boolean jj_3R_157() { - if (jj_3R_87()) return true; - return false; - } - - final private boolean jj_3R_156() { - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_56()) return true; - if (jj_scan_token(RPAREN)) return true; - return false; - } - - final private boolean jj_3_29() { - if (jj_3R_84()) return true; - return false; - } - - final private boolean jj_3R_155() { - if (jj_scan_token(SUPER)) return true; - if (jj_scan_token(DOT)) return true; - if (jj_scan_token(IDENTIFIER)) return true; - return false; - } - - final private boolean jj_3R_197() { - if (jj_scan_token(IDENTIFIER)) return true; - if (jj_scan_token(DOT)) return true; - return false; - } - - final private boolean jj_3R_154() { - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_197()) { - jj_scanpos = xsp; - break; - } - } - if (jj_scan_token(THIS)) return true; - return false; - } - - final private boolean jj_3R_124() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_153()) { - jj_scanpos = xsp; - if (jj_3R_154()) { - jj_scanpos = xsp; - if (jj_3R_155()) { - jj_scanpos = xsp; - if (jj_3R_156()) { - jj_scanpos = xsp; - if (jj_3R_157()) { - jj_scanpos = xsp; - if (jj_3R_158()) { - jj_scanpos = xsp; - if (jj_3R_159()) return true; - } - } - } - } - } - } - return false; - } - - final private boolean jj_3R_153() { - if (jj_3R_196()) return true; - return false; - } - - final private boolean jj_3R_88() { - if (jj_scan_token(DOT)) return true; - if (jj_3R_78()) return true; - if (jj_scan_token(IDENTIFIER)) return true; - return false; - } - - final private boolean jj_3R_280() { - if (jj_3R_293()) return true; - return false; - } - - final private boolean jj_3_28() { - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_83()) return true; - return false; - } - - final private boolean jj_3R_90() { - if (jj_3R_124()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3_29()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_319() { - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_72()) return true; - if (jj_scan_token(RPAREN)) return true; - if (jj_3R_313()) return true; - return false; - } - - final private boolean jj_3R_318() { - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_72()) return true; - if (jj_scan_token(RPAREN)) return true; - if (jj_3R_307()) return true; - return false; - } - - final private boolean jj_3R_317() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_318()) { - jj_scanpos = xsp; - if (jj_3R_319()) return true; - } - return false; - } - - final private boolean jj_3R_293() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(97)) { - jj_scanpos = xsp; - if (jj_scan_token(98)) return true; - } - return false; - } - - final private boolean jj_3_27() { - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_72()) return true; - if (jj_scan_token(LBRACKET)) return true; - return false; - } - - final private boolean jj_3R_266() { - if (jj_3R_90()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_280()) jj_scanpos = xsp; - return false; - } - - final private boolean jj_3R_116() { - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_72()) return true; - if (jj_scan_token(RPAREN)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(88)) { - jj_scanpos = xsp; - if (jj_scan_token(87)) { - jj_scanpos = xsp; - if (jj_scan_token(75)) { - jj_scanpos = xsp; - if (jj_scan_token(72)) { - jj_scanpos = xsp; - if (jj_scan_token(52)) { - jj_scanpos = xsp; - if (jj_scan_token(49)) { - jj_scanpos = xsp; - if (jj_scan_token(39)) { - jj_scanpos = xsp; - if (jj_3R_152()) return true; - } - } - } - } - } - } - } - return false; - } - - final private boolean jj_3R_115() { - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_72()) return true; - if (jj_scan_token(LBRACKET)) return true; - if (jj_scan_token(RBRACKET)) return true; - return false; - } - - final private boolean jj_3R_82() { - Token xsp; - xsp = jj_scanpos; - if (jj_3_26()) { - jj_scanpos = xsp; - if (jj_3R_115()) { - jj_scanpos = xsp; - if (jj_3R_116()) return true; - } - } - return false; - } - - final private boolean jj_3_26() { - if (jj_scan_token(LPAREN)) return true; - if (jj_3R_83()) return true; - return false; - } - - final private boolean jj_3_25() { - if (jj_3R_82()) return true; - return false; - } - - final private boolean jj_3_24() { - if (jj_3R_81()) return true; - return false; - } - - final private boolean jj_3R_316() { - if (jj_3R_266()) return true; - return false; - } - - final private boolean jj_3R_315() { - if (jj_3R_317()) return true; - return false; - } - - final private boolean jj_3R_314() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(88)) { - jj_scanpos = xsp; - if (jj_scan_token(87)) return true; - } - if (jj_3R_307()) return true; - return false; - } - - final private boolean jj_3R_313() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_314()) { - jj_scanpos = xsp; - if (jj_3R_315()) { - jj_scanpos = xsp; - if (jj_3R_316()) return true; - } - } - return false; - } - - final private boolean jj_3R_264() { - if (jj_scan_token(DECR)) return true; - if (jj_3R_90()) return true; - return false; - } - - final private boolean jj_3R_306() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(99)) { - jj_scanpos = xsp; - if (jj_scan_token(100)) return true; - } - if (jj_3R_305()) return true; - return false; - } - - final private boolean jj_3R_308() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(101)) { - jj_scanpos = xsp; - if (jj_scan_token(102)) { - jj_scanpos = xsp; - if (jj_scan_token(106)) return true; - } - } - if (jj_3R_307()) return true; - return false; - } - - final private boolean jj_3_23() { - if (jj_3R_80()) return true; - return false; - } - - final private boolean jj_3R_263() { - if (jj_scan_token(INCR)) return true; - if (jj_3R_90()) return true; - return false; - } - - final private boolean jj_3R_312() { - if (jj_3R_313()) return true; - return false; - } - - final private boolean jj_3_22() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(107)) { - jj_scanpos = xsp; - if (jj_3_23()) { - jj_scanpos = xsp; - if (jj_3_24()) return true; - } - } - if (jj_3R_304()) return true; - return false; - } - - final private boolean jj_3R_311() { - if (jj_3R_264()) return true; - return false; - } - - final private boolean jj_3R_310() { - if (jj_3R_263()) return true; - return false; - } - - final private boolean jj_3R_309() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(99)) { - jj_scanpos = xsp; - if (jj_scan_token(100)) return true; - } - if (jj_3R_307()) return true; - return false; - } - - final private boolean jj_3R_307() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_309()) { - jj_scanpos = xsp; - if (jj_3R_310()) { - jj_scanpos = xsp; - if (jj_3R_311()) { - jj_scanpos = xsp; - if (jj_3R_312()) return true; - } - } - } - return false; - } - - final private boolean jj_3R_303() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(86)) { - jj_scanpos = xsp; - if (jj_scan_token(122)) { - jj_scanpos = xsp; - if (jj_scan_token(92)) { - jj_scanpos = xsp; - if (jj_scan_token(93)) return true; - } - } - } - if (jj_3R_302()) return true; - return false; - } - - final private boolean jj_3R_301() { - if (jj_scan_token(INSTANCEOF)) return true; - if (jj_3R_72()) return true; - return false; - } - - final private boolean jj_3R_305() { - if (jj_3R_307()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_308()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_298() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(91)) { - jj_scanpos = xsp; - if (jj_scan_token(94)) return true; - } - if (jj_3R_297()) return true; - return false; - } - - final private boolean jj_3R_304() { - if (jj_3R_305()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_306()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_302() { - if (jj_3R_304()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3_22()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_288() { - if (jj_scan_token(BIT_AND)) return true; - if (jj_3R_287()) return true; - return false; - } - - final private boolean jj_3R_300() { - if (jj_3R_302()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_303()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_254() { - if (jj_scan_token(BIT_OR)) return true; - if (jj_3R_253()) return true; - return false; - } - - final private boolean jj_3R_297() { - if (jj_3R_300()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_301()) jj_scanpos = xsp; - return false; - } - - final private boolean jj_3R_274() { - if (jj_scan_token(XOR)) return true; - if (jj_3R_273()) return true; - return false; - } - - final private boolean jj_3R_230() { - if (jj_scan_token(SC_AND)) return true; - if (jj_3R_229()) return true; - return false; - } - - final private boolean jj_3R_287() { - if (jj_3R_297()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_298()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_190() { - if (jj_scan_token(SC_OR)) return true; - if (jj_3R_189()) return true; - return false; - } - - final private boolean jj_3R_273() { - if (jj_3R_287()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_288()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_142() { - if (jj_scan_token(HOOK)) return true; - if (jj_3R_56()) return true; - if (jj_scan_token(COLON)) return true; - if (jj_3R_56()) return true; - return false; - } - - final private boolean jj_3R_253() { - if (jj_3R_273()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_274()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_229() { - if (jj_3R_253()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_254()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_189() { - if (jj_3R_229()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_230()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_141() { - if (jj_3R_189()) return true; - Token xsp; - while (true) { - xsp = jj_scanpos; - if (jj_3R_190()) { - jj_scanpos = xsp; - break; - } - } - return false; - } - - final private boolean jj_3R_101() { - if (jj_3R_141()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_142()) jj_scanpos = xsp; - return false; - } - - final private boolean jj_3R_265() { - if (jj_3R_90()) return true; - if (jj_3R_79()) return true; - if (jj_3R_56()) return true; - return false; - } - - final private boolean jj_3R_79() { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(85)) { - jj_scanpos = xsp; - if (jj_scan_token(110)) { - jj_scanpos = xsp; - if (jj_scan_token(111)) { - jj_scanpos = xsp; - if (jj_scan_token(115)) { - jj_scanpos = xsp; - if (jj_scan_token(108)) { - jj_scanpos = xsp; - if (jj_scan_token(109)) { - jj_scanpos = xsp; - if (jj_scan_token(116)) { - jj_scanpos = xsp; - if (jj_scan_token(117)) { - jj_scanpos = xsp; - if (jj_scan_token(118)) { - jj_scanpos = xsp; - if (jj_scan_token(112)) { - jj_scanpos = xsp; - if (jj_scan_token(114)) { - jj_scanpos = xsp; - if (jj_scan_token(113)) - return true; - } - } - } - } - } - } - } - } - } - } - } - return false; - } - - final private boolean jj_3_21() { - if (jj_3R_79()) return true; - if (jj_3R_56()) return true; - return false; - } - - public JavaParserTokenManager token_source; - - JavaCharStream jj_input_stream; - - public Token token, jj_nt; - - private int jj_ntk; - - private Token jj_scanpos, jj_lastpos; - - private int jj_la; - - public boolean lookingAhead = false; - - private boolean jj_semLA; - - private final boolean parseMethodBody; - - public JavaParser(java.io.InputStream stream) { - this(stream, null, false); - } - - public JavaParser(java.io.InputStream stream, boolean parseMethodBody) { - this(stream, null, parseMethodBody); - } - - public JavaParser(java.io.InputStream stream, String encoding) { - this(stream, encoding, false); - } - - public JavaParser(java.io.InputStream stream, String encoding, boolean parseMethodBody) { - this.parseMethodBody = parseMethodBody; - try { - jj_input_stream = new JavaCharStream(stream, encoding, 1, 1); - } catch (java.io.UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - token_source = new JavaParserTokenManager(jj_input_stream); - token = new Token(); - jj_ntk = -1; - } - - public void ReInit(java.io.InputStream stream) { - ReInit(stream, null); - } - - public void ReInit(java.io.InputStream stream, String encoding) { - try { - jj_input_stream.ReInit(stream, encoding, 1, 1); - } catch (java.io.UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - token_source.ReInit(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jjtree.reset(); - } - - public JavaParser(java.io.Reader stream) { - this(stream, false); - } - - public JavaParser(java.io.Reader stream, boolean parseMethodBody) { - this.parseMethodBody=parseMethodBody; - jj_input_stream = new JavaCharStream(stream, 1, 1); - token_source = new JavaParserTokenManager(jj_input_stream); - token = new Token(); - jj_ntk = -1; - } - - public void ReInit(java.io.Reader stream) { - jj_input_stream.ReInit(stream, 1, 1); - token_source.ReInit(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jjtree.reset(); - } - - public JavaParser(JavaParserTokenManager tm, boolean parseMethodBody) { - this.parseMethodBody =parseMethodBody; - token_source = tm; - token = new Token(); - jj_ntk = -1; - } - - public void ReInit(JavaParserTokenManager tm) { - token_source = tm; - token = new Token(); - jj_ntk = -1; - jjtree.reset(); - } - - final private Token jj_consume_token(int kind) throws ParseException { - Token oldToken; - if ((oldToken = token).next != null) token = token.next; - else token = token.next = token_source.getNextToken(); - jj_ntk = -1; - if (token.kind == kind) { - return token; - } - token = oldToken; - throw generateParseException(); - } - - static private final class LookaheadSuccess extends java.lang.Error { - } - - final private LookaheadSuccess jj_ls = new LookaheadSuccess(); - - final private boolean jj_scan_token(int kind) { - if (jj_scanpos == jj_lastpos) { - jj_la--; - if (jj_scanpos.next == null) { - jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken(); - } else { - jj_lastpos = jj_scanpos = jj_scanpos.next; - } - } else { - jj_scanpos = jj_scanpos.next; - } - if (jj_scanpos.kind != kind) return true; - if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls; - return false; - } - - final public Token getNextToken() { - if (token.next != null) token = token.next; - else token = token.next = token_source.getNextToken(); - jj_ntk = -1; - return token; - } - - final public Token getToken(int index) { - Token t = lookingAhead ? jj_scanpos : token; - for (int i = 0; i < index; i++) { - if (t.next != null) t = t.next; - else t = t.next = token_source.getNextToken(); - } - return t; - } - - final private int jj_ntk() { - if ((jj_nt = token.next) == null) - return (jj_ntk = (token.next = token_source.getNextToken()).kind); - else - return (jj_ntk = jj_nt.kind); - } - - public ParseException generateParseException() { - Token errortok = token.next; - int line = errortok.beginLine, column = errortok.beginColumn; - String mess = (errortok.kind == 0) ? tokenImage[0] : errortok.image; - return new ParseException("Unable to parse Java code near token: " + mess, line, column); - } - - final public void enable_tracing() { - } - - final public void disable_tracing() { - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserConstants.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserConstants.java deleted file mode 100644 index d7c2d2c..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserConstants.java +++ /dev/null @@ -1,404 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JJTree&JavaCC: Do not edit this line. JavaParserConstants.java */ - -package jaxx.compiler.java.parser; - -public interface JavaParserConstants { - - int EOF = 0; - - int WHITE_SPACE = 3; - - int SINGLE_LINE_COMMENT = 4; - - int FORMAL_COMMENT = 5; - - int MULTI_LINE_COMMENT = 6; - - int ABSTRACT = 8; - - int ASSERT = 9; - - int BOOLEAN = 10; - - int BREAK = 11; - - int BYTE = 12; - - int CASE = 13; - - int CATCH = 14; - - int CHAR = 15; - - int CLASS = 16; - - int CONST = 17; - - int CONTINUE = 18; - - int _DEFAULT = 19; - - int DO = 20; - - int DOUBLE = 21; - - int ELSE = 22; - - int ENUM = 23; - - int EXTENDS = 24; - - int FALSE = 25; - - int FINAL = 26; - - int FINALLY = 27; - - int FLOAT = 28; - - int FOR = 29; - - int GOTO = 30; - - int IF = 31; - - int IMPLEMENTS = 32; - - int IMPORT = 33; - - int INSTANCEOF = 34; - - int INT = 35; - - int INTERFACE = 36; - - int LONG = 37; - - int NATIVE = 38; - - int NEW = 39; - - int NULL = 40; - - int PACKAGE = 41; - - int PRIVATE = 42; - - int PROTECTED = 43; - - int PUBLIC = 44; - - int RETURN = 45; - - int SHORT = 46; - - int STATIC = 47; - - int STRICTFP = 48; - - int SUPER = 49; - - int SWITCH = 50; - - int SYNCHRONIZED = 51; - - int THIS = 52; - - int THROW = 53; - - int THROWS = 54; - - int TRANSIENT = 55; - - int TRUE = 56; - - int TRY = 57; - - int VOID = 58; - - int VOLATILE = 59; - - int WHILE = 60; - - int INTEGER_LITERAL = 61; - - int DECIMAL_LITERAL = 62; - - int HEX_LITERAL = 63; - - int OCTAL_LITERAL = 64; - - int FLOATING_POINT_LITERAL = 65; - - int DECIMAL_FLOATING_POINT_LITERAL = 66; - - int DECIMAL_EXPONENT = 67; - - int HEXADECIMAL_FLOATING_POINT_LITERAL = 68; - - int HEXADECIMAL_EXPONENT = 69; - - int CHARACTER_LITERAL = 70; - - int STRING_LITERAL = 71; - - int IDENTIFIER = 72; - - int LETTER = 73; - - int PART_LETTER = 74; - - int LPAREN = 75; - - int RPAREN = 76; - - int LBRACE = 77; - - int RBRACE = 78; - - int LBRACKET = 79; - - int RBRACKET = 80; - - int SEMICOLON = 81; - - int COMMA = 82; - - int DOT = 83; - - int AT = 84; - - int ASSIGN = 85; - - int LT = 86; - - int BANG = 87; - - int TILDE = 88; - - int HOOK = 89; - - int COLON = 90; - - int EQ = 91; - - int LE = 92; - - int GE = 93; - - int NE = 94; - - int SC_OR = 95; - - int SC_AND = 96; - - int INCR = 97; - - int DECR = 98; - - int PLUS = 99; - - int MINUS = 100; - - int STAR = 101; - - int SLASH = 102; - - int BIT_AND = 103; - - int BIT_OR = 104; - - int XOR = 105; - - int REM = 106; - - int LSHIFT = 107; - - int PLUSASSIGN = 108; - - int MINUSASSIGN = 109; - - int STARASSIGN = 110; - - int SLASHASSIGN = 111; - - int ANDASSIGN = 112; - - int ORASSIGN = 113; - - int XORASSIGN = 114; - - int REMASSIGN = 115; - - int LSHIFTASSIGN = 116; - - int RSIGNEDSHIFTASSIGN = 117; - - int RUNSIGNEDSHIFTASSIGN = 118; - - int ELLIPSIS = 119; - - int RUNSIGNEDSHIFT = 120; - - int RSIGNEDSHIFT = 121; - - int GT = 122; - - int STUFF_TO_IGNORE = 124; - - int DEFAULT = 0; - - int IN_FORMAL_COMMENT = 1; - - int IN_MULTI_LINE_COMMENT = 2; - - String[] tokenImage = { - "<EOF>", - "<token of kind 1>", - "\"/*\"", - "<WHITE_SPACE>", - "<SINGLE_LINE_COMMENT>", - "\"*/\"", - "\"*/\"", - "<token of kind 7>", - "\"abstract\"", - "\"assert\"", - "\"boolean\"", - "\"break\"", - "\"byte\"", - "\"case\"", - "\"catch\"", - "\"char\"", - "\"class\"", - "\"const\"", - "\"continue\"", - "\"default\"", - "\"do\"", - "\"double\"", - "\"else\"", - "\"enum\"", - "\"extends\"", - "\"false\"", - "\"final\"", - "\"finally\"", - "\"float\"", - "\"for\"", - "\"goto\"", - "\"if\"", - "\"implements\"", - "\"import\"", - "\"instanceof\"", - "\"int\"", - "\"interface\"", - "\"long\"", - "\"native\"", - "\"new\"", - "\"null\"", - "\"package\"", - "\"private\"", - "\"protected\"", - "\"public\"", - "\"return\"", - "\"short\"", - "\"static\"", - "\"strictfp\"", - "\"super\"", - "\"switch\"", - "\"synchronized\"", - "\"this\"", - "\"throw\"", - "\"throws\"", - "\"transient\"", - "\"true\"", - "\"try\"", - "\"void\"", - "\"volatile\"", - "\"while\"", - "<INTEGER_LITERAL>", - "<DECIMAL_LITERAL>", - "<HEX_LITERAL>", - "<OCTAL_LITERAL>", - "<FLOATING_POINT_LITERAL>", - "<DECIMAL_FLOATING_POINT_LITERAL>", - "<DECIMAL_EXPONENT>", - "<HEXADECIMAL_FLOATING_POINT_LITERAL>", - "<HEXADECIMAL_EXPONENT>", - "<CHARACTER_LITERAL>", - "<STRING_LITERAL>", - "<IDENTIFIER>", - "<LETTER>", - "<PART_LETTER>", - "\"(\"", - "\")\"", - "\"{\"", - "\"}\"", - "\"[\"", - "\"]\"", - "\";\"", - "\",\"", - "\".\"", - "\"@\"", - "\"=\"", - "\"<\"", - "\"!\"", - "\"~\"", - "\"?\"", - "\":\"", - "\"==\"", - "\"<=\"", - "\">=\"", - "\"!=\"", - "\"||\"", - "\"&&\"", - "\"++\"", - "\"--\"", - "\"+\"", - "\"-\"", - "\"*\"", - "\"/\"", - "\"&\"", - "\"|\"", - "\"^\"", - "\"%\"", - "\"<<\"", - "\"+=\"", - "\"-=\"", - "\"*=\"", - "\"/=\"", - "\"&=\"", - "\"|=\"", - "\"^=\"", - "\"%=\"", - "\"<<=\"", - "\">>=\"", - "\">>>=\"", - "\"...\"", - "\">>>\"", - "\">>\"", - "\">\"", - "\"\\u001a\"", - "<STUFF_TO_IGNORE>" - }; - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserTokenManager.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserTokenManager.java deleted file mode 100644 index 2384639..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserTokenManager.java +++ /dev/null @@ -1,2156 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JJTree&JavaCC: Do not edit this line. JavaParserTokenManager.java */ - -package jaxx.compiler.java.parser; - -import java.io.IOException; -import java.io.PrintStream; - -public class JavaParserTokenManager implements JavaParserConstants { - public PrintStream debugStream = System.out; - - public void setDebugStream(PrintStream ds) { - debugStream = ds; - } - - private int jjStopStringLiteralDfa_0(int pos, long active0, long active1) { - switch (pos) { - case 0: - if ((active0 & 0x4L) != 0L || (active1 & 0x804000000000L) != 0L) - return 48; - if ((active1 & 0x80000000080000L) != 0L) - return 5; - if ((active0 & 0x1fffffffffffff00L) != 0L) { - jjmatchedKind = 72; - return 29; - } - return -1; - case 1: - if ((active0 & 0x4L) != 0L) - return 46; - if ((active0 & 0x1fffffff7fcfff00L) != 0L) { - if (jjmatchedPos != 1) { - jjmatchedKind = 72; - jjmatchedPos = 1; - } - return 29; - } - if ((active0 & 0x80300000L) != 0L) - return 29; - return -1; - case 2: - if ((active0 & 0x1dffff675fefff00L) != 0L) { - if (jjmatchedPos != 2) { - jjmatchedKind = 72; - jjmatchedPos = 2; - } - return 29; - } - if ((active0 & 0x200009820000000L) != 0L) - return 29; - return -1; - case 3: - if ((active0 & 0x18effe571f2f4f00L) != 0L) { - jjmatchedKind = 72; - jjmatchedPos = 3; - return 29; - } - if ((active0 & 0x510012040c0b000L) != 0L) - return 29; - return -1; - case 4: - if ((active0 & 0x88dbe57012c0700L) != 0L) { - if (jjmatchedPos != 4) { - jjmatchedKind = 72; - jjmatchedPos = 4; - } - return 29; - } - if ((active0 & 0x106240001e034800L) != 0L) - return 29; - return -1; - case 5: - if ((active0 & 0x8890e15090c0500L) != 0L) { - jjmatchedKind = 72; - jjmatchedPos = 5; - return 29; - } - if ((active0 & 0x44b04200200200L) != 0L) - return 29; - return -1; - case 6: - if ((active0 & 0x889081500040100L) != 0L) { - jjmatchedKind = 72; - jjmatchedPos = 6; - return 29; - } - if ((active0 & 0x60009080400L) != 0L) - return 29; - return -1; - case 7: - if ((active0 & 0x801000000040100L) != 0L) - return 29; - if ((active0 & 0x88081500000000L) != 0L) { - jjmatchedKind = 72; - jjmatchedPos = 7; - return 29; - } - return -1; - case 8: - if ((active0 & 0x8000500000000L) != 0L) { - jjmatchedKind = 72; - jjmatchedPos = 8; - return 29; - } - if ((active0 & 0x80081000000000L) != 0L) - return 29; - return -1; - case 9: - if ((active0 & 0x8000000000000L) != 0L) { - jjmatchedKind = 72; - jjmatchedPos = 9; - return 29; - } - if ((active0 & 0x500000000L) != 0L) - return 29; - return -1; - case 10: - if ((active0 & 0x8000000000000L) != 0L) { - jjmatchedKind = 72; - jjmatchedPos = 10; - return 29; - } - return -1; - default: - return -1; - } - } - - private int jjStartNfa_0(int pos, long active0, long active1) { - return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0, active1), pos + 1); - } - - private int jjStopAtPos(int pos, int kind) { - jjmatchedKind = kind; - jjmatchedPos = pos; - return pos + 1; - } - - private int jjStartNfaWithStates_0(int pos, int kind, int state) { - jjmatchedKind = kind; - jjmatchedPos = pos; - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - return pos + 1; - } - return jjMoveNfa_0(state, pos + 1); - } - - private int jjMoveStringLiteralDfa0_0() { - switch (curChar) { - case 26: - return jjStopAtPos(0, 123); - case 33: - jjmatchedKind = 87; - return jjMoveStringLiteralDfa1_0(0x0L, 0x40000000L); - case 37: - jjmatchedKind = 106; - return jjMoveStringLiteralDfa1_0(0x0L, 0x8000000000000L); - case 38: - jjmatchedKind = 103; - return jjMoveStringLiteralDfa1_0(0x0L, 0x1000100000000L); - case 40: - return jjStopAtPos(0, 75); - case 41: - return jjStopAtPos(0, 76); - case 42: - jjmatchedKind = 101; - return jjMoveStringLiteralDfa1_0(0x0L, 0x400000000000L); - case 43: - jjmatchedKind = 99; - return jjMoveStringLiteralDfa1_0(0x0L, 0x100200000000L); - case 44: - return jjStopAtPos(0, 82); - case 45: - jjmatchedKind = 100; - return jjMoveStringLiteralDfa1_0(0x0L, 0x200400000000L); - case 46: - jjmatchedKind = 83; - return jjMoveStringLiteralDfa1_0(0x0L, 0x80000000000000L); - case 47: - jjmatchedKind = 102; - return jjMoveStringLiteralDfa1_0(0x4L, 0x800000000000L); - case 58: - return jjStopAtPos(0, 90); - case 59: - return jjStopAtPos(0, 81); - case 60: - jjmatchedKind = 86; - return jjMoveStringLiteralDfa1_0(0x0L, 0x10080010000000L); - case 61: - jjmatchedKind = 85; - return jjMoveStringLiteralDfa1_0(0x0L, 0x8000000L); - case 62: - jjmatchedKind = 122; - return jjMoveStringLiteralDfa1_0(0x0L, 0x360000020000000L); - case 63: - return jjStopAtPos(0, 89); - case 64: - return jjStopAtPos(0, 84); - case 91: - return jjStopAtPos(0, 79); - case 93: - return jjStopAtPos(0, 80); - case 94: - jjmatchedKind = 105; - return jjMoveStringLiteralDfa1_0(0x0L, 0x4000000000000L); - case 97: - return jjMoveStringLiteralDfa1_0(0x300L, 0x0L); - case 98: - return jjMoveStringLiteralDfa1_0(0x1c00L, 0x0L); - case 99: - return jjMoveStringLiteralDfa1_0(0x7e000L, 0x0L); - case 100: - return jjMoveStringLiteralDfa1_0(0x380000L, 0x0L); - case 101: - return jjMoveStringLiteralDfa1_0(0x1c00000L, 0x0L); - case 102: - return jjMoveStringLiteralDfa1_0(0x3e000000L, 0x0L); - case 103: - return jjMoveStringLiteralDfa1_0(0x40000000L, 0x0L); - case 105: - return jjMoveStringLiteralDfa1_0(0x1f80000000L, 0x0L); - case 108: - return jjMoveStringLiteralDfa1_0(0x2000000000L, 0x0L); - case 110: - return jjMoveStringLiteralDfa1_0(0x1c000000000L, 0x0L); - case 112: - return jjMoveStringLiteralDfa1_0(0x1e0000000000L, 0x0L); - case 114: - return jjMoveStringLiteralDfa1_0(0x200000000000L, 0x0L); - case 115: - return jjMoveStringLiteralDfa1_0(0xfc00000000000L, 0x0L); - case 116: - return jjMoveStringLiteralDfa1_0(0x3f0000000000000L, 0x0L); - case 118: - return jjMoveStringLiteralDfa1_0(0xc00000000000000L, 0x0L); - case 119: - return jjMoveStringLiteralDfa1_0(0x1000000000000000L, 0x0L); - case 123: - return jjStopAtPos(0, 77); - case 124: - jjmatchedKind = 104; - return jjMoveStringLiteralDfa1_0(0x0L, 0x2000080000000L); - case 125: - return jjStopAtPos(0, 78); - case 126: - return jjStopAtPos(0, 88); - default: - return jjMoveNfa_0(1, 0); - } - } - - private int jjMoveStringLiteralDfa1_0(long active0, long active1) { - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - jjStopStringLiteralDfa_0(0, active0, active1); - return 1; - } - switch (curChar) { - case 38: - if ((active1 & 0x100000000L) != 0L) - return jjStopAtPos(1, 96); - break; - case 42: - if ((active0 & 0x4L) != 0L) - return jjStartNfaWithStates_0(1, 2, 46); - break; - case 43: - if ((active1 & 0x200000000L) != 0L) - return jjStopAtPos(1, 97); - break; - case 45: - if ((active1 & 0x400000000L) != 0L) - return jjStopAtPos(1, 98); - break; - case 46: - return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x80000000000000L); - case 60: - if ((active1 & 0x80000000000L) != 0L) { - jjmatchedKind = 107; - jjmatchedPos = 1; - } - return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x10000000000000L); - case 61: - if ((active1 & 0x8000000L) != 0L) - return jjStopAtPos(1, 91); - else if ((active1 & 0x10000000L) != 0L) - return jjStopAtPos(1, 92); - else if ((active1 & 0x20000000L) != 0L) - return jjStopAtPos(1, 93); - else if ((active1 & 0x40000000L) != 0L) - return jjStopAtPos(1, 94); - else if ((active1 & 0x100000000000L) != 0L) - return jjStopAtPos(1, 108); - else if ((active1 & 0x200000000000L) != 0L) - return jjStopAtPos(1, 109); - else if ((active1 & 0x400000000000L) != 0L) - return jjStopAtPos(1, 110); - else if ((active1 & 0x800000000000L) != 0L) - return jjStopAtPos(1, 111); - else if ((active1 & 0x1000000000000L) != 0L) - return jjStopAtPos(1, 112); - else if ((active1 & 0x2000000000000L) != 0L) - return jjStopAtPos(1, 113); - else if ((active1 & 0x4000000000000L) != 0L) - return jjStopAtPos(1, 114); - else if ((active1 & 0x8000000000000L) != 0L) - return jjStopAtPos(1, 115); - break; - case 62: - if ((active1 & 0x200000000000000L) != 0L) { - jjmatchedKind = 121; - jjmatchedPos = 1; - } - return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x160000000000000L); - case 97: - return jjMoveStringLiteralDfa2_0(active0, 0x24002006000L, active1, 0L); - case 98: - return jjMoveStringLiteralDfa2_0(active0, 0x100L, active1, 0L); - case 101: - return jjMoveStringLiteralDfa2_0(active0, 0x208000080000L, active1, 0L); - case 102: - if ((active0 & 0x80000000L) != 0L) - return jjStartNfaWithStates_0(1, 31, 29); - break; - case 104: - return jjMoveStringLiteralDfa2_0(active0, 0x1070400000008000L, active1, 0L); - case 105: - return jjMoveStringLiteralDfa2_0(active0, 0xc000000L, active1, 0L); - case 108: - return jjMoveStringLiteralDfa2_0(active0, 0x10410000L, active1, 0L); - case 109: - return jjMoveStringLiteralDfa2_0(active0, 0x300000000L, active1, 0L); - case 110: - return jjMoveStringLiteralDfa2_0(active0, 0x1c00800000L, active1, 0L); - case 111: - if ((active0 & 0x100000L) != 0L) { - jjmatchedKind = 20; - jjmatchedPos = 1; - } - return jjMoveStringLiteralDfa2_0(active0, 0xc00002060260400L, active1, 0L); - case 114: - return jjMoveStringLiteralDfa2_0(active0, 0x3800c0000000800L, active1, 0L); - case 115: - return jjMoveStringLiteralDfa2_0(active0, 0x200L, active1, 0L); - case 116: - return jjMoveStringLiteralDfa2_0(active0, 0x1800000000000L, active1, 0L); - case 117: - return jjMoveStringLiteralDfa2_0(active0, 0x2110000000000L, active1, 0L); - case 119: - return jjMoveStringLiteralDfa2_0(active0, 0x4000000000000L, active1, 0L); - case 120: - return jjMoveStringLiteralDfa2_0(active0, 0x1000000L, active1, 0L); - case 121: - return jjMoveStringLiteralDfa2_0(active0, 0x8000000001000L, active1, 0L); - case 124: - if ((active1 & 0x80000000L) != 0L) - return jjStopAtPos(1, 95); - break; - default: - break; - } - return jjStartNfa_0(0, active0, active1); - } - - private int jjMoveStringLiteralDfa2_0(long old0, long active0, long old1, long active1) { - if (((active0 &= old0) | (active1 &= old1)) == 0L) - return jjStartNfa_0(0, old0, old1); - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - jjStopStringLiteralDfa_0(1, active0, active1); - return 2; - } - switch (curChar) { - case 46: - if ((active1 & 0x80000000000000L) != 0L) - return jjStopAtPos(2, 119); - break; - case 61: - if ((active1 & 0x10000000000000L) != 0L) - return jjStopAtPos(2, 116); - else if ((active1 & 0x20000000000000L) != 0L) - return jjStopAtPos(2, 117); - break; - case 62: - if ((active1 & 0x100000000000000L) != 0L) { - jjmatchedKind = 120; - jjmatchedPos = 2; - } - return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x40000000000000L); - case 97: - return jjMoveStringLiteralDfa3_0(active0, 0x80800000018000L, active1, 0L); - case 98: - return jjMoveStringLiteralDfa3_0(active0, 0x100000000000L, active1, 0L); - case 99: - return jjMoveStringLiteralDfa3_0(active0, 0x20000000000L, active1, 0L); - case 101: - return jjMoveStringLiteralDfa3_0(active0, 0x800L, active1, 0L); - case 102: - return jjMoveStringLiteralDfa3_0(active0, 0x80000L, active1, 0L); - case 105: - return jjMoveStringLiteralDfa3_0(active0, 0x1414040000000000L, active1, 0L); - case 108: - return jjMoveStringLiteralDfa3_0(active0, 0x800010002000000L, active1, 0L); - case 110: - return jjMoveStringLiteralDfa3_0(active0, 0x800200c060000L, active1, 0L); - case 111: - return jjMoveStringLiteralDfa3_0(active0, 0x480010000400L, active1, 0L); - case 112: - return jjMoveStringLiteralDfa3_0(active0, 0x2000300000000L, active1, 0L); - case 114: - if ((active0 & 0x20000000L) != 0L) - return jjStartNfaWithStates_0(2, 29, 29); - return jjMoveStringLiteralDfa3_0(active0, 0x61000000000000L, active1, 0L); - case 115: - return jjMoveStringLiteralDfa3_0(active0, 0x400402300L, active1, 0L); - case 116: - if ((active0 & 0x800000000L) != 0L) { - jjmatchedKind = 35; - jjmatchedPos = 2; - } - return jjMoveStringLiteralDfa3_0(active0, 0x205041005000L, active1, 0L); - case 117: - return jjMoveStringLiteralDfa3_0(active0, 0x100000000a00000L, active1, 0L); - case 119: - if ((active0 & 0x8000000000L) != 0L) - return jjStartNfaWithStates_0(2, 39, 29); - break; - case 121: - if ((active0 & 0x200000000000000L) != 0L) - return jjStartNfaWithStates_0(2, 57, 29); - break; - default: - break; - } - return jjStartNfa_0(1, active0, active1); - } - - private int jjMoveStringLiteralDfa3_0(long old0, long active0, long old1, long active1) { - if (((active0 &= old0) | (active1 &= old1)) == 0L) - return jjStartNfa_0(1, old0, old1); - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - jjStopStringLiteralDfa_0(2, active0, active1); - return 3; - } - switch (curChar) { - case 61: - if ((active1 & 0x40000000000000L) != 0L) - return jjStopAtPos(3, 118); - break; - case 97: - return jjMoveStringLiteralDfa4_0(active0, 0x80000001c080800L, active1, 0L); - case 98: - return jjMoveStringLiteralDfa4_0(active0, 0x200000L, active1, 0L); - case 99: - return jjMoveStringLiteralDfa4_0(active0, 0x8000000004000L, active1, 0L); - case 100: - if ((active0 & 0x400000000000000L) != 0L) - return jjStartNfaWithStates_0(3, 58, 29); - break; - case 101: - if ((active0 & 0x1000L) != 0L) - return jjStartNfaWithStates_0(3, 12, 29); - else if ((active0 & 0x2000L) != 0L) - return jjStartNfaWithStates_0(3, 13, 29); - else if ((active0 & 0x400000L) != 0L) - return jjStartNfaWithStates_0(3, 22, 29); - else if ((active0 & 0x100000000000000L) != 0L) - return jjStartNfaWithStates_0(3, 56, 29); - return jjMoveStringLiteralDfa4_0(active0, 0x2001001000200L, active1, 0L); - case 103: - if ((active0 & 0x2000000000L) != 0L) - return jjStartNfaWithStates_0(3, 37, 29); - break; - case 105: - return jjMoveStringLiteralDfa4_0(active0, 0x1004000000000L, active1, 0L); - case 107: - return jjMoveStringLiteralDfa4_0(active0, 0x20000000000L, active1, 0L); - case 108: - if ((active0 & 0x10000000000L) != 0L) - return jjStartNfaWithStates_0(3, 40, 29); - return jjMoveStringLiteralDfa4_0(active0, 0x1000100100000400L, active1, 0L); - case 109: - if ((active0 & 0x800000L) != 0L) - return jjStartNfaWithStates_0(3, 23, 29); - break; - case 110: - return jjMoveStringLiteralDfa4_0(active0, 0x80000000000000L, active1, 0L); - case 111: - if ((active0 & 0x40000000L) != 0L) - return jjStartNfaWithStates_0(3, 30, 29); - return jjMoveStringLiteralDfa4_0(active0, 0x60000200000000L, active1, 0L); - case 114: - if ((active0 & 0x8000L) != 0L) - return jjStartNfaWithStates_0(3, 15, 29); - return jjMoveStringLiteralDfa4_0(active0, 0x400000000000L, active1, 0L); - case 115: - if ((active0 & 0x10000000000000L) != 0L) - return jjStartNfaWithStates_0(3, 52, 29); - return jjMoveStringLiteralDfa4_0(active0, 0x2030000L, active1, 0L); - case 116: - return jjMoveStringLiteralDfa4_0(active0, 0x4880400040100L, active1, 0L); - case 117: - return jjMoveStringLiteralDfa4_0(active0, 0x200000000000L, active1, 0L); - case 118: - return jjMoveStringLiteralDfa4_0(active0, 0x40000000000L, active1, 0L); - default: - break; - } - return jjStartNfa_0(2, active0, active1); - } - - private int jjMoveStringLiteralDfa4_0(long old0, long active0, long old1, long active1) { - if (((active0 &= old0) | (active1 &= old1)) == 0L) - return jjStartNfa_0(2, old0, old1); - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - jjStopStringLiteralDfa_0(3, active0, 0L); - return 4; - } - switch (curChar) { - case 97: - return jjMoveStringLiteralDfa5_0(active0, 0x60400000000L); - case 99: - return jjMoveStringLiteralDfa5_0(active0, 0x5000000000000L); - case 101: - if ((active0 & 0x2000000L) != 0L) - return jjStartNfaWithStates_0(4, 25, 29); - else if ((active0 & 0x1000000000000000L) != 0L) - return jjStartNfaWithStates_0(4, 60, 29); - return jjMoveStringLiteralDfa5_0(active0, 0x80100000400L); - case 104: - if ((active0 & 0x4000L) != 0L) - return jjStartNfaWithStates_0(4, 14, 29); - return jjMoveStringLiteralDfa5_0(active0, 0x8000000000000L); - case 105: - return jjMoveStringLiteralDfa5_0(active0, 0x900000040000L); - case 107: - if ((active0 & 0x800L) != 0L) - return jjStartNfaWithStates_0(4, 11, 29); - break; - case 108: - if ((active0 & 0x4000000L) != 0L) { - jjmatchedKind = 26; - jjmatchedPos = 4; - } - return jjMoveStringLiteralDfa5_0(active0, 0x8200000L); - case 110: - return jjMoveStringLiteralDfa5_0(active0, 0x1000000L); - case 114: - if ((active0 & 0x2000000000000L) != 0L) - return jjStartNfaWithStates_0(4, 49, 29); - return jjMoveStringLiteralDfa5_0(active0, 0x201200000300L); - case 115: - if ((active0 & 0x10000L) != 0L) - return jjStartNfaWithStates_0(4, 16, 29); - return jjMoveStringLiteralDfa5_0(active0, 0x80000000000000L); - case 116: - if ((active0 & 0x20000L) != 0L) - return jjStartNfaWithStates_0(4, 17, 29); - else if ((active0 & 0x10000000L) != 0L) - return jjStartNfaWithStates_0(4, 28, 29); - else if ((active0 & 0x400000000000L) != 0L) - return jjStartNfaWithStates_0(4, 46, 29); - return jjMoveStringLiteralDfa5_0(active0, 0x800000000000000L); - case 117: - return jjMoveStringLiteralDfa5_0(active0, 0x80000L); - case 118: - return jjMoveStringLiteralDfa5_0(active0, 0x4000000000L); - case 119: - if ((active0 & 0x20000000000000L) != 0L) { - jjmatchedKind = 53; - jjmatchedPos = 4; - } - return jjMoveStringLiteralDfa5_0(active0, 0x40000000000000L); - default: - break; - } - return jjStartNfa_0(3, active0, 0L); - } - - private int jjMoveStringLiteralDfa5_0(long old0, long active0) { - if ((active0 &= old0) == 0L) - return jjStartNfa_0(3, old0, 0L); - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - jjStopStringLiteralDfa_0(4, active0, 0L); - return 5; - } - switch (curChar) { - case 97: - return jjMoveStringLiteralDfa6_0(active0, 0x500L); - case 99: - if ((active0 & 0x100000000000L) != 0L) - return jjStartNfaWithStates_0(5, 44, 29); - else if ((active0 & 0x800000000000L) != 0L) - return jjStartNfaWithStates_0(5, 47, 29); - return jjMoveStringLiteralDfa6_0(active0, 0x80000000000L); - case 100: - return jjMoveStringLiteralDfa6_0(active0, 0x1000000L); - case 101: - if ((active0 & 0x200000L) != 0L) - return jjStartNfaWithStates_0(5, 21, 29); - else if ((active0 & 0x4000000000L) != 0L) - return jjStartNfaWithStates_0(5, 38, 29); - break; - case 102: - return jjMoveStringLiteralDfa6_0(active0, 0x1000000000L); - case 103: - return jjMoveStringLiteralDfa6_0(active0, 0x20000000000L); - case 104: - if ((active0 & 0x4000000000000L) != 0L) - return jjStartNfaWithStates_0(5, 50, 29); - break; - case 105: - return jjMoveStringLiteralDfa6_0(active0, 0x880000000000000L); - case 108: - return jjMoveStringLiteralDfa6_0(active0, 0x8080000L); - case 109: - return jjMoveStringLiteralDfa6_0(active0, 0x100000000L); - case 110: - if ((active0 & 0x200000000000L) != 0L) - return jjStartNfaWithStates_0(5, 45, 29); - return jjMoveStringLiteralDfa6_0(active0, 0x400040000L); - case 114: - return jjMoveStringLiteralDfa6_0(active0, 0x8000000000000L); - case 115: - if ((active0 & 0x40000000000000L) != 0L) - return jjStartNfaWithStates_0(5, 54, 29); - break; - case 116: - if ((active0 & 0x200L) != 0L) - return jjStartNfaWithStates_0(5, 9, 29); - else if ((active0 & 0x200000000L) != 0L) - return jjStartNfaWithStates_0(5, 33, 29); - return jjMoveStringLiteralDfa6_0(active0, 0x1040000000000L); - default: - break; - } - return jjStartNfa_0(4, active0, 0L); - } - - private int jjMoveStringLiteralDfa6_0(long old0, long active0) { - if ((active0 &= old0) == 0L) - return jjStartNfa_0(4, old0, 0L); - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - jjStopStringLiteralDfa_0(5, active0, 0L); - return 6; - } - switch (curChar) { - case 97: - return jjMoveStringLiteralDfa7_0(active0, 0x1000000000L); - case 99: - return jjMoveStringLiteralDfa7_0(active0, 0x400000100L); - case 101: - if ((active0 & 0x20000000000L) != 0L) - return jjStartNfaWithStates_0(6, 41, 29); - else if ((active0 & 0x40000000000L) != 0L) - return jjStartNfaWithStates_0(6, 42, 29); - return jjMoveStringLiteralDfa7_0(active0, 0x80000100000000L); - case 102: - return jjMoveStringLiteralDfa7_0(active0, 0x1000000000000L); - case 108: - return jjMoveStringLiteralDfa7_0(active0, 0x800000000000000L); - case 110: - if ((active0 & 0x400L) != 0L) - return jjStartNfaWithStates_0(6, 10, 29); - break; - case 111: - return jjMoveStringLiteralDfa7_0(active0, 0x8000000000000L); - case 115: - if ((active0 & 0x1000000L) != 0L) - return jjStartNfaWithStates_0(6, 24, 29); - break; - case 116: - if ((active0 & 0x80000L) != 0L) - return jjStartNfaWithStates_0(6, 19, 29); - return jjMoveStringLiteralDfa7_0(active0, 0x80000000000L); - case 117: - return jjMoveStringLiteralDfa7_0(active0, 0x40000L); - case 121: - if ((active0 & 0x8000000L) != 0L) - return jjStartNfaWithStates_0(6, 27, 29); - break; - default: - break; - } - return jjStartNfa_0(5, active0, 0L); - } - - private int jjMoveStringLiteralDfa7_0(long old0, long active0) { - if ((active0 &= old0) == 0L) - return jjStartNfa_0(5, old0, 0L); - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - jjStopStringLiteralDfa_0(6, active0, 0L); - return 7; - } - switch (curChar) { - case 99: - return jjMoveStringLiteralDfa8_0(active0, 0x1000000000L); - case 101: - if ((active0 & 0x40000L) != 0L) - return jjStartNfaWithStates_0(7, 18, 29); - else if ((active0 & 0x800000000000000L) != 0L) - return jjStartNfaWithStates_0(7, 59, 29); - return jjMoveStringLiteralDfa8_0(active0, 0x80400000000L); - case 110: - return jjMoveStringLiteralDfa8_0(active0, 0x88000100000000L); - case 112: - if ((active0 & 0x1000000000000L) != 0L) - return jjStartNfaWithStates_0(7, 48, 29); - break; - case 116: - if ((active0 & 0x100L) != 0L) - return jjStartNfaWithStates_0(7, 8, 29); - break; - default: - break; - } - return jjStartNfa_0(6, active0, 0L); - } - - private int jjMoveStringLiteralDfa8_0(long old0, long active0) { - if ((active0 &= old0) == 0L) - return jjStartNfa_0(6, old0, 0L); - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - jjStopStringLiteralDfa_0(7, active0, 0L); - return 8; - } - switch (curChar) { - case 100: - if ((active0 & 0x80000000000L) != 0L) - return jjStartNfaWithStates_0(8, 43, 29); - break; - case 101: - if ((active0 & 0x1000000000L) != 0L) - return jjStartNfaWithStates_0(8, 36, 29); - break; - case 105: - return jjMoveStringLiteralDfa9_0(active0, 0x8000000000000L); - case 111: - return jjMoveStringLiteralDfa9_0(active0, 0x400000000L); - case 116: - if ((active0 & 0x80000000000000L) != 0L) - return jjStartNfaWithStates_0(8, 55, 29); - return jjMoveStringLiteralDfa9_0(active0, 0x100000000L); - default: - break; - } - return jjStartNfa_0(7, active0, 0L); - } - - private int jjMoveStringLiteralDfa9_0(long old0, long active0) { - if ((active0 &= old0) == 0L) - return jjStartNfa_0(7, old0, 0L); - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - jjStopStringLiteralDfa_0(8, active0, 0L); - return 9; - } - switch (curChar) { - case 102: - if ((active0 & 0x400000000L) != 0L) - return jjStartNfaWithStates_0(9, 34, 29); - break; - case 115: - if ((active0 & 0x100000000L) != 0L) - return jjStartNfaWithStates_0(9, 32, 29); - break; - case 122: - return jjMoveStringLiteralDfa10_0(active0, 0x8000000000000L); - default: - break; - } - return jjStartNfa_0(8, active0, 0L); - } - - private int jjMoveStringLiteralDfa10_0(long old0, long active0) { - if ((active0 &= old0) == 0L) - return jjStartNfa_0(8, old0, 0L); - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - jjStopStringLiteralDfa_0(9, active0, 0L); - return 10; - } - switch (curChar) { - case 101: - return jjMoveStringLiteralDfa11_0(active0, 0x8000000000000L); - default: - break; - } - return jjStartNfa_0(9, active0, 0L); - } - - private int jjMoveStringLiteralDfa11_0(long old0, long active0) { - if ((active0 &= old0) == 0L) - return jjStartNfa_0(9, old0, 0L); - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - jjStopStringLiteralDfa_0(10, active0, 0L); - return 11; - } - switch (curChar) { - case 100: - if ((active0 & 0x8000000000000L) != 0L) - return jjStartNfaWithStates_0(11, 51, 29); - break; - default: - break; - } - return jjStartNfa_0(10, active0, 0L); - } - - private void jjCheckNAdd(int state) { - if (jjrounds[state] != jjround) { - jjstateSet[jjnewStateCnt++] = state; - jjrounds[state] = jjround; - } - } - - private void jjAddStates(int start, int end) { - do { - jjstateSet[jjnewStateCnt++] = jjnextStates[start]; - } while (start++ != end); - } - - private void jjCheckNAddTwoStates(int state1, int state2) { - jjCheckNAdd(state1); - jjCheckNAdd(state2); - } - - private void jjCheckNAddStates(int start, int end) { - do { - jjCheckNAdd(jjnextStates[start]); - } while (start++ != end); - } - - private void jjCheckNAddStates(int start) { - jjCheckNAdd(jjnextStates[start]); - jjCheckNAdd(jjnextStates[start + 1]); - } - - static final long[] jjbitVec0 = { - 0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL - }; - - static final long[] jjbitVec2 = { - 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL - }; - - static final long[] jjbitVec3 = { - 0xfff0000000200002L, 0xffffffffffffdfffL, 0xfffff00f7fffffffL, 0x12000000007fffffL - }; - - static final long[] jjbitVec4 = { - 0x0L, 0x0L, 0x420043c00000000L, 0xff7fffffff7fffffL - }; - - static final long[] jjbitVec5 = { - 0xffffcffffffffL, 0xffffffffffff0000L, 0xf9ff3fffffffffffL, 0x401f00030003L - }; - - static final long[] jjbitVec6 = { - 0x0L, 0x400000000000000L, 0xfffffffbffffd740L, 0xffffffcff7fffL - }; - - static final long[] jjbitVec7 = { - 0xffffffffffffffffL, 0xffffffffffffffffL, 0xfffffffffffff003L, 0x33fffffffff199fL - }; - - static final long[] jjbitVec8 = { - 0xfffe000000000000L, 0xfffffffe027fffffL, 0xffL, 0x707ffffff0000L - }; - - static final long[] jjbitVec9 = { - 0x7fffffe00000000L, 0xfffe0000000007ffL, 0xffffffffffffffffL, 0x1c000060002fffffL - }; - - static final long[] jjbitVec10 = { - 0x1ffffffd0000L, 0x0L, 0x3fffffffffL, 0x0L - }; - - static final long[] jjbitVec11 = { - 0x23ffffffffffffe0L, 0x3ff010000L, 0x3c5fdfffff99fe0L, 0xf0003b0000000L - }; - - static final long[] jjbitVec12 = { - 0x36dfdfffff987e0L, 0x1c00005e000000L, 0x23edfdfffffbafe0L, 0x100010000L - }; - - static final long[] jjbitVec13 = { - 0x23cdfdfffff99fe0L, 0x3b0000000L, 0x3bfc718d63dc7e0L, 0x0L - }; - - static final long[] jjbitVec14 = { - 0x3effdfffffddfe0L, 0x300000000L, 0x3effdfffffddfe0L, 0x340000000L - }; - - static final long[] jjbitVec15 = { - 0x3fffdfffffddfe0L, 0x300000000L, 0x2ffbfffffc7fffe0L, 0x7fL - }; - - static final long[] jjbitVec16 = { - 0x800dfffffffffffeL, 0x7fL, 0x200decaefef02596L, 0x3000005fL - }; - - static final long[] jjbitVec17 = { - 0x1L, 0x7fffffffeffL, 0xf00L, 0x0L - }; - - static final long[] jjbitVec18 = { - 0x6fbffffffffL, 0x3f0000L, 0xffffffff00000000L, 0x7fffffffff003fL - }; - - static final long[] jjbitVec19 = { - 0xffffffffffffffffL, 0xffffffff83ffffffL, 0xffffff07ffffffffL, 0x3ffffffffffffffL - }; - - static final long[] jjbitVec20 = { - 0xffffffffffffff7fL, 0xffffffff3d7f3d7fL, 0x7f3d7fffffff3d7fL, 0xffff7fffff7f7f3dL - }; - - static final long[] jjbitVec21 = { - 0xffffffff7f3d7fffL, 0x7ffff7fL, 0xffffffff00000000L, 0x1fffffffffffffL - }; - - static final long[] jjbitVec22 = { - 0xffffffffffffffffL, 0x7f9fffffffffffL, 0xffffffff07fffffeL, 0x7ffffffffffL - }; - - static final long[] jjbitVec23 = { - 0x0L, 0x0L, 0xfffffffffffffL, 0x8000000L - }; - - static final long[] jjbitVec24 = { - 0xffffffff00000000L, 0xffffffffffffffL, 0x1ffffffffffL, 0x0L - }; - - static final long[] jjbitVec25 = { - 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffff0fffffffL, 0x3ffffffffffffffL - }; - - static final long[] jjbitVec26 = { - 0xffffffff3f3fffffL, 0x3fffffffaaff3f3fL, 0x5fdfffffffffffffL, 0x1fdc1fff0fcf1fdcL - }; - - static final long[] jjbitVec27 = { - 0x8000000000000000L, 0x8000000000000001L, 0xffff00000000L, 0x0L - }; - - static final long[] jjbitVec28 = { - 0x3fbbd503e2ffc84L, 0xffffffff00000000L, 0xfL, 0x0L - }; - - static final long[] jjbitVec29 = { - 0x73e03fe000000e0L, 0xfffffffffffffffeL, 0xfffffffe601fffffL, 0x7fffffffffffffffL - }; - - static final long[] jjbitVec30 = { - 0xfffe1fffffffffe0L, 0xffffffffffffffffL, 0xffffff00007fffL, 0x0L - }; - - static final long[] jjbitVec31 = { - 0xffffffffffffffffL, 0xffffffffffffffffL, 0x3fffffffffffffL, 0x0L - }; - - static final long[] jjbitVec32 = { - 0xffffffffffffffffL, 0xffffffffffffffffL, 0x3fffffffffL, 0x0L - }; - - static final long[] jjbitVec33 = { - 0xffffffffffffffffL, 0xffffffffffffffffL, 0x1fffL, 0x0L - }; - - static final long[] jjbitVec34 = { - 0xffffffffffffffffL, 0xffffffffffffffffL, 0xfffffffffL, 0x0L - }; - - static final long[] jjbitVec35 = { - 0x3fffffffffffL, 0x0L, 0x0L, 0x0L - }; - - static final long[] jjbitVec36 = { - 0x5f7ffdffa0f8007fL, 0xffffffffffffffdbL, 0x3ffffffffffffL, 0xfffffffffff80000L - }; - - static final long[] jjbitVec37 = { - 0x3fffffffffffffffL, 0xffffffffffff0000L, 0xfffffffffffcffffL, 0xfff0000000000ffL - }; - - static final long[] jjbitVec38 = { - 0x18000000000000L, 0xffd702000000e000L, 0xffffffffffffffffL, 0x1fffffffffffffffL - }; - - static final long[] jjbitVec39 = { - 0x87fffffe00000010L, 0xffffffe007fffffeL, 0x7fffffffffffffffL, 0x631cfcfcfcL - }; - - static final long[] jjbitVec40 = { - 0x0L, 0x0L, 0x420043cffffffffL, 0xff7fffffff7fffffL - }; - - static final long[] jjbitVec41 = { - 0xffffffffffffffffL, 0x400000700007fffL, 0xfffffffbffffd740L, 0xffffffcff7fffL - }; - - static final long[] jjbitVec42 = { - 0xffffffffffffffffL, 0xffffffffffffffffL, 0xfffffffffffff07bL, 0x33fffffffff199fL - }; - - static final long[] jjbitVec43 = { - 0xfffe000000000000L, 0xfffffffe027fffffL, 0xbbfffffbfffe00ffL, 0x707ffffff0016L - }; - - static final long[] jjbitVec44 = { - 0x7fffffe00000000L, 0xffff03ff003fffffL, 0xffffffffffffffffL, 0x1fff3dff9fefffffL - }; - - static final long[] jjbitVec45 = { - 0xffff1fffffff8000L, 0x7ffL, 0x1ffffffffffffL, 0x0L - }; - - static final long[] jjbitVec46 = { - 0xf3ffffffffffffeeL, 0xffcfff1f3fffL, 0xd3c5fdfffff99feeL, 0xfffcfb080399fL - }; - - static final long[] jjbitVec47 = { - 0xd36dfdfffff987e4L, 0x1fffc05e003987L, 0xf3edfdfffffbafeeL, 0xffc100013bbfL - }; - - static final long[] jjbitVec48 = { - 0xf3cdfdfffff99feeL, 0xffc3b0c0398fL, 0xc3bfc718d63dc7ecL, 0xff8000803dc7L - }; - - static final long[] jjbitVec49 = { - 0xc3effdfffffddfeeL, 0xffc300603ddfL, 0xc3effdfffffddfecL, 0xffc340603ddfL - }; - - static final long[] jjbitVec50 = { - 0xc3fffdfffffddfecL, 0xffc300803dcfL, 0x2ffbfffffc7fffecL, 0xc0000ff5f847fL - }; - - static final long[] jjbitVec51 = { - 0x87fffffffffffffeL, 0x3ff7fffL, 0x3bffecaefef02596L, 0x33ff3f5fL - }; - - static final long[] jjbitVec52 = { - 0xc2a003ff03000001L, 0xfffe07fffffffeffL, 0x1ffffffffeff0fdfL, 0x40L - }; - - static final long[] jjbitVec53 = { - 0x3c7f6fbffffffffL, 0x3ff03ffL, 0xffffffff00000000L, 0x7fffffffff003fL - }; - - static final long[] jjbitVec54 = { - 0xffffffff7f3d7fffL, 0x3fe0007ffff7fL, 0xffffffff00000000L, 0x1fffffffffffffL - }; - - static final long[] jjbitVec55 = { - 0x0L, 0x0L, 0xffffffffffffffffL, 0x3ff080fffffL - }; - - static final long[] jjbitVec56 = { - 0xffffffff03ff7800L, 0xffffffffffffffL, 0x3ffffffffffL, 0x0L - }; - - static final long[] jjbitVec57 = { - 0x80007c000000f000L, 0x8000fc0000000001L, 0xffff00000000L, 0x21fff0000L - }; - - static final long[] jjbitVec58 = { - 0x73efffe000000e0L, 0xfffffffffffffffeL, 0xfffffffe661fffffL, 0x7fffffffffffffffL - }; - - static final long[] jjbitVec59 = { - 0x5f7ffdffe0f8007fL, 0xffffffffffffffdbL, 0x3ffffffffffffL, 0xfffffffffff80000L - }; - - static final long[] jjbitVec60 = { - 0x18000f00000000L, 0xffd702000000e000L, 0xffffffffffffffffL, 0x9fffffffffffffffL - }; - - static final long[] jjbitVec61 = { - 0x87fffffe03ff0010L, 0xffffffe007fffffeL, 0x7fffffffffffffffL, 0xe0000631cfcfcfcL - }; - - private int jjMoveNfa_0(int startState, int curPos) { - int[] nextStates; - int startsAt = 0; - jjnewStateCnt = 71; - int i = 1; - jjstateSet[0] = startState; - int j, kind = 0x7fffffff; - for (; ; ) { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) { - long l = 1L << curChar; - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 1: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddStates(0, 6); - else if ((0x100003600L & l) != 0L) { - if (kind > 3) - kind = 3; - jjCheckNAdd(0); - } else if (curChar == 47) - jjAddStates(7, 8); - else if (curChar == 36) { - if (kind > 72) - kind = 72; - jjCheckNAdd(29); - } else if (curChar == 34) - jjCheckNAddStates(9, 11); - else if (curChar == 39) - jjAddStates(12, 13); - else if (curChar == 46) - jjCheckNAdd(5); - if ((0x3fe000000000000L & l) != 0L) { - if (kind > 61) - kind = 61; - jjCheckNAddTwoStates(2, 3); - } else if (curChar == 48) { - if (kind > 61) - kind = 61; - jjCheckNAddStates(14, 18); - } - break; - case 48: - if (curChar == 47) { - if (kind > 4) - kind = 4; - jjCheckNAddStates(19, 21); - } else if (curChar == 42) - jjstateSet[jjnewStateCnt++] = 46; - break; - case 0: - if ((0x100003600L & l) == 0L) - break; - if (kind > 3) - kind = 3; - jjCheckNAdd(0); - break; - case 2: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 61) - kind = 61; - jjCheckNAddTwoStates(2, 3); - break; - case 4: - if (curChar == 46) - jjCheckNAdd(5); - break; - case 5: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 65) - kind = 65; - jjCheckNAddStates(22, 24); - break; - case 7: - if ((0x280000000000L & l) != 0L) - jjCheckNAdd(8); - break; - case 8: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 65) - kind = 65; - jjCheckNAddTwoStates(8, 9); - break; - case 10: - if (curChar == 39) - jjAddStates(12, 13); - break; - case 11: - if ((0xffffff7fffffdbffL & l) != 0L) - jjCheckNAdd(12); - break; - case 12: - if (curChar == 39 && kind > 70) - kind = 70; - break; - case 14: - if ((0x8400000000L & l) != 0L) - jjCheckNAdd(12); - break; - case 15: - if ((0xff000000000000L & l) != 0L) - jjCheckNAddTwoStates(16, 12); - break; - case 16: - if ((0xff000000000000L & l) != 0L) - jjCheckNAdd(12); - break; - case 17: - if ((0xf000000000000L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 18; - break; - case 18: - if ((0xff000000000000L & l) != 0L) - jjCheckNAdd(16); - break; - case 19: - if (curChar == 34) - jjCheckNAddStates(9, 11); - break; - case 20: - if ((0xfffffffbffffdbffL & l) != 0L) - jjCheckNAddStates(9, 11); - break; - case 22: - if ((0x8400000000L & l) != 0L) - jjCheckNAddStates(9, 11); - break; - case 23: - if (curChar == 34 && kind > 71) - kind = 71; - break; - case 24: - if ((0xff000000000000L & l) != 0L) - jjCheckNAddStates(25, 28); - break; - case 25: - if ((0xff000000000000L & l) != 0L) - jjCheckNAddStates(9, 11); - break; - case 26: - if ((0xf000000000000L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 27; - break; - case 27: - if ((0xff000000000000L & l) != 0L) - jjCheckNAdd(25); - break; - case 28: - if (curChar != 36) - break; - if (kind > 72) - kind = 72; - jjCheckNAdd(29); - break; - case 29: - if ((0x3ff00100fffc1ffL & l) == 0L) - break; - if (kind > 72) - kind = 72; - jjCheckNAdd(29); - break; - case 30: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddStates(0, 6); - break; - case 31: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddStates(29, 31); - break; - case 33: - if ((0x280000000000L & l) != 0L) - jjCheckNAdd(34); - break; - case 34: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddTwoStates(34, 9); - break; - case 35: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddTwoStates(35, 36); - break; - case 37: - if ((0x280000000000L & l) != 0L) - jjCheckNAdd(38); - break; - case 38: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 65) - kind = 65; - jjCheckNAddTwoStates(38, 9); - break; - case 39: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddTwoStates(39, 40); - break; - case 40: - if (curChar != 46) - break; - if (kind > 65) - kind = 65; - jjCheckNAddStates(32, 34); - break; - case 41: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 65) - kind = 65; - jjCheckNAddStates(32, 34); - break; - case 43: - if ((0x280000000000L & l) != 0L) - jjCheckNAdd(44); - break; - case 44: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 65) - kind = 65; - jjCheckNAddTwoStates(44, 9); - break; - case 45: - if (curChar == 47) - jjAddStates(7, 8); - break; - case 46: - if (curChar == 42) - jjstateSet[jjnewStateCnt++] = 47; - break; - case 47: - if ((0xffff7fffffffffffL & l) != 0L && kind > 1) - kind = 1; - break; - case 49: - if (curChar != 47) - break; - if (kind > 4) - kind = 4; - jjCheckNAddStates(19, 21); - break; - case 50: - if ((0xffffffffffffdbffL & l) == 0L) - break; - if (kind > 4) - kind = 4; - jjCheckNAddStates(19, 21); - break; - case 51: - if ((0x2400L & l) != 0L && kind > 4) - kind = 4; - break; - case 52: - if (curChar == 10 && kind > 4) - kind = 4; - break; - case 53: - if (curChar == 13) - jjstateSet[jjnewStateCnt++] = 52; - break; - case 54: - if (curChar != 48) - break; - if (kind > 61) - kind = 61; - jjCheckNAddStates(14, 18); - break; - case 56: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 61) - kind = 61; - jjCheckNAddTwoStates(56, 3); - break; - case 57: - if ((0xff000000000000L & l) == 0L) - break; - if (kind > 61) - kind = 61; - jjCheckNAddTwoStates(57, 3); - break; - case 59: - if ((0x3ff000000000000L & l) != 0L) - jjAddStates(35, 36); - break; - case 60: - if (curChar == 46) - jjCheckNAdd(61); - break; - case 61: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddTwoStates(61, 62); - break; - case 63: - if ((0x280000000000L & l) != 0L) - jjCheckNAdd(64); - break; - case 64: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 65) - kind = 65; - jjCheckNAddTwoStates(64, 9); - break; - case 66: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddStates(37, 39); - break; - case 67: - if (curChar == 46) - jjCheckNAdd(68); - break; - case 69: - if ((0x280000000000L & l) != 0L) - jjCheckNAdd(70); - break; - case 70: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 65) - kind = 65; - jjCheckNAddTwoStates(70, 9); - break; - default: - break; - } - } while (i != startsAt); - } else if (curChar < 128) { - long l = 1L << (curChar & 077); - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 1: - if ((0x7fffffe87fffffeL & l) == 0L) - break; - if (kind > 72) - kind = 72; - jjCheckNAdd(29); - break; - case 3: - if ((0x100000001000L & l) != 0L && kind > 61) - kind = 61; - break; - case 6: - if ((0x2000000020L & l) != 0L) - jjAddStates(40, 41); - break; - case 9: - if ((0x5000000050L & l) != 0L && kind > 65) - kind = 65; - break; - case 11: - if ((0xffffffffefffffffL & l) != 0L) - jjCheckNAdd(12); - break; - case 13: - if (curChar == 92) - jjAddStates(42, 44); - break; - case 14: - if ((0x14404410000000L & l) != 0L) - jjCheckNAdd(12); - break; - case 20: - if ((0xffffffffefffffffL & l) != 0L) - jjCheckNAddStates(9, 11); - break; - case 21: - if (curChar == 92) - jjAddStates(45, 47); - break; - case 22: - if ((0x14404410000000L & l) != 0L) - jjCheckNAddStates(9, 11); - break; - case 29: - if ((0x87fffffe87fffffeL & l) == 0L) - break; - if (kind > 72) - kind = 72; - jjCheckNAdd(29); - break; - case 32: - if ((0x2000000020L & l) != 0L) - jjAddStates(48, 49); - break; - case 36: - if ((0x2000000020L & l) != 0L) - jjAddStates(50, 51); - break; - case 42: - if ((0x2000000020L & l) != 0L) - jjAddStates(52, 53); - break; - case 47: - if (kind > 1) - kind = 1; - break; - case 50: - if (kind > 4) - kind = 4; - jjAddStates(19, 21); - break; - case 55: - if ((0x100000001000000L & l) != 0L) - jjCheckNAdd(56); - break; - case 56: - if ((0x7e0000007eL & l) == 0L) - break; - if (kind > 61) - kind = 61; - jjCheckNAddTwoStates(56, 3); - break; - case 58: - if ((0x100000001000000L & l) != 0L) - jjCheckNAddTwoStates(59, 60); - break; - case 59: - if ((0x7e0000007eL & l) != 0L) - jjCheckNAddTwoStates(59, 60); - break; - case 61: - if ((0x7e0000007eL & l) != 0L) - jjAddStates(54, 55); - break; - case 62: - if ((0x1000000010000L & l) != 0L) - jjAddStates(56, 57); - break; - case 65: - if ((0x100000001000000L & l) != 0L) - jjCheckNAdd(66); - break; - case 66: - if ((0x7e0000007eL & l) != 0L) - jjCheckNAddStates(37, 39); - break; - case 68: - if ((0x1000000010000L & l) != 0L) - jjAddStates(58, 59); - break; - default: - break; - } - } while (i != startsAt); - } else { - int hiByte = (int) (curChar >> 8); - int i1 = hiByte >> 6; - long l1 = 1L << (hiByte & 077); - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - MatchLoop: - do { - switch (jjstateSet[--i]) { - case 1: - if (!jjCanMove_1(hiByte, i1, i2, l1, l2)) - break; - if (kind > 72) - kind = 72; - jjCheckNAdd(29); - break; - case 11: - if (jjCanMove_0(hiByte, i1, i2, l1, l2)) - jjstateSet[jjnewStateCnt++] = 12; - break; - case 20: - if (jjCanMove_0(hiByte, i1, i2, l1, l2)) - jjAddStates(9, 11); - break; - case 29: - if (!jjCanMove_2(hiByte, i1, i2, l1, l2)) - break; - if (kind > 72) - kind = 72; - jjCheckNAdd(29); - break; - case 47: - if (jjCanMove_0(hiByte, i1, i2, l1, l2) && kind > 1) - kind = 1; - break; - case 50: - if (!jjCanMove_0(hiByte, i1, i2, l1, l2)) - break; - if (kind > 4) - kind = 4; - jjAddStates(19, 21); - break; - default: - break; - } - } while (i != startsAt); - } - if (kind != 0x7fffffff) { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 71 - (jjnewStateCnt = startsAt))) - return curPos; - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - return curPos; - } - } - } - - private int jjMoveStringLiteralDfa0_2() { - switch (curChar) { - case 42: - return jjMoveStringLiteralDfa1_2(0x40L); - default: - return 1; - } - } - - private int jjMoveStringLiteralDfa1_2(long active0) { - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - return 1; - } - switch (curChar) { - case 47: - if ((active0 & 0x40L) != 0L) - return jjStopAtPos(1, 6); - break; - default: - return 2; - } - return 2; - } - - private int jjMoveStringLiteralDfa0_1() { - switch (curChar) { - case 42: - return jjMoveStringLiteralDfa1_1(0x20L); - default: - return 1; - } - } - - private int jjMoveStringLiteralDfa1_1(long active0) { - try { - curChar = input_stream.readChar(); - } catch (IOException e) { - return 1; - } - switch (curChar) { - case 47: - if ((active0 & 0x20L) != 0L) - return jjStopAtPos(1, 5); - break; - default: - return 2; - } - return 2; - } - - static final int[] jjnextStates = { - 31, 32, 9, 35, 36, 39, 40, 48, 49, 20, 21, 23, 11, 13, 55, 57, - 3, 58, 65, 50, 51, 53, 5, 6, 9, 20, 21, 25, 23, 31, 32, 9, - 41, 42, 9, 59, 60, 66, 67, 68, 7, 8, 14, 15, 17, 22, 24, 26, - 33, 34, 37, 38, 43, 44, 61, 62, 63, 64, 69, 70, - }; - - private static boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2) { - switch (hiByte) { - case 0: - return (jjbitVec2[i2] & l2) != 0L; - default: - if ((jjbitVec0[i1] & l1) != 0L) - return true; - return false; - } - } - - private static boolean jjCanMove_1(int hiByte, int i1, int i2, long l1, long l2) { - switch (hiByte) { - case 0: - return (jjbitVec4[i2] & l2) != 0L; - case 2: - return (jjbitVec5[i2] & l2) != 0L; - case 3: - return (jjbitVec6[i2] & l2) != 0L; - case 4: - return (jjbitVec7[i2] & l2) != 0L; - case 5: - return (jjbitVec8[i2] & l2) != 0L; - case 6: - return (jjbitVec9[i2] & l2) != 0L; - case 7: - return (jjbitVec10[i2] & l2) != 0L; - case 9: - return (jjbitVec11[i2] & l2) != 0L; - case 10: - return (jjbitVec12[i2] & l2) != 0L; - case 11: - return (jjbitVec13[i2] & l2) != 0L; - case 12: - return (jjbitVec14[i2] & l2) != 0L; - case 13: - return (jjbitVec15[i2] & l2) != 0L; - case 14: - return (jjbitVec16[i2] & l2) != 0L; - case 15: - return (jjbitVec17[i2] & l2) != 0L; - case 16: - return (jjbitVec18[i2] & l2) != 0L; - case 17: - return (jjbitVec19[i2] & l2) != 0L; - case 18: - return (jjbitVec20[i2] & l2) != 0L; - case 19: - return (jjbitVec21[i2] & l2) != 0L; - case 20: - return (jjbitVec0[i2] & l2) != 0L; - case 22: - return (jjbitVec22[i2] & l2) != 0L; - case 23: - return (jjbitVec23[i2] & l2) != 0L; - case 24: - return (jjbitVec24[i2] & l2) != 0L; - case 30: - return (jjbitVec25[i2] & l2) != 0L; - case 31: - return (jjbitVec26[i2] & l2) != 0L; - case 32: - return (jjbitVec27[i2] & l2) != 0L; - case 33: - return (jjbitVec28[i2] & l2) != 0L; - case 48: - return (jjbitVec29[i2] & l2) != 0L; - case 49: - return (jjbitVec30[i2] & l2) != 0L; - case 77: - return (jjbitVec31[i2] & l2) != 0L; - case 159: - return (jjbitVec32[i2] & l2) != 0L; - case 164: - return (jjbitVec33[i2] & l2) != 0L; - case 215: - return (jjbitVec34[i2] & l2) != 0L; - case 250: - return (jjbitVec35[i2] & l2) != 0L; - case 251: - return (jjbitVec36[i2] & l2) != 0L; - case 253: - return (jjbitVec37[i2] & l2) != 0L; - case 254: - return (jjbitVec38[i2] & l2) != 0L; - case 255: - return (jjbitVec39[i2] & l2) != 0L; - default: - if ((jjbitVec3[i1] & l1) != 0L) - return true; - return false; - } - } - - private static boolean jjCanMove_2(int hiByte, int i1, int i2, long l1, long l2) { - switch (hiByte) { - case 0: - return (jjbitVec40[i2] & l2) != 0L; - case 2: - return (jjbitVec5[i2] & l2) != 0L; - case 3: - return (jjbitVec41[i2] & l2) != 0L; - case 4: - return (jjbitVec42[i2] & l2) != 0L; - case 5: - return (jjbitVec43[i2] & l2) != 0L; - case 6: - return (jjbitVec44[i2] & l2) != 0L; - case 7: - return (jjbitVec45[i2] & l2) != 0L; - case 9: - return (jjbitVec46[i2] & l2) != 0L; - case 10: - return (jjbitVec47[i2] & l2) != 0L; - case 11: - return (jjbitVec48[i2] & l2) != 0L; - case 12: - return (jjbitVec49[i2] & l2) != 0L; - case 13: - return (jjbitVec50[i2] & l2) != 0L; - case 14: - return (jjbitVec51[i2] & l2) != 0L; - case 15: - return (jjbitVec52[i2] & l2) != 0L; - case 16: - return (jjbitVec53[i2] & l2) != 0L; - case 17: - return (jjbitVec19[i2] & l2) != 0L; - case 18: - return (jjbitVec20[i2] & l2) != 0L; - case 19: - return (jjbitVec54[i2] & l2) != 0L; - case 20: - return (jjbitVec0[i2] & l2) != 0L; - case 22: - return (jjbitVec22[i2] & l2) != 0L; - case 23: - return (jjbitVec55[i2] & l2) != 0L; - case 24: - return (jjbitVec56[i2] & l2) != 0L; - case 30: - return (jjbitVec25[i2] & l2) != 0L; - case 31: - return (jjbitVec26[i2] & l2) != 0L; - case 32: - return (jjbitVec57[i2] & l2) != 0L; - case 33: - return (jjbitVec28[i2] & l2) != 0L; - case 48: - return (jjbitVec58[i2] & l2) != 0L; - case 49: - return (jjbitVec30[i2] & l2) != 0L; - case 77: - return (jjbitVec31[i2] & l2) != 0L; - case 159: - return (jjbitVec32[i2] & l2) != 0L; - case 164: - return (jjbitVec33[i2] & l2) != 0L; - case 215: - return (jjbitVec34[i2] & l2) != 0L; - case 250: - return (jjbitVec35[i2] & l2) != 0L; - case 251: - return (jjbitVec59[i2] & l2) != 0L; - case 253: - return (jjbitVec37[i2] & l2) != 0L; - case 254: - return (jjbitVec60[i2] & l2) != 0L; - case 255: - return (jjbitVec61[i2] & l2) != 0L; - default: - if ((jjbitVec3[i1] & l1) != 0L) - return true; - return false; - } - } - - public static final String[] jjstrLiteralImages = { - "", null, null, null, null, null, null, null, - "\141\142\163\164\162\141\143\164", "\141\163\163\145\162\164", "\142\157\157\154\145\141\156", - "\142\162\145\141\153", "\142\171\164\145", "\143\141\163\145", "\143\141\164\143\150", - "\143\150\141\162", "\143\154\141\163\163", "\143\157\156\163\164", - "\143\157\156\164\151\156\165\145", "\144\145\146\141\165\154\164", "\144\157", "\144\157\165\142\154\145", - "\145\154\163\145", "\145\156\165\155", "\145\170\164\145\156\144\163", "\146\141\154\163\145", - "\146\151\156\141\154", "\146\151\156\141\154\154\171", "\146\154\157\141\164", "\146\157\162", - "\147\157\164\157", "\151\146", "\151\155\160\154\145\155\145\156\164\163", - "\151\155\160\157\162\164", "\151\156\163\164\141\156\143\145\157\146", "\151\156\164", - "\151\156\164\145\162\146\141\143\145", "\154\157\156\147", "\156\141\164\151\166\145", "\156\145\167", - "\156\165\154\154", "\160\141\143\153\141\147\145", "\160\162\151\166\141\164\145", - "\160\162\157\164\145\143\164\145\144", "\160\165\142\154\151\143", "\162\145\164\165\162\156", - "\163\150\157\162\164", "\163\164\141\164\151\143", "\163\164\162\151\143\164\146\160", - "\163\165\160\145\162", "\163\167\151\164\143\150", - "\163\171\156\143\150\162\157\156\151\172\145\144", "\164\150\151\163", "\164\150\162\157\167", "\164\150\162\157\167\163", - "\164\162\141\156\163\151\145\156\164", "\164\162\165\145", "\164\162\171", "\166\157\151\144", - "\166\157\154\141\164\151\154\145", "\167\150\151\154\145", null, null, null, null, null, null, null, null, null, - null, null, null, null, null, "\50", "\51", "\173", "\175", "\133", "\135", "\73", - "\54", "\56", "\100", "\75", "\74", "\41", "\176", "\77", "\72", "\75\75", "\74\75", - "\76\75", "\41\75", "\174\174", "\46\46", "\53\53", "\55\55", "\53", "\55", "\52", - "\57", "\46", "\174", "\136", "\45", "\74\74", "\53\75", "\55\75", "\52\75", - "\57\75", "\46\75", "\174\75", "\136\75", "\45\75", "\74\74\75", "\76\76\75", - "\76\76\76\75", "\56\56\56", "\76\76\76", "\76\76", "\76", "\32", null,}; - - public static final String[] lexStateNames = { - "DEFAULT", - "IN_FORMAL_COMMENT", - "IN_MULTI_LINE_COMMENT", - }; - - public static final int[] jjnewLexState = { - -1, 1, 2, -1, -1, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - }; - - static final long[] jjtoToken = { - 0x3fffffffffffff01L, 0x1ffffffffffff9c2L, - }; - - static final long[] jjtoSkip = { - 0x78L, 0x0L, - }; - - static final long[] jjtoSpecial = { - 0x78L, 0x0L, - }; - - static final long[] jjtoMore = { - 0x86L, 0x0L, - }; - - protected JavaCharStream input_stream; - - private final int[] jjrounds = new int[71]; - - private final int[] jjstateSet = new int[142]; - - StringBuilder image; - - int jjimageLen; - - int lengthOfMatch; - - protected char curChar; - - public JavaParserTokenManager(JavaCharStream stream) { - if (JavaCharStream.staticFlag) - throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); - input_stream = stream; - } - - public JavaParserTokenManager(JavaCharStream stream, int lexState) { - this(stream); - SwitchTo(lexState); - } - - public void ReInit(JavaCharStream stream) { - jjmatchedPos = jjnewStateCnt = 0; - curLexState = defaultLexState; - input_stream = stream; - ReInitRounds(); - } - - private void ReInitRounds() { - int i; - jjround = 0x80000001; - for (i = 71; i-- > 0; ) - jjrounds[i] = 0x80000000; - } - - public void ReInit(JavaCharStream stream, int lexState) { - ReInit(stream); - SwitchTo(lexState); - } - - public void SwitchTo(int lexState) { - if (lexState >= 3 || lexState < 0) - throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); - else - curLexState = lexState; - } - - protected Token jjFillToken() { - Token t = Token.newToken(jjmatchedKind); - t.kind = jjmatchedKind; - String im = jjstrLiteralImages[jjmatchedKind]; - t.image = im == null ? input_stream.GetImage() : im; - t.beginLine = input_stream.getBeginLine(); - t.beginColumn = input_stream.getBeginColumn(); - t.endLine = input_stream.getEndLine(); - t.endColumn = input_stream.getEndColumn(); - return t; - } - - int curLexState = 0; - - int defaultLexState = 0; - - int jjnewStateCnt; - - int jjround; - - int jjmatchedPos; - - int jjmatchedKind; - - public Token getNextToken() { - int kind; - Token specialToken = null; - Token matchedToken; - int curPos = 0; - - EOFLoop: - for (; ; ) { - try { - curChar = input_stream.BeginToken(); - } catch (IOException e) { - jjmatchedKind = 0; - matchedToken = jjFillToken(); - matchedToken.specialToken = specialToken; - return matchedToken; - } - image = null; - jjimageLen = 0; - - for (; ; ) { - switch (curLexState) { - case 0: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_0(); - if (jjmatchedPos == 0 && jjmatchedKind > 124) { - jjmatchedKind = 124; - } - break; - case 1: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_1(); - if (jjmatchedPos == 0 && jjmatchedKind > 7) { - jjmatchedKind = 7; - } - break; - case 2: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_2(); - if (jjmatchedPos == 0 && jjmatchedKind > 7) { - jjmatchedKind = 7; - } - break; - } - if (jjmatchedKind != 0x7fffffff) { - if (jjmatchedPos + 1 < curPos) - input_stream.backup(curPos - jjmatchedPos - 1); - if ((jjtoToken[jjmatchedKind >> 6] & 1L << (jjmatchedKind & 077)) != 0L) { - matchedToken = jjFillToken(); - matchedToken.specialToken = specialToken; - TokenLexicalActions(matchedToken); - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - return matchedToken; - } else if ((jjtoSkip[jjmatchedKind >> 6] & 1L << (jjmatchedKind & 077)) != 0L) { - if ((jjtoSpecial[jjmatchedKind >> 6] & 1L << (jjmatchedKind & 077)) != 0L) { - matchedToken = jjFillToken(); - if (specialToken == null) - specialToken = matchedToken; - else { - matchedToken.specialToken = specialToken; - specialToken = specialToken.next = matchedToken; - } - SkipLexicalActions(matchedToken); - } else - SkipLexicalActions(null); - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - continue EOFLoop; - } - MoreLexicalActions(); - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - curPos = 0; - jjmatchedKind = 0x7fffffff; - try { - curChar = input_stream.readChar(); - continue; - } catch (IOException e1) { - } - } - int error_line = input_stream.getEndLine(); - int error_column = input_stream.getEndColumn(); - String error_after = null; - boolean EOFSeen = false; - try { - input_stream.readChar(); - input_stream.backup(1); - } catch (IOException e1) { - EOFSeen = true; - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - if (curChar == '\n' || curChar == '\r') { - error_line++; - error_column = 0; - } else - error_column++; - } - if (!EOFSeen) { - input_stream.backup(1); - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - } - throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); - } - } - } - - void SkipLexicalActions(Token matchedToken) { - switch (jjmatchedKind) { - default: - break; - } - } - - void MoreLexicalActions() { - jjimageLen += lengthOfMatch = jjmatchedPos + 1; - switch (jjmatchedKind) { - case 1: - if (image == null) - image = new StringBuilder(); - image.append(input_stream.GetSuffix(jjimageLen)); - jjimageLen = 0; - input_stream.backup(1); - break; - default: - break; - } - } - - void TokenLexicalActions(Token matchedToken) { - switch (jjmatchedKind) { - case 120: - if (image == null) - image = new StringBuilder(); - image.append(jjstrLiteralImages[120]); - matchedToken.kind = GT; - ((Token.GTToken) matchedToken).realKind = RUNSIGNEDSHIFT; - input_stream.backup(2); - matchedToken.image = ">"; - break; - case 121: - if (image == null) - image = new StringBuilder(); - image.append(jjstrLiteralImages[121]); - matchedToken.kind = GT; - ((Token.GTToken) matchedToken).realKind = RSIGNEDSHIFT; - input_stream.backup(1); - matchedToken.image = ">"; - break; - default: - break; - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserTreeConstants.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserTreeConstants.java deleted file mode 100644 index 279f2d4..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserTreeConstants.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JJTree: Do not edit this line. ./JavaParserTreeConstants.java */ - - -package jaxx.compiler.java.parser; - -public interface JavaParserTreeConstants { - int JJTLINE = 0; - - int JJTCOMPILATIONUNIT = 1; - - int JJTPACKAGEDECLARATION = 2; - - int JJTIMPORTDECLARATION = 3; - - int JJTMODIFIERS = 4; - - int JJTTYPEDECLARATION = 5; - - int JJTCLASSORINTERFACEDECLARATION = 6; - - int JJTEXTENDSLIST = 7; - - int JJTIMPLEMENTSLIST = 8; - - int JJTENUMDECLARATION = 9; - - int JJTENUMBODY = 10; - - int JJTENUMCONSTANT = 11; - - int JJTTYPEPARAMETERS = 12; - - int JJTTYPEPARAMETER = 13; - - int JJTTYPEBOUND = 14; - - int JJTCLASSORINTERFACEBODY = 15; - - int JJTCLASSORINTERFACEBODYDECLARATION = 16; - - int JJTFIELDDECLARATION = 17; - - int JJTVARIABLEDECLARATOR = 18; - - int JJTVARIABLEDECLARATORID = 19; - - int JJTVARIABLEINITIALIZER = 20; - - int JJTARRAYINITIALIZER = 21; - - int JJTMETHODDECLARATION = 22; - - int JJTMETHODDECLARATOR = 23; - - int JJTFORMALPARAMETERS = 24; - - int JJTFORMALPARAMETER = 25; - - int JJTCONSTRUCTORDECLARATION = 26; - - int JJTEXPLICITCONSTRUCTORINVOCATION = 27; - - int JJTINITIALIZER = 28; - - int JJTTYPE = 29; - - int JJTREFERENCETYPE = 30; - - int JJTCLASSORINTERFACETYPE = 31; - - int JJTTYPEARGUMENTS = 32; - - int JJTTYPEARGUMENT = 33; - - int JJTWILDCARDBOUNDS = 34; - - int JJTPRIMITIVETYPE = 35; - - int JJTRESULTTYPE = 36; - - int JJTNAME = 37; - - int JJTNAMELIST = 38; - - int JJTEXPRESSION = 39; - - int JJTASSIGNMENTOPERATOR = 40; - - int JJTASSIGNMENTEXPRESSION = 41; - - int JJTCONDITIONALEXPRESSION = 42; - - int JJTCONDITIONALOREXPRESSION = 43; - - int JJTCONDITIONALANDEXPRESSION = 44; - - int JJTINCLUSIVEOREXPRESSION = 45; - - int JJTEXCLUSIVEOREXPRESSION = 46; - - int JJTANDEXPRESSION = 47; - - int JJTEQUALITYEXPRESSION = 48; - - int JJTINSTANCEOFEXPRESSION = 49; - - int JJTRELATIONALEXPRESSION = 50; - - int JJTSHIFTEXPRESSION = 51; - - int JJTADDITIVEEXPRESSION = 52; - - int JJTMULTIPLICATIVEEXPRESSION = 53; - - int JJTUNARYEXPRESSION = 54; - - int JJTPREINCREMENTEXPRESSION = 55; - - int JJTPREDECREMENTEXPRESSION = 56; - - int JJTUNARYEXPRESSIONNOTPLUSMINUS = 57; - - int JJTCASTLOOKAHEAD = 58; - - int JJTPOSTFIXEXPRESSION = 59; - - int JJTPOSTFIXOPERATOR = 60; - - int JJTCASTEXPRESSION = 61; - - int JJTPRIMARYEXPRESSION = 62; - - int JJTMEMBERSELECTOR = 63; - - int JJTPRIMARYPREFIX = 64; - - int JJTPRIMARYSUFFIX = 65; - - int JJTLITERAL = 66; - - int JJTBOOLEANLITERAL = 67; - - int JJTNULLLITERAL = 68; - - int JJTARGUMENTS = 69; - - int JJTARGUMENTLIST = 70; - - int JJTALLOCATIONEXPRESSION = 71; - - int JJTARRAYDIMSANDINITS = 72; - - int JJTSTATEMENT = 73; - - int JJTASSERTSTATEMENT = 74; - - int JJTLABELEDSTATEMENT = 75; - - int JJTBLOCK = 76; - - int JJTBLOCKSTATEMENT = 77; - - int JJTLOCALVARIABLEDECLARATION = 78; - - int JJTEMPTYSTATEMENT = 79; - - int JJTSTATEMENTEXPRESSION = 80; - - int JJTSWITCHSTATEMENT = 81; - - int JJTSWITCHLABEL = 82; - - int JJTIFSTATEMENT = 83; - - int JJTWHILESTATEMENT = 84; - - int JJTDOSTATEMENT = 85; - - int JJTFORSTATEMENT = 86; - - int JJTFORINIT = 87; - - int JJTSTATEMENTEXPRESSIONLIST = 88; - - int JJTFORUPDATE = 89; - - int JJTBREAKSTATEMENT = 90; - - int JJTCONTINUESTATEMENT = 91; - - int JJTRETURNSTATEMENT = 92; - - int JJTTHROWSTATEMENT = 93; - - int JJTSYNCHRONIZEDSTATEMENT = 94; - - int JJTTRYSTATEMENT = 95; - - int JJTRUNSIGNEDSHIFT = 96; - - int JJTRSIGNEDSHIFT = 97; - - int JJTANNOTATION = 98; - - int JJTNORMALANNOTATION = 99; - - int JJTMARKERANNOTATION = 100; - - int JJTSINGLEMEMBERANNOTATION = 101; - - int JJTMEMBERVALUEPAIRS = 102; - - int JJTMEMBERVALUEPAIR = 103; - - int JJTMEMBERVALUE = 104; - - int JJTMEMBERVALUEARRAYINITIALIZER = 105; - - int JJTANNOTATIONTYPEDECLARATION = 106; - - int JJTANNOTATIONTYPEBODY = 107; - - int JJTANNOTATIONTYPEMEMBERDECLARATION = 108; - - int JJTDEFAULTVALUE = 109; - - - String[] jjtNodeName = { - "Line", - "CompilationUnit", - "PackageDeclaration", - "ImportDeclaration", - "Modifiers", - "TypeDeclaration", - "ClassOrInterfaceDeclaration", - "ExtendsList", - "ImplementsList", - "EnumDeclaration", - "EnumBody", - "EnumConstant", - "TypeParameters", - "TypeParameter", - "TypeBound", - "ClassOrInterfaceBody", - "ClassOrInterfaceBodyDeclaration", - "FieldDeclaration", - "VariableDeclarator", - "VariableDeclaratorId", - "VariableInitializer", - "ArrayInitializer", - "MethodDeclaration", - "MethodDeclarator", - "FormalParameters", - "FormalParameter", - "ConstructorDeclaration", - "ExplicitConstructorInvocation", - "Initializer", - "Type", - "ReferenceType", - "ClassOrInterfaceType", - "TypeArguments", - "TypeArgument", - "WildcardBounds", - "PrimitiveType", - "ResultType", - "Name", - "NameList", - "Expression", - "AssignmentOperator", - "AssignmentExpression", - "ConditionalExpression", - "ConditionalOrExpression", - "ConditionalAndExpression", - "InclusiveOrExpression", - "ExclusiveOrExpression", - "AndExpression", - "EqualityExpression", - "InstanceOfExpression", - "RelationalExpression", - "ShiftExpression", - "AdditiveExpression", - "MultiplicativeExpression", - "UnaryExpression", - "PreIncrementExpression", - "PreDecrementExpression", - "UnaryExpressionNotPlusMinus", - "CastLookahead", - "PostfixExpression", - "PostfixOperator", - "CastExpression", - "PrimaryExpression", - "MemberSelector", - "PrimaryPrefix", - "PrimarySuffix", - "Literal", - "BooleanLiteral", - "NullLiteral", - "Arguments", - "ArgumentList", - "AllocationExpression", - "ArrayDimsAndInits", - "Statement", - "AssertStatement", - "LabeledStatement", - "Block", - "BlockStatement", - "LocalVariableDeclaration", - "EmptyStatement", - "StatementExpression", - "SwitchStatement", - "SwitchLabel", - "IfStatement", - "WhileStatement", - "DoStatement", - "ForStatement", - "ForInit", - "StatementExpressionList", - "ForUpdate", - "BreakStatement", - "ContinueStatement", - "ReturnStatement", - "ThrowStatement", - "SynchronizedStatement", - "TryStatement", - "RUNSIGNEDSHIFT", - "RSIGNEDSHIFT", - "Annotation", - "NormalAnnotation", - "MarkerAnnotation", - "SingleMemberAnnotation", - "MemberValuePairs", - "MemberValuePair", - "MemberValue", - "MemberValueArrayInitializer", - "AnnotationTypeDeclaration", - "AnnotationTypeBody", - "AnnotationTypeMemberDeclaration", - "DefaultValue", - }; -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Node.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Node.java deleted file mode 100644 index a947768..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Node.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JJTree: Do not edit this line. Node.java */ - - -package jaxx.compiler.java.parser; - -/* All AST nodes must implement this interface. It provides basic - machinery for constructing the parent and child relationships - between nodes. */ - -public interface Node { - - /** - * This method is called after the node has been made the current - * node. It indicates that child nodes can now be added to it. - */ - void jjtOpen(); - - /** - * This method is called after all the child nodes have been - * added. - */ - void jjtClose(); - - /** - * This pair of methods are used to inform the node of its - * parent. - * - * @param n node - */ - void jjtSetParent(Node n); - - Node jjtGetParent(); - - /** - * This method tells the node to add its argument to the node's - * list of children. - * - * @param n node - * @param i index ? - */ - void jjtAddChild(Node n, int i); - - /** - * @param i index of child - * @return a child node. The children are numbered - * from zero, left to right. - */ - Node jjtGetChild(int i); - - /** @return the number of children the node has. */ - int jjtGetNumChildren(); -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/ParseException.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/ParseException.java deleted file mode 100644 index ba7fd4b..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/ParseException.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */ - -package jaxx.compiler.java.parser; - -/** - * This exception is thrown when parse errors are encountered. - * You can explicitly create objects of this exception type by - * calling the method generateParseException in the generated - * parser. - * - * You can modify this class to customize your error reporting - * mechanisms so long as you retain the public fields. - */ -public class ParseException extends jaxx.compiler.CompilerException { - int line; - - int column; - - private static final long serialVersionUID = 6179854408401024700L; - - /** - * This constructor is used by the method "generateParseException" - * in the generated parser. Calling this constructor generates - * a new object of this type with the fields "currentToken", - * "expectedTokenSequences", and "tokenImage" set. The boolean - * flag "specialConstructor" is also set to true to indicate that - * this constructor was used to create this object. - * This constructor calls its super class with the empty string - * to force the "toString" method of parent class "Throwable" to - * print the error message in the form: - * ParseException: <result of getMessage> - * - * @param currentTokenVal ? - * @param expectedTokenSequencesVal ? - * @param tokenImageVal ? - */ - public ParseException(Token currentTokenVal, - int[][] expectedTokenSequencesVal, - String[] tokenImageVal - ) { - super(""); - specialConstructor = true; - currentToken = currentTokenVal; - expectedTokenSequences = expectedTokenSequencesVal; - tokenImage = tokenImageVal; - } - - /** - * The following constructors are for use by you for whatever - * purpose you can think of. Constructing the exception in this - * manner makes the exception behave in the normal way - i.e., as - * documented in the class "Throwable". The fields "errorToken", - * "expectedTokenSequences", and "tokenImage" do not contain - * relevant information. The JavaCC generated code does not use - * these constructors. - */ - - public ParseException() { - super(); - specialConstructor = false; - } - - public ParseException(String message) { - super(message); - specialConstructor = false; - } - - public ParseException(String message, int line, int column) { - super(message); - specialConstructor = false; - this.line = line; - this.column = column; - } - - - /** - * This variable determines which constructor was used to create - * this object and thereby affects the semantics of the - * "getMessage" method (see below). - */ - protected boolean specialConstructor; - - /** - * This is the last token that has been consumed successfully. If - * this object has been created due to a parse error, the token - * followng this token will (therefore) be the first error token. - */ - public Token currentToken; - - /** - * Each entry in this array is an array of integers. Each array - * of integers represents a sequence of tokens (by their ordinal - * values) that is expected at this point of the parse. - */ - public int[][] expectedTokenSequences; - - /** - * This is a reference to the "tokenImage" array of the generated - * parser within which the parse error occurred. This array is - * defined in the generated ...Constants interface. - */ - public String[] tokenImage; - - /** - * This method has the standard behavior when this object has been - * created using the standard constructors. Otherwise, it uses - * "currentToken" and "expectedTokenSequences" to generate a parse - * error message and returns it. If this object has been created - * due to a parse error, and you do not catch it (it gets thrown - * from the parser), then this method is called during the printing - * of the final stack trace, and hence the correct error message - * gets displayed. - */ - public String getMessage() { - if (!specialConstructor) { - return super.getMessage(); - } - StringBuilder expected = new StringBuilder(); - int maxSize = 0; - for (int[] expectedTokenSequence : expectedTokenSequences) { - if (maxSize < expectedTokenSequence.length) { - maxSize = expectedTokenSequence.length; - } - for (int anExpectedTokenSequence : expectedTokenSequence) { - expected.append(tokenImage[anExpectedTokenSequence]).append(" "); - } - if (expectedTokenSequence[expectedTokenSequence.length - 1] != 0) { - expected.append("..."); - } - expected.append(eol).append(" "); - } - String retval = "Encountered \""; - Token tok = currentToken.next; - for (int i = 0; i < maxSize; i++) { - if (i != 0) retval += " "; - if (tok.kind == 0) { - retval += tokenImage[0]; - break; - } - retval += add_escapes(tok.image); - tok = tok.next; - } - retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; - retval += "." + eol; - if (expectedTokenSequences.length == 1) { - retval += "Was expecting:" + eol + " "; - } else { - retval += "Was expecting one of:" + eol + " "; - } - retval += expected.toString(); - return retval; - } - - - public int getLine() { - return line; - } - - public int getColumn() { - return column; - } - - /** The end of line string for this machine. */ - protected String eol = System.getProperty("line.separator", "\n"); - - /** - * Used to convert raw characters to their escaped version - * when these raw version cannot be used as part of an ASCII - * string literal. - * - * @param str text to treate - * @return the escaped version of text - */ - protected String add_escapes(String str) { - StringBuilder retval = new StringBuilder(); - char ch; - for (int i = 0; i < str.length(); i++) { - switch (str.charAt(i)) { - case 0: - continue; - case '\b': - retval.append("\\b"); - continue; - case '\t': - retval.append("\\t"); - continue; - case '\n': - retval.append("\\n"); - continue; - case '\f': - retval.append("\\f"); - continue; - case '\r': - retval.append("\\r"); - continue; - case '\"': - retval.append("\\\""); - continue; - case '\'': - retval.append("\\\'"); - continue; - case '\\': - retval.append("\\\\"); - continue; - default: - if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { - String s = "0000" + Integer.toString(ch, 16); - retval.append("\\u").append(s.substring(s.length() - 4, s.length())); - } else { - retval.append(ch); - } - } - } - return retval.toString(); - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/SimpleNode.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/SimpleNode.java deleted file mode 100644 index 164007d..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/SimpleNode.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JJTree: Do not edit this line. SimpleNode.java */ - - -package jaxx.compiler.java.parser; - -import jaxx.compiler.reflect.ClassDescriptor; - -public class SimpleNode implements Node { - protected Node parent; - - protected Node[] children; - - protected int id; - - protected JavaParser parser; - - public Token firstToken; - - public Token lastToken; - - private ClassDescriptor javaType; - - - public SimpleNode(int i) { - id = i; - } - - public SimpleNode(JavaParser p, int i) { - this(i); - parser = p; - } - - - public int getId() { - return id; - } - - public void jjtOpen() { - } - - public void jjtClose() { - } - - public void jjtSetParent(Node n) { - parent = n; - } - - public Node jjtGetParent() { - return parent; - } - - public SimpleNode getParent() { - return (SimpleNode) parent; - } - - - public ClassDescriptor getJavaType() { - return javaType; - } - - - public void setJavaType(ClassDescriptor javaType) { - this.javaType = javaType; - } - - public void jjtAddChild(Node n, int i) { - if (children == null) { - children = new Node[i + 1]; - } else if (i >= children.length) { - Node c[] = new Node[i + 1]; - System.arraycopy(children, 0, c, 0, children.length); - children = c; - } - children[i] = n; - } - - public Node jjtGetChild(int i) { - return children[i]; - } - - public SimpleNode getChild(int i) { - return (SimpleNode) children[i]; - } - - public int jjtGetNumChildren() { - return (children == null) ? 0 : children.length; - } - - /* You can override these two methods in subclasses of SimpleNode to -customize the way the node appears when the tree is dumped. If -your output uses more than one line you should override -toString(String), otherwise overriding toString() is probably all -you need to do. */ - - @Override - public String toString() { - return getClass().getName() + "[" + getText() + "]"; - } - - public String toString(String prefix) { - return prefix + toString(); - } - - /* Override this method if you want to customize how the node dumps - out its children. */ - - public void dump(String prefix) { - System.out.println(toString(prefix)); - if (children != null) { - for (Node aChildren : children) { - SimpleNode n = (SimpleNode) aChildren; - if (n != null) { - n.dump(prefix + " "); - } - } - } - } - - private void appendSpecialTokens(StringBuilder s, Token st) { - if (st != null) { - appendSpecialTokens(s, st.specialToken); - s.append(st.image); - } - } - - - /** @return the text of the tokens comprising this node. */ - public String getText() { - StringBuilder text = new StringBuilder(); - Token t = firstToken; - while (t != null) { - appendSpecialTokens(text, t.specialToken); - text.append(t.image); - if (t == lastToken) - break; - t = t.next; - } - - return text.toString(); - } -} - diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Token.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Token.java deleted file mode 100644 index 67adb03..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Token.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */ - -package jaxx.compiler.java.parser; - -/** Describes the input token stream. */ - -public class Token { - /** - * An integer that describes the kind of this token. This numbering - * system is determined by JavaCCParser, and a table of these numbers is - * stored in the file ...Constants.java. - */ - public int kind; - - /** - * beginLine and beginColumn describe the position of the first character - * of this token; endLine and endColumn describe the position of the - * last character of this token. - */ - public int beginLine, beginColumn, endLine, endColumn; - - /** The string image of the token. */ - public String image; - - /** - * A reference to the next regular (non-special) token from the input - * stream. If this is the last token from the input stream, or if the - * token manager has not read tokens beyond this one, this field is - * set to null. This is true only if this token is also a regular - * token. Otherwise, see below for a description of the contents of - * this field. - */ - public Token next; - - /** - * This field is used to access special tokens that occur prior to this - * token, but after the immediately preceding regular (non-special) token. - * If there are no such special tokens, this field is set to null. - * When there are more than one such special token, this field refers - * to the last of these special tokens, which in turn refers to the next - * previous special token through its specialToken field, and so on - * until the first special token (whose specialToken field is null). - * The next fields of special tokens refer to other special tokens that - * immediately follow it (without an intervening regular token). If there - * is no such token, this field is null. - */ - public Token specialToken; - - /** Returns the image. */ - public String toString() { - return image; - } - - /** - * Returns a new Token object, by default. However, if you want, you - * can create and return subclass objects based on the value of ofKind. - * Simply add the cases to the switch for all those special cases. - * For example, if you have a subclass of Token called IDToken that - * you want to create if ofKind is ID, simlpy add something like : - * - * case MyParserConstants.ID : return new IDToken(); - * - * to the following switch statement. Then you can cast matchedToken - * variable to the appropriate type and use it in your lexical actions. - */ - public static final Token newToken(int ofKind) { - switch (ofKind) { - default: - return new Token(); - case JavaParserConstants.RUNSIGNEDSHIFT: - case JavaParserConstants.RSIGNEDSHIFT: - case JavaParserConstants.GT: - return new GTToken(); - } - } - - public static class GTToken extends Token { - int realKind = JavaParserConstants.GT; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/TokenMgrError.java b/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/TokenMgrError.java deleted file mode 100644 index fc091e1..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/TokenMgrError.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */ - -package jaxx.compiler.java.parser; - -public class TokenMgrError extends Error { - /* - * Ordinals for various reasons why an Error of this type can be thrown. - */ - - /** Lexical error occured. */ - static final int LEXICAL_ERROR = 0; - - /** An attempt wass made to create a second instance of a static token manager. */ - static final int STATIC_LEXER_ERROR = 1; - - /** Tried to change to an invalid lexical state. */ - static final int INVALID_LEXICAL_STATE = 2; - - /** Detected (and bailed out of) an infinite loop in the token manager. */ - static final int LOOP_DETECTED = 3; - - /** - * Indicates the reason why the exception is thrown. It will have - * one of the above 4 values. - */ - int errorCode; - - private static final long serialVersionUID = -9131500865453532454L; - - /** - * Replaces unprintable characters by their espaced (or unicode escaped) - * equivalents in the given string - * - * @param str text to treate - * @return the treated text - */ - protected static String addEscapes(String str) { - StringBuilder retval = new StringBuilder(); - char ch; - for (int i = 0; i < str.length(); i++) { - switch (str.charAt(i)) { - case 0: - continue; - case '\b': - retval.append("\\b"); - continue; - case '\t': - retval.append("\\t"); - continue; - case '\n': - retval.append("\\n"); - continue; - case '\f': - retval.append("\\f"); - continue; - case '\r': - retval.append("\\r"); - continue; - case '\"': - retval.append("\\\""); - continue; - case '\'': - retval.append("\\\'"); - continue; - case '\\': - retval.append("\\\\"); - continue; - default: - if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { - String s = "0000" + Integer.toString(ch, 16); - retval.append("\\u").append(s.substring(s.length() - 4, s.length())); - } else { - retval.append(ch); - } - } - } - return retval.toString(); - } - - /** - * @param EOFSeen : indicates if EOF caused the lexicl error - * @param lexState : lexical state in which this error occured - * @param errorLine : line number when the error occured - * @param errorColumn : column number when the error occured - * @param errorAfter : prefix that was seen before this error occured - * @param curChar : the offending character - * Note: You can customize the lexical error message by modifying this method. - * @return a detailed message for the Error when it is thrown by the - * token manager to indicate a lexical error. - */ - protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { - return "Lexical error at line " + - errorLine + ", column " + - errorColumn + ". Encountered: " + - (EOFSeen ? "<EOF> " : "\"" + addEscapes(String.valueOf(curChar)) + "\"" + " (" + (int) curChar + "), ") + - "after : \"" + addEscapes(errorAfter) + "\""; - } - - /** - * You can also modify the body of this method to customize your error messages. - * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not - * of end-users concern, so you can return something like : - * - * "Internal Error : Please file a bug report .... " - * - * from this method for such cases in the release version of your parser. - */ - @Override - public String getMessage() { - return super.getMessage(); - } - - /* - * Constructors of various flavors follow. - */ - - public TokenMgrError() { - } - - public TokenMgrError(String message, int reason) { - super(message); - errorCode = reason; - } - - public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { - this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptor.java b/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptor.java deleted file mode 100644 index 13df107..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptor.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.reflect; - -import jaxx.runtime.JAXXObjectDescriptor; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.Arrays; - -/** - * Mirrors the class <code>java.lang.Class</code>. JAXX uses <code>ClassDescriptor</code> instead of <code>Class</code> - * almost everywhere so that it can handle circular dependencies (there can't be a <code>Class</code> object for an uncompiled - * JAXX or Java source file, and a compiler must be allow references to symbols in uncompiled source files in order to handle - * circular dependencies). - */ -public abstract class ClassDescriptor { - - /** Logger. */ - private static final Log log = LogFactory.getLog(ClassDescriptor.class); - - public static final FieldDescriptor[] EMPTY_FIELD_DESCRIPTORS_ARRAY = - new FieldDescriptor[0]; - - private String name; - - private String packageName; - - private String superclass; - - private String[] interfaces; - - private boolean isInterface; - - private boolean isArray; - - private String componentType; - - private JAXXObjectDescriptor jaxxObjectDescriptor; - - private ClassLoader classLoader; - - private MethodDescriptor[] constructorDescriptors; - - private MethodDescriptor[] methodDescriptors; - - private FieldDescriptor[] fieldDescriptors; - - protected FieldDescriptor[] declaredFieldDescriptors; - - protected final ClassDescriptorHelper.ResolverType resolverType; - - public abstract MethodDescriptor getDeclaredMethodDescriptor( - String name, - ClassDescriptor... parameterTypes) throws NoSuchMethodException; - -// public abstract FieldDescriptor getDeclaredFieldDescriptor( -// String name) throws NoSuchFieldException; - - public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { - for (FieldDescriptor descriptor : declaredFieldDescriptors) { - if (name.equals(descriptor.getName())) { - if (log.isDebugEnabled()) { - log.debug("Using a declared field descriptor [" + name + - "] for " + getName()); - } - return descriptor; - } - } - throw new NoSuchFieldException(name); - } - - protected ClassDescriptor(ClassDescriptorHelper.ResolverType resolverType, - String name, - String packageName, - String superclass, - String[] interfaces, - boolean isInterface, - boolean isArray, - String componentType, - JAXXObjectDescriptor jaxxObjectDescriptor, - ClassLoader classLoader, - MethodDescriptor[] constructorDescriptors, - MethodDescriptor[] methodDescriptors, - FieldDescriptor[] fieldDescriptors) { - this( - resolverType, name, - packageName, - superclass, - interfaces, - isInterface, - isArray, - componentType, - jaxxObjectDescriptor, - classLoader, - constructorDescriptors, - methodDescriptors, - fieldDescriptors, - null - ); - } - - protected ClassDescriptor( - ClassDescriptorHelper.ResolverType resolverType, - String name, - String packageName, - String superclass, - String[] interfaces, - boolean isInterface, - boolean isArray, - String componentType, - JAXXObjectDescriptor jaxxObjectDescriptor, - ClassLoader classLoader, - MethodDescriptor[] constructorDescriptors, - MethodDescriptor[] methodDescriptors, - FieldDescriptor[] fieldDescriptors, - FieldDescriptor[] declaredFieldDescriptors) { - this.resolverType = resolverType; - this.name = name; - this.packageName = packageName; - this.superclass = superclass; - this.interfaces = interfaces; - this.isInterface = isInterface; - this.isArray = isArray; - this.componentType = componentType; - this.jaxxObjectDescriptor = jaxxObjectDescriptor; - this.classLoader = classLoader; - this.constructorDescriptors = constructorDescriptors; - this.methodDescriptors = methodDescriptors; - this.fieldDescriptors = fieldDescriptors; - this.declaredFieldDescriptors = declaredFieldDescriptors; - } - - - public ClassDescriptorHelper.ResolverType getResolverType() { - return resolverType; - } - - public String getName() { - return name; - } - - public String getSimpleName() { - int dot = name.lastIndexOf("."); - return dot == -1 ? name : name.substring(dot + 1); - } - - public String getPackageName() { - return packageName; - } - - public ClassDescriptor getSuperclass() { - return getClassDescriptor(superclass); - - } - - public ClassDescriptor[] getInterfaces() { - ClassDescriptor[] result = new ClassDescriptor[interfaces.length]; - for (int i = 0; i < result.length; i++) { - result[i] = getClassDescriptor(interfaces[i]); - } - return result; - } - - public boolean isInterface() { - return isInterface; - } - - public boolean isArray() { - return isArray; - } - - public ClassDescriptor getComponentType() { - return getClassDescriptor(componentType); - } - - public ClassLoader getClassLoader() { - return classLoader; - } - - public MethodDescriptor[] getConstructorDescriptors() { - return constructorDescriptors; - } - - public MethodDescriptor[] getMethodDescriptors() { - return methodDescriptors; - } - - public MethodDescriptor getMethodDescriptor(String name, - ClassDescriptor... parameterTypes) throws NoSuchMethodException { - for (MethodDescriptor m : methodDescriptors) { - if (m.getName().equals(name) && - m.getParameterTypes().length == parameterTypes.length && - Arrays.equals(m.getParameterTypes(), parameterTypes)) { - return m; - } - } - throw new NoSuchMethodException( - "Could not find method " + name + "(" + - Arrays.asList(parameterTypes) + ") in " + getName()); - } - - public FieldDescriptor[] getFieldDescriptors() { - return fieldDescriptors; - } - - public FieldDescriptor[] getDeclaredFieldDescriptors() { - return declaredFieldDescriptors == null ? EMPTY_FIELD_DESCRIPTORS_ARRAY : declaredFieldDescriptors; - } - - public FieldDescriptor getFieldDescriptor(String name) throws NoSuchFieldException { - for (FieldDescriptor fieldDescriptor : fieldDescriptors) { - if (fieldDescriptor.getName().equals(name)) { - return fieldDescriptor; - } - } - throw new NoSuchFieldException( - "Could not find field " + name + " in " + getName()); - } - - public JAXXObjectDescriptor getJAXXObjectDescriptor() { - return jaxxObjectDescriptor; - } - - public boolean isAssignableFrom(ClassDescriptor descriptor) { - while (descriptor != null) { - if (equals(descriptor)) { - return true; - } - for (ClassDescriptor anInterface : descriptor.getInterfaces()) { - if (equals(anInterface) || isAssignableFrom(anInterface)) { - return true; - } - } - descriptor = descriptor.getSuperclass(); - } - return false; - } - - @Override - public String toString() { - return "ClassDescriptor[" + getName() + "]"; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof ClassDescriptor)) return false; - - ClassDescriptor that = (ClassDescriptor) o; - - return name.equals(that.name); - - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - protected ClassDescriptor getClassDescriptor(String fqn) { - if (fqn == null) { - return null; - } - - try { - return ClassDescriptorHelper.getClassDescriptor( - fqn, - getClassLoader() - ); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptorHelper.java b/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptorHelper.java deleted file mode 100644 index 520eb84..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptorHelper.java +++ /dev/null @@ -1,533 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.reflect; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXCompilerFile; -import jaxx.compiler.JAXXEngine; -import jaxx.compiler.JAXXFactory; -import jaxx.compiler.reflect.resolvers.ClassDescriptorResolverFromJavaClass; -import jaxx.compiler.reflect.resolvers.ClassDescriptorResolverFromJavaFile; -import jaxx.compiler.reflect.resolvers.ClassDescriptorResolverFromJaxxFile; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.JAXXObjectDescriptor; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URL; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; - -/** - * Mirrors the class <code>java.lang.ClassLoader</code>. JAXX uses <code>ClassDescriptor</code> instead of <code>Class</code> - * almost everywhere so that it can handle circular dependencies (there can't be a <code>Class</code> object for an uncompiled - * JAXX or Java source file, and a compiler must be allow references to symbols in uncompiled source files in order to handle - * circular dependencies). - * - * <b>Note : </b> Was previously {@code ClassDescriptorLoader}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class ClassDescriptorHelper { - - /** Logger */ - private static final Log log = LogFactory.getLog(ClassDescriptorHelper.class); - - /** - * Constants to define who load a {@link ClassDescriptor}. - * - * This will be usefull in some case (for consturctor for example when some - * descriptors are not fully loaded... - * - * @since 2.4 - */ - public enum ResolverType { - JAVA_CLASS, - JAVA_FILE, - JAXX_FILE - } - - private static boolean SHOW_LOADING = log.isDebugEnabled(); - - private static Map<String, ClassDescriptor> descriptors = - new HashMap<>(); - - private static Map<ResolverType, ClassDescriptorResolver> descriptorResolvers; - - protected static Map<ResolverType, ClassDescriptorResolver> getDescriptorResolvers() { - if (descriptorResolvers == null) { - descriptorResolvers = new EnumMap<>(ResolverType.class); - descriptorResolvers.put(ResolverType.JAVA_CLASS, new ClassDescriptorResolverFromJavaClass()); - descriptorResolvers.put(ResolverType.JAVA_FILE, new ClassDescriptorResolverFromJavaFile()); - descriptorResolvers.put(ResolverType.JAXX_FILE, new ClassDescriptorResolverFromJaxxFile()); - } - return descriptorResolvers; - } - - private ClassDescriptorHelper() { - // on instance - } - - public static boolean isAssignableFrom(ClassDescriptor classDescriptor, - Class<?> awareClass) throws ClassNotFoundException { - ClassDescriptor awareDescriptor = getClassDescriptor(awareClass); - return awareDescriptor.isAssignableFrom(classDescriptor); - } - - public static ClassDescriptor getClassDescriptor(String className) throws ClassNotFoundException { - - return getClassDescriptor(className, - Thread.currentThread().getContextClassLoader()); - } - - public static ClassDescriptor getClassDescriptor(Class<?> javaClass) { - try { - return getClassDescriptor(javaClass.getName(), - javaClass.getClassLoader()); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - public static URL getURL(ClassLoader classLoader, String className, String clasifier) { - String relativePath = className.replaceAll("\\.", "/"); - String path = relativePath + "." + clasifier; - if (log.isDebugEnabled()) { - log.debug("Path to search : " + path); - } - return classLoader.getResource(path); - } - - public static ClassDescriptor getClassDescriptor( - String className, - ClassLoader classLoader) throws ClassNotFoundException { - - if (classLoader == null) { - classLoader = ClassDescriptorHelper.class.getClassLoader(); - } - - ClassDescriptor result = descriptors.get(className); - if (result != null) { - - // found in cache - if (log.isTraceEnabled()) { - log.trace("resolved " + result + " from cache."); - } - return result; - } - - JAXXEngine engine = JAXXFactory.isEngineRegistred() ? - JAXXFactory.getEngine() : null; - - String relativePathPattern = ".*";// + className + ".*"; // used to ensure that the located resource has the right character cases - - if (engine != null) { - - JAXXCompilerFile file = engine.getJAXXCompilerFile(className); - - if (file != null) { - - // use the symbole table of this jaxx file on computation - - if (SHOW_LOADING) { - log.info("from JAXXFile " + file.getJaxxFile()); - } - result = getClassDescriptor0( - ResolverType.JAXX_FILE, - className, - file.getJAXXFileURL(), - classLoader - ); - - if (log.isDebugEnabled()) { - log.debug("[" + className + "] loaded"); - } - - return result; - } - } - - // the class is not in this compile set, try to have it from java - // sources or classes. - - // find the most recently updated source for the class -- Java source, JAXX source, or compiled class file - long javaLastModified = -1; - URL javaFile = getURL(classLoader, className, "java"); - if (javaFile != null && - javaFile.toString().startsWith("file:") && - javaFile.toString().matches(relativePathPattern)) { - javaLastModified = JAXXCompiler.URLtoFile(javaFile).lastModified(); - if (log.isTraceEnabled()) { - log.trace("[" + className + "] javaFile lastModified " + javaLastModified); - } - } - - long classLastModified = -1; - URL classFile = getURL(classLoader, className, "class"); - if (classFile != null && - classFile.toString().startsWith("file:") && - classFile.toString().matches(relativePathPattern)) { - classLastModified = JAXXCompiler.URLtoFile(classFile).lastModified(); - if (log.isTraceEnabled()) { - log.trace("[" + className + "] class lastModified " + classLastModified); - } - } - - // there is a java source and is the last modified - if (javaLastModified != -1 && javaLastModified > classLastModified) { - - // java file exist and it is the last modified file, so use it - - if (SHOW_LOADING) { - log.info("from JavaFile " + javaFile); - } - - result = getClassDescriptor0( - ResolverType.JAVA_FILE, - className, - javaFile, - classLoader - ); - - if (log.isDebugEnabled()) { - log.debug("[" + className + "] loaded"); - } - return result; - } - - // use the class ... - - if (SHOW_LOADING) { - log.info("from class " + className); - } - - result = getClassDescriptor0( - ResolverType.JAVA_CLASS, - className, - classFile, - classLoader - ); - - if (log.isDebugEnabled()) { - log.debug("[" + className + "] loaded"); - } - - if (result != null) { - return result; - } - - // can NOT come here, means could not find result... - - throw new IllegalStateException( - "Can not find descriptor for " + className); - } - - protected static ClassDescriptor getClassDescriptor0( - ResolverType resolverType, - String className, - URL source, - ClassLoader classLoader) throws ClassNotFoundException { - - if (log.isDebugEnabled()) { - log.debug("Loading class descriptor for [" + className + - "] with " + resolverType); - } - - Map<ResolverType, ClassDescriptorResolver> resolvers = - getDescriptorResolvers(); - - ClassDescriptorResolver resolver = resolvers.get(resolverType); - - resolver.setClassLoader(classLoader); - - ClassDescriptor result = resolver.resolvDescriptor(className, source); - if (result != null) { - descriptors.put(className, result); - } - return result; - } - - public static Class<?> getPrimitiveBoxedClass(String className) { - if (className.equals("boolean")) { - return Boolean.class; - } - if (className.equals("byte")) { - return Byte.class; - } - if (className.equals("short")) { - return Short.class; - } - if (className.equals("int")) { - return Integer.class; - } - if (className.equals("long")) { - return Long.class; - } - if (className.equals("float")) { - return Float.class; - } - if (className.equals("double")) { - return Double.class; - } - if (className.equals("char")) { - return Character.class; - } - if (className.equals("void")) { - return Void.class; - } - return null; - } - - public static Class<?> getPrimitiveClass( - String className) throws ClassNotFoundException { - if (className.equals("boolean")) { - return boolean.class; - } - if (className.equals("byte")) { - return byte.class; - } - if (className.equals("short")) { - return short.class; - } - if (className.equals("int")) { - return int.class; - } - if (className.equals("long")) { - return long.class; - } - if (className.equals("float")) { - return float.class; - } - if (className.equals("double")) { - return double.class; - } - if (className.equals("char")) { - return char.class; - } - if (className.equals("void")) { - return void.class; - } - // detect arrays - int arrayCount = 0; - while (className.endsWith("[]")) { - arrayCount++; - className = className.substring(0, className.length() - 2); - } - Class<?> klass; - if (arrayCount > 0) { - klass = getPrimitiveClass(className); - if (klass == null) { - // none primitive array - return null; - } - // must take the boxed class, other it does not works - // to make a Class.forName("[Lchar;"); but works - // with Class.forName("[LCharacter;"); ... - klass = getPrimitiveBoxedClass(className); - className = klass.getName(); - - className = "L" + className + ";"; - while (arrayCount > 0) { - className = "[" + className; - arrayCount--; - } - //System.out.println("primitive array class "+className); - return Class.forName(className); - } - return null; - } - - public static Class<?> getClass(String className, - ClassLoader classLoader) throws ClassNotFoundException { - Class<?> klass = getPrimitiveClass(className); - if (klass != null) { - return klass; - } - // try an array of none primitive classes - int arrayCount = 0; - while (className.endsWith("[]")) { - arrayCount++; - className = className.substring(0, className.length() - 2); - } - if (arrayCount > 0) { - className = "L" + className + ";"; - while (arrayCount > 0) { - className = "[" + className; - arrayCount--; - } - } - try { - return classLoader != null ? - Class.forName(className, true, classLoader) : - Class.forName(className); - - } catch (ClassNotFoundException e) { - // perharps we are in a inner class ? - int dotIndex = className.lastIndexOf("."); - if (dotIndex > -1) { - String parentFQN = className.substring(0, dotIndex); - String simpleName = className.substring(dotIndex + 1); - try { - Class<?> parentClass = classLoader != null ? Class.forName(parentFQN, true, classLoader) : Class.forName(parentFQN); - for (Class<?> innerClass : parentClass.getClasses()) { - if (simpleName.equals(innerClass.getSimpleName())) { - return innerClass; - } - } - } catch (ClassNotFoundException e1) { - // no super class,so let the first exception throw... - } - } - throw e; - } catch (NoClassDefFoundError e) { - - throw new ClassNotFoundException(e.toString()); - } - } - -// private static MethodDescriptor createMethodDescriptor(Method javaMethod, -// ClassLoader classLoader) { -// String methodName = javaMethod.getName(); -// int modifiers = javaMethod.getModifiers(); -// String returnType = javaMethod.getReturnType().getName(); -// Class<?>[] javaParameters = javaMethod.getParameterTypes(); -// String[] parameters = new String[javaParameters.length]; -// for (int i = 0; i < parameters.length; i++) { -// parameters[i] = javaParameters[i].getName(); -// } -// return new MethodDescriptor(methodName, modifiers, returnType, parameters, classLoader); -// } -// -// private static FieldDescriptor createFieldDescriptor(Field javaField, -// ClassLoader classLoader) { -// String fieldName = javaField.getName(); -// int modifiers = javaField.getModifiers(); -// String type = javaField.getType().getName(); -// return new FieldDescriptor(fieldName, modifiers, type, classLoader); -// } -// -// private static JAXXObjectDescriptor getJAXXObjectDescriptor(Class<?> jaxxClass) { -// if (!JAXXObject.class.isAssignableFrom(jaxxClass) || -// JAXXObject.class.equals(jaxxClass)) { -// return null; -// } -// try { -// Method getJAXXObjectDescriptor = jaxxClass.getMethod("$getJAXXObjectDescriptor"); -// return (JAXXObjectDescriptor) getJAXXObjectDescriptor.invoke(null); -// } catch (NoSuchMethodException e) { -// throw new CompilerException("Expected JAXXObject " + jaxxClass.getName() + " to have a static method named $getJAXXObjectDescriptor"); -// } catch (IllegalAccessException e) { -// throw new CompilerException("Expected JAXXObject " + jaxxClass.getName() + "'s $getJAXXObjectDescriptor method to be public"); -// } catch (InvocationTargetException e) { -// throw new RuntimeException(e); -// } -// } - - public static void checkSupportClass(Class<?> handlerClass, - ClassDescriptor beanClass, - Class<?>... tagClasses) { - for (Class<?> tagClass : tagClasses) { - if (getClassDescriptor(tagClass).isAssignableFrom(beanClass)) { - return; - } - } - throw new IllegalArgumentException(handlerClass.getName() + " does not support the class " + beanClass.getName()); - } - - public static void reset() { - descriptors.clear(); - } - - public static MethodDescriptor createMethodDescriptor(Method javaMethod, - ClassLoader classLoader) { - String methodName = javaMethod.getName(); - int modifiers = javaMethod.getModifiers(); - String returnType = javaMethod.getReturnType().getName(); - Class<?>[] javaParameters = javaMethod.getParameterTypes(); - String[] parameters = new String[javaParameters.length]; - for (int i = 0; i < parameters.length; i++) { - parameters[i] = javaParameters[i].getName(); - } - return new MethodDescriptor(methodName, - modifiers, - returnType, - parameters, - classLoader - ); - } - - public static MethodDescriptor createMethodDescriptor(Constructor<?> javaMethod, - ClassLoader classLoader) { - String methodName = javaMethod.getName(); - int modifiers = javaMethod.getModifiers(); - String returnType = null; - Class<?>[] javaParameters = javaMethod.getParameterTypes(); - String[] parameters = new String[javaParameters.length]; - for (int i = 0; i < parameters.length; i++) { - parameters[i] = javaParameters[i].getName(); - } - return new MethodDescriptor(methodName, - modifiers, - returnType, - parameters, - classLoader - ); - } - - public static FieldDescriptor createFieldDescriptor(Field javaField, - ClassLoader classLoader) { - String fieldName = javaField.getName(); - int modifiers = javaField.getModifiers(); - String type = javaField.getType().getName(); - return new FieldDescriptor(fieldName, modifiers, type, classLoader); - } - - public static JAXXObjectDescriptor getJAXXObjectDescriptor(Class<?> jaxxClass) { - if (!JAXXObject.class.isAssignableFrom(jaxxClass) || - JAXXObject.class.equals(jaxxClass) || - jaxxClass.isInterface()) { - return null; - } - try { - Method getJAXXObjectDescriptor = jaxxClass.getMethod("$getJAXXObjectDescriptor"); - return (JAXXObjectDescriptor) getJAXXObjectDescriptor.invoke(null); - } catch (NoSuchMethodException e) { - throw new CompilerException("Expected JAXXObject " + jaxxClass.getName() + " to have a static method named $getJAXXObjectDescriptor"); - } catch (IllegalAccessException e) { - throw new CompilerException("Expected JAXXObject " + jaxxClass.getName() + "'s $getJAXXObjectDescriptor method to be public"); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - public static void setShowLoading(boolean b) { - SHOW_LOADING = b; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptorResolver.java b/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptorResolver.java deleted file mode 100644 index 7e4f754..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptorResolver.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.reflect; - -import java.net.URL; - -/** - * Contract of a resolver of class descriptor. - * - * The unique method {@link #resolvDescriptor(String, URL)} will returns the - * descriptor if can be found. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public abstract class ClassDescriptorResolver { - - private ClassLoader classLoader; - - private ClassDescriptorHelper.ResolverType resolverType; - - protected ClassDescriptorResolver(ClassDescriptorHelper.ResolverType resolverType) { - this.resolverType = resolverType; - } - - public ClassDescriptorHelper.ResolverType getResolverType() { - return resolverType; - } - - public ClassLoader getClassLoader() { - return classLoader; - } - - public void setClassLoader(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - /** - * @param className the fully qualified name of the class - * @param source the source of the class (java file, jaxx file, class) - * @return the descriptor of the given class - * @throws ClassNotFoundException if class descriptor could not be found. - */ - public abstract ClassDescriptor resolvDescriptor(String className, - URL source) throws ClassNotFoundException; - - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/FieldDescriptor.java b/jaxx-compiler/src/main/java/jaxx/compiler/reflect/FieldDescriptor.java deleted file mode 100644 index 4b7f6c8..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/FieldDescriptor.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.reflect; - -/** - * Mirrors the class <code>java.lang.ref.Field</code>. JAXX uses <code>ClassDescriptor</code> instead of <code>Class</code> - * almost everywhere so that it can handle circular dependencies (there can't be a <code>Class</code> object for an uncompiled - * JAXX or Java source file, and a compiler must be allow references to symbols in uncompiled source files in order to handle - * circular dependencies). - */ -public class FieldDescriptor extends MemberDescriptor { - - private String type; - - public FieldDescriptor(String name, int modifiers, String type, ClassLoader classLoader) { - super(name, modifiers, classLoader); - this.type = type; - } - - public ClassDescriptor getType() { - try { - return ClassDescriptorHelper.getClassDescriptor(type, getClassLoader()); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Type not found for field " + this, e); - } catch (Exception e) { - throw new RuntimeException("Type not found for field " + this, e); - } - } - - @Override - public String toString() { - return super.toString() + " type : [" + type + "]"; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/MemberDescriptor.java b/jaxx-compiler/src/main/java/jaxx/compiler/reflect/MemberDescriptor.java deleted file mode 100644 index 99d653b..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/MemberDescriptor.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.reflect; - -/** - * Mirrors the class <code>java.lang.ref.Member</code>. JAXX uses <code>ClassDescriptor</code> instead of <code>Class</code> - * almost everywhere so that it can handle circular dependencies (there can't be a <code>Class</code> object for an uncompiled - * JAXX or Java source file, and a compiler must be allow references to symbols in uncompiled source files in order to handle - * circular dependencies). - */ -public abstract class MemberDescriptor { - - private String name; - - private int modifiers; - - private ClassLoader classLoader; - - MemberDescriptor(String name, int modifiers, ClassLoader classLoader) { - this.name = name; - this.modifiers = modifiers; - this.classLoader = classLoader; - } - - public String getName() { - return name; - } - - public int getModifiers() { - return modifiers; - } - - protected ClassLoader getClassLoader() { - return classLoader; - } - - @Override - public String toString() { - return getClass().getName() + "[" + getName() + "]"; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/MethodDescriptor.java b/jaxx-compiler/src/main/java/jaxx/compiler/reflect/MethodDescriptor.java deleted file mode 100644 index 4f1f4b9..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/MethodDescriptor.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.reflect; - -import jaxx.compiler.JAXXCompiler; - -import java.util.Arrays; - -/** - * Mirrors the class <code>java.lang.ref.Method</code>. JAXX uses <code>ClassDescriptor</code> instead of <code>Class</code> - * almost everywhere so that it can handle circular dependencies (there can't be a <code>Class</code> object for an uncompiled - * JAXX or Java source file, and a compiler must be allow references to symbols in uncompiled source files in order to handle - * circular dependencies). - */ -public class MethodDescriptor extends MemberDescriptor { - - private String returnType; - - private String[] parameterTypes; - - public MethodDescriptor(String name, int modifiers, String returnType, String[] parameterTypes, ClassLoader classLoader) { - super(name, modifiers, classLoader); - this.returnType = returnType; - this.parameterTypes = parameterTypes; - if (JAXXCompiler.STRICT_CHECKS && Arrays.asList(parameterTypes).contains(null)) { - throw new NullPointerException(name); - } - } - - public ClassDescriptor getReturnType() { - try { - //TC 20090228 : fix bug when no return type defined (constructor method) - if (returnType == null) { - return null; - } - return ClassDescriptorHelper.getClassDescriptor(returnType); - } catch (ClassNotFoundException e) { - throw new RuntimeException("could not find return type " + returnType, e); - } - } - - public ClassDescriptor[] getParameterTypes() { - ClassDescriptor[] result = new ClassDescriptor[parameterTypes.length]; - try { - for (int i = 0; i < result.length; i++) { - if (parameterTypes[i] != null) { - result[i] = ClassDescriptorHelper.getClassDescriptor(parameterTypes[i], getClassLoader()); - } - } - return result; - } catch (ClassNotFoundException e) { - throw new RuntimeException("could not find the parameter types " + Arrays.toString(parameterTypes), e); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaClass.java b/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaClass.java deleted file mode 100644 index 6ab03de..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaClass.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.reflect.resolvers; - -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.reflect.ClassDescriptorResolver; -import jaxx.compiler.reflect.FieldDescriptor; -import jaxx.compiler.reflect.MethodDescriptor; -import jaxx.runtime.JAXXObjectDescriptor; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.net.URL; - -/** - * To obtain a class descriptor from a java source file. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class ClassDescriptorResolverFromJavaClass extends ClassDescriptorResolver { - - /** Logger */ - private static final Log log = - LogFactory.getLog(ClassDescriptorResolverFromJavaClass.class); - - public ClassDescriptorResolverFromJavaClass() { - super(ClassDescriptorHelper.ResolverType.JAVA_CLASS); - } - - @Override - public ClassDescriptor resolvDescriptor(String className, - URL source) throws ClassNotFoundException { - - if (log.isDebugEnabled()) { - log.debug("for source " + className); - } - - Class<?> javaClass = - ClassDescriptorHelper.getClass(className, getClassLoader()); - - String name = javaClass.getName(); - Package p = javaClass.getPackage(); - String packageName = p != null ? p.getName() : null; - Class<?> superclass = javaClass.getSuperclass(); - String superclassName = superclass != null ? superclass.getName() : null; - Class<?>[] interfaces = javaClass.getInterfaces(); - String[] interfaceNames = new String[interfaces.length]; - for (int i = 0; i < interfaces.length; i++) { - interfaceNames[i] = interfaces[i].getName(); - } - boolean isInterface = javaClass.isInterface(); - boolean isArray = javaClass.isArray(); - String componentTypeName = isArray ? javaClass.getComponentType().getName() : null; - ClassLoader classLoader = javaClass.getClassLoader(); - Constructor<?>[] javaConstructors = javaClass.getConstructors(); - MethodDescriptor[] constructors = new MethodDescriptor[javaConstructors.length]; - for (int i = 0; i < constructors.length; i++) { - constructors[i] = ClassDescriptorHelper.createMethodDescriptor( - javaConstructors[i], - javaClass.getClassLoader() - ); - } - Method[] javaMethods = javaClass.getMethods(); - MethodDescriptor[] methods = new MethodDescriptor[javaMethods.length]; - for (int i = 0; i < methods.length; i++) { - methods[i] = ClassDescriptorHelper.createMethodDescriptor( - javaMethods[i], - javaClass.getClassLoader() - ); - } - - Field[] javaFields = javaClass.getFields(); - FieldDescriptor[] fields = new FieldDescriptor[javaFields.length]; - for (int i = 0; i < fields.length; i++) { - fields[i] = ClassDescriptorHelper.createFieldDescriptor( - javaFields[i], - javaClass.getClassLoader() - ); - } - - Field[] javaDeclaredFields = javaClass.getDeclaredFields(); - FieldDescriptor[] declaredFields = - new FieldDescriptor[javaDeclaredFields.length]; - for (int i = 0; i < declaredFields.length; i++) { - declaredFields[i] = ClassDescriptorHelper.createFieldDescriptor( - javaDeclaredFields[i], - javaClass.getClassLoader() - ); - } - - JAXXObjectDescriptor jaxxObjectDescriptor = - ClassDescriptorHelper.getJAXXObjectDescriptor(javaClass); - - return new JavaClassClassDescriptor( - javaClass, - name, - packageName, - superclassName, - interfaceNames, - isInterface, - isArray, - componentTypeName, - jaxxObjectDescriptor, - classLoader, - constructors, - methods, - fields, - declaredFields - ); - } - - - private class JavaClassClassDescriptor extends ClassDescriptor { - - private final Class<?> javaClass; - - public JavaClassClassDescriptor( - Class<?> javaClass, - String name, - String packageName, - String superclassName, - String[] interfaceNames, - boolean anInterface, - boolean array, - String componentTypeName, - JAXXObjectDescriptor jaxxObjectDescriptor, - ClassLoader classLoader, - MethodDescriptor[] constructors, - MethodDescriptor[] methods, - FieldDescriptor[] fields, - FieldDescriptor[] declaredFields - ) { - super( - ClassDescriptorResolverFromJavaClass.this.getResolverType(), - name, - packageName, - superclassName, - interfaceNames, - anInterface, - array, - componentTypeName, - jaxxObjectDescriptor, - classLoader, - constructors, - methods, - fields, - declaredFields - ); - this.javaClass = javaClass; - } - -// @Override -// public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { -// return ClassDescriptorHelper.createFieldDescriptor(javaClass.getDeclaredField(name), -// javaClass.getClassLoader() -// ); -// } - - @Override - public MethodDescriptor getDeclaredMethodDescriptor(String name, - ClassDescriptor... parameterTypes) throws NoSuchMethodException { - try { - Class<?>[] parameterTypeClasses = new Class[parameterTypes.length]; - for (int i = 0; i < parameterTypes.length; i++) { - parameterTypeClasses[i] = Class.forName(parameterTypes[i].getName()); - } - return ClassDescriptorHelper.createMethodDescriptor(javaClass.getDeclaredMethod(name, parameterTypeClasses), javaClass.getClassLoader()); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - } - - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFile.java b/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFile.java deleted file mode 100644 index c7571d4..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFile.java +++ /dev/null @@ -1,746 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.reflect.resolvers; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXFactory; -import jaxx.compiler.java.parser.JavaParser; -import jaxx.compiler.java.parser.JavaParserTreeConstants; -import jaxx.compiler.java.parser.ParseException; -import jaxx.compiler.java.parser.SimpleNode; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.reflect.ClassDescriptorResolver; -import jaxx.compiler.reflect.FieldDescriptor; -import jaxx.compiler.reflect.MethodDescriptor; -import jaxx.compiler.tags.TagManager; -import jaxx.runtime.JAXXUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.lang.reflect.Modifier; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * To obtain a class descriptor from a java source file. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class ClassDescriptorResolverFromJavaFile extends ClassDescriptorResolver { - - /** Logger */ - private static final Log log = - LogFactory.getLog(ClassDescriptorResolverFromJavaFile.class); - - private final boolean parseMethodBody; - - public ClassDescriptorResolverFromJavaFile() { - this(false); - } - public ClassDescriptorResolverFromJavaFile(boolean parseMethodBody) { - super(ClassDescriptorHelper.ResolverType.JAVA_FILE); - this.parseMethodBody = parseMethodBody; - } - - @Override - public ClassDescriptor resolvDescriptor(String className, - URL source) throws ClassNotFoundException { - - ClassLoader classLoader = getClassLoader(); - - try { - Reader reader = new InputStreamReader(source.openStream(), "utf-8"); - try { - - String displayName = source.toString(); - if (log.isDebugEnabled()) { - log.debug("for source " + displayName); - } - JavaFileParser parser = new JavaFileParser(classLoader, parseMethodBody); - if (log.isDebugEnabled()) { - log.debug("starting parsing : " + displayName); - } - try { - parser.doParse(displayName, reader); - } catch (Exception e) { -// log.error(e.getMessage()); - throw new RuntimeException(e); - } - return new JavaFileClassDescriptor(parser, classLoader); - - } finally { - - reader.close(); - } - } catch (IOException e) { - throw new ClassNotFoundException( - "Could not resolv descriptor from source " + source, - e); - } - } - - private class JavaFileClassDescriptor extends ClassDescriptor { - - public JavaFileClassDescriptor(JavaFileParser parser, - ClassLoader classLoader) { - super( - ClassDescriptorResolverFromJavaFile.this.getResolverType(), - parser.className, - parser.packageName, - parser.superclass, - parser.interfaces.toArray(new String[parser.interfaces.size()]), - parser.isInterface, - false, - null, - parser.jaxxObjectDescriptorValue == null ? null : JAXXUtil.decodeCompressedJAXXObjectDescriptor(parser.jaxxObjectDescriptorValue), - classLoader, - parser.constructors.toArray(new MethodDescriptor[parser.constructors.size()]), - parser.methods.toArray(new MethodDescriptor[parser.methods.size()]), - parser.fields.toArray(new FieldDescriptor[parser.fields.size()]), - parser.declaredFields.toArray(new FieldDescriptor[parser.declaredFields.size()]) - ); - - } - -// @Override -// public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { -// for (FieldDescriptor descriptor : declaredFieldDescriptors) { -// if (name.equals(descriptor.getName())) { -// if (log.isDebugEnabled()) { -// log.debug("Using a declared field descriptor [" + name + "] for " + getName()); -// } -// return descriptor; -// } -// } -// throw new NoSuchFieldException(name); -// } - - @Override - public MethodDescriptor getDeclaredMethodDescriptor(String name, ClassDescriptor... parameterTypes) throws NoSuchMethodException { - throw new NoSuchMethodException(name); - } - - } - - public static class JavaFileParser { - - /** Logger */ - static private final Log log = LogFactory.getLog(JavaFileParser.class); - - /** - * the compiler used (this is a dummy compiler with no link with any file). - * - * FIXME-TC20100504 We should remove this link : should not need of a - * compiler to parse a java files. - */ - private JAXXCompiler compiler; - - /** fully qualified name of the class */ - private String className; - - /** package of the class */ - private String packageName; - - /** fully qualified name of the super class or {@code null} if no super class. */ - private String superclass; - - /** - * flag to known if we deal with an enum (the state is setted in the - * {@link #doParse(String, Reader)} method). - */ - private boolean isEnum; - - /** - * flag to known if we deal with an interface(the state is setted in the - * {@link #doParse(String, Reader)} method). - */ - private boolean isInterface; - - /** set of fully qualified names of interfaces of the class. */ - private Set<String> interfaces; - - /** public methods of the class */ - private List<MethodDescriptor> methods; - - private List<MethodDescriptor> constructors; - - /** none public methods of the class */ -// private List<MethodDescriptor> declaredMethods; - - /** public fields of the class */ - private List<FieldDescriptor> fields; - - /** none public fields of the class */ - private List<FieldDescriptor> declaredFields; - - /** - * If sets, compressed value of the $jaxxObjectDescriptor field, this means - * the class if a JAXXObject implementation. - */ - private String jaxxObjectDescriptorValue; - - public static final String[] EMPTY_STRING_ARRAY = new String[0]; - - private final boolean parseMethodBody; - - /** - * To test if a compilation unit was already parsed. If so, then stop - * parsing the java file : one parsing can only give one class - * descriptor. - * - * @since 2.4.2 - */ - private boolean firstTypeScanned; - - protected JavaFileParser(ClassLoader classLoader,boolean parseMethodBody) { - this.parseMethodBody = parseMethodBody; - //FIXME-TC-20100504 : shoudl remove this to make the parser free of jaxx :) - // We could imagine just to offers to the parser a list of namespaces - // (for class resolving)... - compiler = JAXXFactory.newDummyCompiler(classLoader); - methods = new ArrayList<>(); - constructors = new ArrayList<>(); -// declaredMethods = new ArrayList<MethodDescriptor>(); - interfaces = new HashSet<>(); - fields = new ArrayList<>(); - declaredFields = new ArrayList<>(); - superclass = Object.class.getName(); - } - - - public void doParse(String className, Reader src) throws ClassNotFoundException { - - // reset this internal state - firstTypeScanned = false; - - try { - JavaParser p = new JavaParser(src, parseMethodBody); - p.CompilationUnit(); - SimpleNode node = p.popNode(); - if (node != null) { - scanCompilationUnit(node); - if (isInterface) { - - // remove super class - superclass = null; - - // load all super classes - if (!interfaces.isEmpty()) { - for (String anInterface : interfaces) { - ClassDescriptor superclassDescriptor = ClassDescriptorHelper.getClassDescriptor(anInterface, compiler.getClassLoader()); - methods.addAll(Arrays.asList(superclassDescriptor.getMethodDescriptors())); - fields.addAll(Arrays.asList(superclassDescriptor.getFieldDescriptors())); - } - } - } - - if (isEnum) { - - // super class is always Enum - - superclass = Enum.class.getName(); - } - if (superclass != null) { - //FIXME-TC20100504 This is not good, should add nothing here - // and modify the algorithm of ClassDescriptor to go and seek - // in super classes on interfaces if required. - - ClassDescriptor superclassDescriptor = ClassDescriptorHelper.getClassDescriptor(superclass, compiler.getClassLoader()); - methods.addAll(Arrays.asList(superclassDescriptor.getMethodDescriptors())); - fields.addAll(Arrays.asList(superclassDescriptor.getFieldDescriptors())); - declaredFields.addAll(Arrays.asList(superclassDescriptor.getDeclaredFieldDescriptors())); - } - - return; - } - throw new CompilerException("Internal error: null node parsing Java file from " + src); - } catch (ParseException e) { - throw new CompilerException("Error parsing Java source code " + className + ": " + e.getMessage()); - } - } - - private void scanCompilationUnit(SimpleNode node) { - for (int i = 0; i < node.jjtGetNumChildren(); i++) { - SimpleNode child = node.getChild(i); - scanCompilationUnitChild(child); - } - } - - private void scanCompilationUnitChild(SimpleNode child) { - if (firstTypeScanned) { - - // already scan the first class of the java file - // for the moment, can not do anything else... - if (log.isWarnEnabled()) { - log.warn("There is more than one type in current file, skip next type..."); - } - return; - } - int nodeType = child.getId(); - switch (nodeType) { - case JavaParserTreeConstants.JJTPACKAGEDECLARATION: - packageName = child.getChild(1).getText().trim(); - compiler.addImport(packageName + ".*"); - - // add implicit java.lnag namespace available - compiler.addImport("java.lang.*"); - break; - case JavaParserTreeConstants.JJTIMPORTDECLARATION: - String text = child.getText().trim(); - int importIndex = text.indexOf("import"); - if (importIndex > -1) { - text = text.substring(importIndex + "import".length()).trim(); - } - if (text.endsWith(";")) { - text = text.substring(0, text.length() - 1); - } - if (log.isDebugEnabled()) { - log.debug("import " + text); - } - compiler.addImport(text); - break; - case JavaParserTreeConstants.JJTTYPEDECLARATION: - scanCompilationUnit(child); - break; - - case JavaParserTreeConstants.JJTCLASSORINTERFACEDECLARATION: - isInterface = child.firstToken.image.equals("interface"); - scanClass(child); - break; - case JavaParserTreeConstants.JJTENUMDECLARATION: - isEnum = child.firstToken.image.equals("enum"); - scanClass(child); - break; - } - } - - // scans the main ClassOrInterfaceDeclaration - - private void scanClass(SimpleNode node) { - firstTypeScanned = true; -// boolean isInterface = node.firstToken.image.equals("interface"); - className = node.firstToken.next.image; - if (packageName != null) { - className = packageName + "." + className; - } - for (int i = 0; i < node.jjtGetNumChildren(); i++) { - SimpleNode child = node.getChild(i); - int nodeType = child.getId(); - - if (nodeType == JavaParserTreeConstants.JJTIMPLEMENTSLIST) { - - if (log.isDebugEnabled()) { - log.debug("[" + className + "] Found a implements list " + child + " :: " + child.jjtGetNumChildren()); - } - - // obtain interfaces - for (int j = 0; j < child.jjtGetNumChildren(); j++) { - String rawName = child.getChild(j).getText().trim(); - - addInterface(rawName); - } - continue; - } - if (nodeType == JavaParserTreeConstants.JJTEXTENDSLIST) { - - if (isInterface) { - - // obtain interfaces - for (int j = 0; j < child.jjtGetNumChildren(); j++) { - String rawName = child.getChild(j).getText().trim(); - - addInterface(rawName); - } - continue; - } - - // this is an extends - assert child.jjtGetNumChildren() == 1 : "expected ExtendsList to have exactly one child for a non-interface class"; - String rawName = child.getChild(0).getText().trim(); - superclass = TagManager.resolveClassName(rawName, compiler); - if (superclass == null) { - throw new CompilerException("Could not find class: " + rawName); - } - if (log.isDebugEnabled()) { - log.debug("Set superClass = " + superclass); - } - } else if (nodeType == JavaParserTreeConstants.JJTCLASSORINTERFACEBODY) { - scanClassNode(child); - } - } - } - - // scans class body nodes - - private void scanClassNode(SimpleNode node) { - int nodeType = node.getId(); - - switch (nodeType) { - case JavaParserTreeConstants.JJTCLASSORINTERFACEDECLARATION: - - // TODO: handle inner classes - break; - - case JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION: - - scanConstructorDeclaration(node); - break; - - case JavaParserTreeConstants.JJTMETHODDECLARATION: - - scanMethodDeclaration(node); - break; - - case JavaParserTreeConstants.JJTFIELDDECLARATION: - - scanFieldDeclaration(node); - break; - - default: - - // go throught it - for (int i = 0; i < node.jjtGetNumChildren(); i++) { - SimpleNode child = node.getChild(i); - scanClassNode(child); - } - } - } - - - protected void scanFieldDeclaration(SimpleNode node) { - String text = node.getText(); - String declaration = text; - String value = null; - int equals = text.indexOf("="); - if (equals != -1) { - value = declaration.substring(equals + 1).trim(); - declaration = declaration.substring(0, equals); - } - declaration = declaration.trim(); - - // get modifiers of the field - - int modifiers; - if (isInterface) { - modifiers = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL; - } else { - modifiers = getModifiers(node); - } - - if (log.isDebugEnabled()) { - log.debug("field [" + declaration + "] modifiers == " + - Modifier.toString(modifiers)); - } - - String[] declarationTokens = declaration.split("\\s"); - String name = declarationTokens[declarationTokens.length - 1]; - if (name.endsWith(";")) { - name = name.substring(0, name.length() - 1).trim(); - } - String cName = declarationTokens[declarationTokens.length - 2]; - String type = TagManager.resolveClassName(cName, compiler); - - FieldDescriptor descriptor = new FieldDescriptor( - name, - modifiers, - type, - compiler.getClassLoader() - ); - - if ("$jaxxObjectDescriptor".equals(name) && value != null) { - - // we are in a jaxx object, save the value of the field - - // value have this form : = "XXX";, we just want the XXX part - int firstIndex = value.indexOf("\""); - int lastIndex = value.lastIndexOf("\""); - - jaxxObjectDescriptorValue = - value.substring(firstIndex + 1, lastIndex); - - if (log.isDebugEnabled()) { - log.debug("detected a $jaxxObjectDescriptor = " + - jaxxObjectDescriptorValue); - } - } - - if (Modifier.isPublic(modifiers)) { - - fields.add(descriptor); - } else { - - declaredFields.add(descriptor); - } - } - - protected void scanConstructorDeclaration(SimpleNode node) { - String name = null; - List<String> parameterTypes = new ArrayList<>(); - //List<String> parameterNames = new ArrayList<String>(); - for (int i = 0; i < node.jjtGetNumChildren(); i++) { - SimpleNode child = node.getChild(i); - int type = child.getId(); - - if (type == JavaParserTreeConstants.JJTMETHODDECLARATOR) { - name = child.firstToken.image.trim(); - SimpleNode formalParameters = child.getChild(0); - assert formalParameters.getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS; - for (int j = 0; j < formalParameters.jjtGetNumChildren(); j++) { - SimpleNode parameter = formalParameters.getChild(j); - String rawParameterType = parameter.getChild(1).getText().trim().replaceAll("\\.\\.\\.", "[]"); - String parameterType = TagManager.resolveClassName(rawParameterType, compiler); - if (parameterType == null && JAXXCompiler.STRICT_CHECKS) { - throw new CompilerException("could not find class '" + rawParameterType + "'"); - } - parameterTypes.add(parameterType); - //parameterNames.add(parameter.getChild(2).getText().trim()); - } - } - } - - // determine the actual modifiers - - int modifiers = getModifiers(node); - - if (isInterface) { - - modifiers = Modifier.PUBLIC; - } - if (log.isDebugEnabled()) { - log.debug("method [" + name + "] modifiers == " + Modifier.toString(modifiers)); - } - - MethodDescriptor methodDescriptor = new MethodDescriptor( - name, - modifiers, - null, - parameterTypes.toArray(new String[parameterTypes.size()]), - compiler.getClassLoader() - ); - - constructors.add(methodDescriptor); - - } - - protected void scanMethodDeclaration(SimpleNode node) { - String returnType = null; - String name = null; - List<String> parameterTypes = new ArrayList<>(); - //List<String> parameterNames = new ArrayList<String>(); - for (int i = 0; i < node.jjtGetNumChildren(); i++) { - SimpleNode child = node.getChild(i); - int type = child.getId(); - if (type == JavaParserTreeConstants.JJTRESULTTYPE) { -// returnType = TagManager.resolveClassName(child.getText().trim(), compiler); - //tchemit 2011-04-21 Remove anything before return type (like javadoc and other comments) - returnType = TagManager.resolveClassName(child.firstToken.image.trim(), compiler); - } else if (type == JavaParserTreeConstants.JJTMETHODDECLARATOR) { - name = child.firstToken.image.trim(); - SimpleNode formalParameters = child.getChild(0); - assert formalParameters.getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS; - for (int j = 0; j < formalParameters.jjtGetNumChildren(); j++) { - SimpleNode parameter = formalParameters.getChild(j); - String rawParameterType = parameter.getChild(1).getText().trim().replaceAll("\\.\\.\\.", "[]"); - String parameterType = TagManager.resolveClassName(rawParameterType, compiler); - if (parameterType == null && JAXXCompiler.STRICT_CHECKS) { - throw new CompilerException("could not find class '" + rawParameterType + "'"); - } - parameterTypes.add(parameterType); - //parameterNames.add(parameter.getChild(2).getText().trim()); - } - } - } - - // determine the actual modifiers - - int modifiers = getModifiers(node); - - if (isInterface) { - - modifiers = Modifier.PUBLIC; - } - if (log.isDebugEnabled()) { - log.debug("method [" + name + "] modifiers == " + Modifier.toString(modifiers)); - } - - MethodDescriptor methodDescriptor = new MethodDescriptor( - name, - modifiers, - returnType, - parameterTypes.toArray(new String[parameterTypes.size()]), - compiler.getClassLoader() - ); - - if (Modifier.isPublic(modifiers)) { - - methods.add(methodDescriptor); - } else { - - //TODO At the moment, do not deal with it... -// declaredMethods.add(methodDescriptor); - } - } - - protected void addInterface(String rawName) { - if (rawName.contains("<")) { - - // generic type - rawName = rawName.substring(0, rawName.indexOf("<")); - } - if (log.isDebugEnabled()) { - log.debug("[" + className + "] try to obtain type of interface " + rawName); - } - - String myInterface = resolveFullyQualifiedName(rawName); - if (myInterface == null) { - throw new CompilerException("Could not find interface: " + myInterface); - } - if (!interfaces.contains(myInterface)) { - if (log.isDebugEnabled()) { - log.debug("[" + className + "] add interface " + myInterface); - } - interfaces.add(myInterface); - } - } - - protected String resolveFullyQualifiedName(String rawName) { - String result; - - String realRawName = null; - String realParentRawName = null; - if (rawName.contains(".")) { - // this is a inner class - int index = rawName.lastIndexOf("."); - realParentRawName = rawName.substring(0, index); - realRawName = rawName.substring(index + 1); - - if (log.isDebugEnabled()) { - log.debug("inner class detected ? " + realParentRawName + "//" + realRawName); - } - } - - if (log.isDebugEnabled()) { - log.debug("try fqn = " + rawName); - } - result = TagManager.resolveClassName(rawName, compiler); - - if (result != null) { - // interface is detected fine (fqn was used or in good package ?) - return result; - } - - String suffix = "." + rawName; - - if (realParentRawName != null) { - suffix = "." + realParentRawName; - } - - for (String aClass : compiler.getImportedClasses()) { - - if (aClass.endsWith(suffix)) { - - // found the class as an already knwon class - - if (realRawName != null) { - aClass += "." + realRawName; - } - - return aClass; - } - } - - // try on packages - - Set<String> importedPackages = compiler.getImportedPackages(); - - for (String aClass : importedPackages) { - String fqn = aClass + rawName; - - if (log.isDebugEnabled()) { - log.debug("try fqn = " + fqn); - } - result = TagManager.resolveClassName(fqn, compiler); - if (result != null) { - return result; - } - } - - // nothing was found - return null; - } - - protected int getModifiers(SimpleNode node) { - SimpleNode parentNode = node.getParent(); - for (int i = 0; i < parentNode.jjtGetNumChildren(); i++) { - SimpleNode child = parentNode.getChild(i); - if (child.getId() == JavaParserTreeConstants.JJTMODIFIERS) { - String modifiersStr = child.getText().trim(); - return scanModifiers(modifiersStr); - } - } - return 0; - } - - protected int scanModifiers(String modifiersStr) { - int modifiers = 0; - if (modifiersStr.contains("public")) { - modifiers |= Modifier.PUBLIC; - } - if (modifiersStr.contains("protected")) { - modifiers |= Modifier.PROTECTED; - } - if (modifiersStr.contains("private")) { - modifiers |= Modifier.PRIVATE; - } - if (modifiersStr.contains("static")) { - modifiers |= Modifier.STATIC; - } - if (modifiersStr.contains("final")) { - modifiers |= Modifier.FINAL; - } - if (modifiersStr.contains("volatile")) { - modifiers |= Modifier.VOLATILE; - } - if (modifiersStr.contains("transient")) { - modifiers |= Modifier.TRANSIENT; - } - if (modifiersStr.contains("synchronized")) { - modifiers |= Modifier.SYNCHRONIZED; - } - if (modifiersStr.contains("abstract")) { - modifiers |= Modifier.ABSTRACT; - } - return modifiers; - } - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJaxxFile.java b/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJaxxFile.java deleted file mode 100644 index fff0079..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJaxxFile.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.reflect.resolvers; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXEngine; -import jaxx.compiler.JAXXFactory; -import jaxx.compiler.SymbolTable; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.reflect.ClassDescriptorResolver; -import jaxx.compiler.reflect.FieldDescriptor; -import jaxx.compiler.reflect.MethodDescriptor; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.JAXXObjectDescriptor; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.lang.reflect.Modifier; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -/** - * To obtain a class descriptor from a java source file. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class ClassDescriptorResolverFromJaxxFile extends ClassDescriptorResolver { - - /** Logger */ - private static final Log log = - LogFactory.getLog(ClassDescriptorResolverFromJaxxFile.class); - - public ClassDescriptorResolverFromJaxxFile() { - super(ClassDescriptorHelper.ResolverType.JAXX_FILE); - } - - @Override - public ClassDescriptor resolvDescriptor(String className, URL source) throws ClassNotFoundException { - - JAXXEngine engine = JAXXFactory.getEngine(); - - JAXXCompiler compiler = engine.getJAXXCompiler(className); - - SymbolTable symbolTable = compiler.getSymbolTable(); - - if (symbolTable == null) { - throw new CompilerException("Internal error: no symbol table was generated for class '" + className + "'"); - } - - if (log.isDebugEnabled()) { - log.debug("for compiler " + compiler.getOutputClassName()); - } - - ClassLoader classLoader = getClassLoader(); - - ClassDescriptor superclass = - ClassDescriptorHelper.getClassDescriptor( - symbolTable.getSuperclassName(), classLoader); - // tchemit 2011-02-18 Be ware!!! - // this is nearly impossible to obtain consturctors from symbol table. - // let says for the moment this data is not available here and must be found in other places... - // Anyway, the only reason of finding constructor is when we want to generate a jaxx file - // If it inheritate from another jaxx file, we will mkae sure order is ok for this... - - List<MethodDescriptor> constructors = new ArrayList<>(); - List<MethodDescriptor> publicMethods = symbolTable.getScriptMethods(); - List<FieldDescriptor> publicFields = symbolTable.getScriptFields(); - //List<MethodDescriptor> declaredMethods = new ArrayList<MethodDescriptor>(publicMethods); - //List<FieldDescriptor> declaredFields = new ArrayList<FieldDescriptor>(publicFields); - Iterator<MethodDescriptor> methods = publicMethods.iterator(); - while (methods.hasNext()) { - MethodDescriptor method = methods.next(); - if (!Modifier.isPublic(method.getModifiers())) { - methods.remove(); - } - } - Iterator<FieldDescriptor> fields = publicFields.iterator(); - while (fields.hasNext()) { - FieldDescriptor field = fields.next(); - if (!Modifier.isPublic(field.getModifiers())) { - fields.remove(); - } - } - Set<String> interfaces = new HashSet<>(); - if (symbolTable.getInterfaces() != null) { - // having interfaces - for (String anInterface : symbolTable.getInterfaces()) { - int genericIndex = anInterface.indexOf("<"); - if (genericIndex > -1) { - // remove generic type - anInterface = anInterface.substring(0, genericIndex); - } - if (log.isDebugEnabled()) { - log.debug("getting interface " + anInterface + " descriptor for class " + className); - } - interfaces.add(anInterface); - ClassDescriptor interfaceclass = ClassDescriptorHelper.getClassDescriptor(anInterface, classLoader); - publicMethods.addAll(Arrays.asList(interfaceclass.getMethodDescriptors())); - publicFields.addAll(Arrays.asList(interfaceclass.getFieldDescriptors())); - } - } - publicMethods.addAll(Arrays.asList(superclass.getMethodDescriptors())); - publicFields.addAll(Arrays.asList(superclass.getFieldDescriptors())); - int dotPos = className.lastIndexOf("."); - String packageName = dotPos != -1 ? className.substring(0, dotPos) : null; - - ClassDescriptor[] superclassInterfaces = superclass.getInterfaces(); - for (ClassDescriptor superclassInterface : superclassInterfaces) { - interfaces.add(superclassInterface.getName()); - } - interfaces.add(JAXXObject.class.getName()); - return new JaxxFileClassDescriptor( - compiler, - className, - packageName, - interfaces, - classLoader, - constructors.toArray(new MethodDescriptor[constructors.size()]), - publicMethods.toArray(new MethodDescriptor[publicMethods.size()]), - publicFields.toArray(new FieldDescriptor[publicFields.size()]) - ); - } - - private class JaxxFileClassDescriptor extends ClassDescriptor { - - private final JAXXCompiler compiler; - - public JaxxFileClassDescriptor(JAXXCompiler compiler, - String className, - String packageName, - Set<String> interfaces, - ClassLoader classLoader, - MethodDescriptor[] constructors, - MethodDescriptor[] publicMethods, - FieldDescriptor[] publicFields) { - super(ClassDescriptorResolverFromJaxxFile.this.getResolverType(), - className, - packageName, - compiler.getSymbolTable().getSuperclassName(), - interfaces.toArray(new String[interfaces.size()]), - false, - false, - null, - null, - classLoader, - constructors, - publicMethods, - publicFields - ); - this.compiler = compiler; - } - - @Override - public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { - String type = compiler.getSymbolTable().getClassTagIds().get(name); - if (type != null) { - return new FieldDescriptor(name, Modifier.PROTECTED, type, compiler.getClassLoader()); - } - throw new NoSuchFieldException(name); - } - - @Override - public MethodDescriptor getDeclaredMethodDescriptor(String name, ClassDescriptor... parameterTypes) throws NoSuchMethodException { - throw new NoSuchMethodException(name); - } - - @Override - public JAXXObjectDescriptor getJAXXObjectDescriptor() { - return compiler.getJAXXObjectDescriptor(); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/script/ScriptInitializer.java b/jaxx-compiler/src/main/java/jaxx/compiler/script/ScriptInitializer.java deleted file mode 100644 index e7a1cc2..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/script/ScriptInitializer.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.script; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptorHelper; - -/** - * A dummy CompiledObject which serves to initialize scripted field. This is handled by - * a CompiledObject rather than (say) simply inlining the initialization code in order to - * ensure that the field is initialized in document order. - */ -public class ScriptInitializer extends CompiledObject { - - public ScriptInitializer(String initializer, JAXXCompiler compiler) { -// super(compiler.getAutoId(ClassDescriptorHelper.getClassDescriptor(ScriptInitializer.class)), - super(compiler.getAutoId(ScriptInitializer.class.getSimpleName()), - ClassDescriptorHelper.getClassDescriptor(ScriptInitializer.class), compiler, false); - appendInitializationCode(initializer); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/script/ScriptManager.java b/jaxx-compiler/src/main/java/jaxx/compiler/script/ScriptManager.java deleted file mode 100644 index 5403f8e..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/script/ScriptManager.java +++ /dev/null @@ -1,482 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.script; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.java.JavaArgument; -import jaxx.compiler.java.JavaConstructor; -import jaxx.compiler.java.JavaElementFactory; -import jaxx.compiler.java.parser.JavaParser; -import jaxx.compiler.java.parser.JavaParserTreeConstants; -import jaxx.compiler.java.parser.SimpleNode; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.FieldDescriptor; -import jaxx.compiler.reflect.MethodDescriptor; -import jaxx.compiler.tags.TagManager; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.StringReader; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class ScriptManager { - - private JAXXCompiler compiler; - - public ScriptManager(JAXXCompiler compiler) { - this.compiler = compiler; - } - - /** - * Strips unnecessary curly braces from around the script, generating a warning if they are found. - * - * @param script script to trim - * @return the trimed script - */ - public String trimScript(String script) { - script = script.trim(); - if (script.startsWith("{") && script.endsWith("}")) { - compiler.reportWarning("curly braces are unnecessary for script '" + script + "'"); - script = script.substring(1, script.length() - 1); - } - return script; - } - - public void checkParse(String script) throws CompilerException { - script = trimScript(script); - JavaParser p = new JavaParser(new StringReader(script)); - while (!p.Line()) { - // ??? - } - } - - public String preprocessScript(String script) throws CompilerException { - script = trimScript(script); - StringBuilder result = new StringBuilder(); - JavaParser p = new JavaParser(new StringReader(script)); - while (!p.Line()) { - SimpleNode node = p.popNode(); - if (node != null) { - preprocessScriptNode(node, false); - result.append(node.getText()); - } - } - return result.toString(); - } - - /** - * Scans through a compound symbol (foo.bar.baz) to identify and compile - * the JAXX class it refers to, if any. - * - * @param symbol symbol to scan - */ - private void scanCompoundSymbol(String symbol) { - String[] tokens = symbol.split("\\."); - StringBuilder currentSymbol = new StringBuilder(); - for (String token : tokens) { - if (currentSymbol.length() > 0) { - currentSymbol.append('.'); - } - currentSymbol.append(token.trim()); - - String contextClass = TagManager.resolveClassName( - currentSymbol.toString(), compiler); - if (contextClass != null) { - compiler.addDependencyClass(contextClass); - } - } - } - - private void preprocessScriptNode(SimpleNode node, - boolean staticContext) throws CompilerException { - // identify static methods and initializers -- we can't fire events statically - if (node.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION) { - if (node.getParent().getChild(0).getText().contains("static")) { - staticContext = true; - } - } else if (node.getId() == JavaParserTreeConstants.JJTINITIALIZER) { - if (node.getText().trim().startsWith("static")) { - staticContext = true; - } - } - - int count = node.jjtGetNumChildren(); - for (int i = 0; i < count; i++) { - preprocessScriptNode(node.getChild(i), staticContext); - } - - int id = node.getId(); - if (id == JavaParserTreeConstants.JJTNAME || - id == JavaParserTreeConstants.JJTCLASSORINTERFACETYPE) { - scanCompoundSymbol(node.getText()); - } - //tchemit 2011-02-02 I never understand this code - //Doing at each assignment a ifre with a called "dummy value" is a none sense - // Since JAXX can handle pretty well with javaBeans I remove this code -// if (!staticContext) { -// String lhs = null; -// if (id == JavaParserTreeConstants.JJTASSIGNMENTEXPRESSION || -// id == JavaParserTreeConstants.JJTPOSTFIXEXPRESSION && node.jjtGetNumChildren() == 2) { -// lhs = ((SimpleNode) node.jjtGetChild(0)).getText().trim(); -// } else if (id == JavaParserTreeConstants.JJTPREINCREMENTEXPRESSION || -// id == JavaParserTreeConstants.JJTPREDECREMENTEXPRESSION) { -// lhs = ((SimpleNode) node.jjtGetChild(0)).getText().trim(); -// } -// if (lhs != null) { -// FieldDescriptor[] fields = compiler.getScriptFields(); -// for (FieldDescriptor field : fields) { -// if (field.getName().equals(lhs)) { -// //lhs.substring(lhs.lastIndexOf(".") + 1); -// String prefix = compiler.getImportedType(JAXXUtil.class); -// node.firstToken.image = prefix + ".assignment(" + node.firstToken.image; -// String outputClassName = compiler.getImportedType(compiler.getOutputClassName()); -// node.lastToken.image = node.lastToken.image + ", \"" + lhs + "\", " + outputClassName + ".this)"; -// } -// } -// } -// } - } - - /** - * Examines a Line to determine its real type. As all tokens returned by the parser are Lines, and - * they are just a tiny wrapper around the real node, this method strips off the wrapper layers to identify - * the real type of a node. - * - * @param line line to scan - * @return the line type - */ - private int getLineType(SimpleNode line) { - if (line.jjtGetNumChildren() == 1) { - SimpleNode node = line.getChild(0); - if (node.getId() == JavaParserTreeConstants.JJTBLOCKSTATEMENT) { - if (node.jjtGetNumChildren() == 1) { - return node.getChild(0).getId(); - } - } else if (node.getId() == JavaParserTreeConstants.JJTCLASSORINTERFACEBODYDECLARATION) { - int id = node.getChild(0).getId(); - if (id == JavaParserTreeConstants.JJTMODIFIERS) { - return node.getChild(1).getId(); - } - if (id == JavaParserTreeConstants.JJTINITIALIZER) { - return id; - } - } - return node.getId(); - } - return JavaParserTreeConstants.JJTLINE; // generic value implying that it's okay to put into the initializer block - } - - private SimpleNode findExplicitConstructorInvocation(SimpleNode parent) { - if (parent.getId() == JavaParserTreeConstants.JJTEXPLICITCONSTRUCTORINVOCATION) { - return parent; - } - - int count = parent.jjtGetNumChildren(); - for (int i = 0; i < count; i++) { - SimpleNode result = findExplicitConstructorInvocation(parent.getChild(i)); - if (result != null) { - return result; - } - } - return null; - } - - private void processConstructor(String modifiers, SimpleNode node) { - assert node.getId() == JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION : "expected node to be ConstructorDeclaration, found " + JavaParserTreeConstants.jjtNodeName[node.getId()] + " instead"; - assert node.getChild(0).getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS : "expected node 0 to be FormalParameters, found " + JavaParserTreeConstants.jjtNodeName[node.getChild(1).getId()] + " instead"; - String code = ""; - if (node.getChild(0).jjtGetNumChildren() == 0) { - compiler.reportError("The default no-argument constructor may not be redefined"); - } else { - SimpleNode explicitConstructorInvocation = findExplicitConstructorInvocation(node); - if (explicitConstructorInvocation == null || explicitConstructorInvocation.getText().trim().startsWith("super(")) { - code = "$initialize();" + JAXXCompiler.getLineSeparator(); - if (explicitConstructorInvocation == null) { - node.getChild(1).firstToken.image = node.getChild(1).firstToken.image; - } else { - explicitConstructorInvocation.lastToken.image += code; - } - } - } - - compiler.appendBodyCode(modifiers + " " + node.getText().substring(0, node.getText().length() - 1) + code + "}"); - } - - private void processConstructor(SimpleNode mainNode) { - - compiler.registerInitializer(new RegisterConstructor(mainNode)); - } - - - /** Logger */ - static private final Log log = LogFactory.getLog(ScriptManager.class); - - private void scanScriptNode(SimpleNode node) throws CompilerException { - int nodeType = getLineType(node); - if (nodeType == JavaParserTreeConstants.JJTIMPORTDECLARATION) { - // have to handle imports early so the preprocessing takes them into account - String text = node.getChild(0).getText().trim(); - if (text.startsWith("import")) { - text = text.substring("import".length()).trim(); - } - if (text.endsWith(";")) { - text = text.substring(0, text.length() - 1); - } - compiler.addImport(text); - } - - preprocessScriptNode(node, false); - - if (nodeType == JavaParserTreeConstants.JJTIMPORTDECLARATION) { - // do nothing, already handled above - } else if (nodeType == JavaParserTreeConstants.JJTMETHODDECLARATION) { - String returnType = null; - String name = null; - List<String> parameterTypes = new ArrayList<>(); - //List<String> parameterNames = new ArrayList<String>(); - SimpleNode methodDeclaration = node.getChild(0).getChild(1); - assert methodDeclaration.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION; - for (int i = 0; i < methodDeclaration.jjtGetNumChildren(); i++) { - SimpleNode child = methodDeclaration.getChild(i); - int type = child.getId(); - if (type == JavaParserTreeConstants.JJTRESULTTYPE) { - String rawReturnType = child.getText().trim(); - returnType = TagManager.resolveClassName(rawReturnType, compiler); - // FIXME: this check fails for inner classes defined in this file - //if (returnType == null) - // throw new CompilerException("could not find class '" + rawReturnType + "'"); - } else if (type == JavaParserTreeConstants.JJTMETHODDECLARATOR) { - name = child.firstToken.image.trim(); - SimpleNode formalParameters = child.getChild(0); - assert formalParameters.getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS; - for (int j = 0; j < formalParameters.jjtGetNumChildren(); j++) { - SimpleNode parameter = formalParameters.getChild(j); - String rawParameterType = parameter.getChild(1).getText().trim().replaceAll("\\.\\.\\.", "[]"); - String parameterType = TagManager.resolveClassName(rawParameterType, compiler); - // FIXME: this check fails for inner classes defined in this file - //if (parameterType == null) - // throw new CompilerException("could not find class '" + rawParameterType + "'"); - parameterTypes.add(parameterType); - //parameterNames.add(parameter.getChild(2).getText().trim()); - } - } - } - compiler.appendBodyCode(node.getText()); - compiler.addScriptMethod(new MethodDescriptor(name, Modifier.PUBLIC, returnType, parameterTypes.toArray(new String[parameterTypes.size()]), compiler.getClassLoader())); - } else if (nodeType == JavaParserTreeConstants.JJTCLASSORINTERFACEDECLARATION || - nodeType == JavaParserTreeConstants.JJTINITIALIZER) { - String str = node.getText().trim(); - if (str.endsWith(";")) { - str += ";"; - } - compiler.appendBodyCode(str); - } else if (nodeType == JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION) { - processConstructor(node); -// processConstructor(node.getChild(0).getChild(0).getText(), node.getChild(0).getChild(1)); - } else if (nodeType == JavaParserTreeConstants.JJTLOCALVARIABLEDECLARATION || nodeType == JavaParserTreeConstants.JJTFIELDDECLARATION) { - // the "local" variable declarations in this expression aren't actually local -- they are flagged local - // just because there isn't an enclosing class scope visible to the parser. "Real" local variable - // declarations won't show up here, because they will be buried inside of methods. - String text = node.getText().trim(); - if (!text.endsWith(";")) { - text += ";"; - } - String declaration = text; - int equals = text.indexOf("="); - if (equals != -1) { - declaration = declaration.substring(0, equals); - } - declaration = declaration.trim(); - if (declaration.contains("<")) { - - // generic declaration detected - - if (log.isDebugEnabled()) { - log.debug("Found a declaration with generics : " + declaration); - } - - int last = declaration.lastIndexOf('>'); - - // copy everything before first '<' - String newDeclaration = declaration.substring(0, declaration.indexOf('<')); - if (last < declaration.length()) { - - // copy everithing after last '>' - newDeclaration += declaration.substring(last + 1); - } - - if (log.isDebugEnabled()) { - log.debug("==> declaration without generics : " + newDeclaration); - } - declaration = newDeclaration; - } - - String[] declarationTokens = declaration.split("\\s"); - boolean isFinal = Arrays.asList(declarationTokens).contains("final"); - boolean isStatic = Arrays.asList(declarationTokens).contains("static"); - String name = declarationTokens[declarationTokens.length - 1]; - if (name.endsWith(";")) { - name = name.substring(0, name.length() - 1).trim(); - } - String className = declarationTokens[declarationTokens.length - 2]; - if (log.isDebugEnabled()) { - log.debug("Found type : " + className + " : " + - Arrays.toString(declarationTokens)); - } - String type = TagManager.resolveClassName(className, compiler); - if (type == null) { - - throw new CompilerException( - "Could not find type of " + className + - " for expression " + text); - } - compiler.addScriptField(new FieldDescriptor(name, - Modifier.PUBLIC, - type, - compiler.getClassLoader()) - ); - // TODO: determine the actual modifiers - if (equals != -1 && !isFinal && !isStatic) { - - // declare the field in the class body, but wait to actually initialize it - compiler.appendBodyCode(text.substring(0, equals).trim() + ";"); - String initializer = text.substring(equals + 1).trim(); - if (type.endsWith("[]")) { - initializer = "new " + type + " " + initializer; - } - final String finalInitializer = name + " = " + initializer; - compiler.registerInitializer(new Runnable() { - - @Override - public void run() { - compiler.registerCompiledObject(new ScriptInitializer( - finalInitializer, compiler)); - } - }); - } else { - compiler.appendBodyCode(text); - } - compiler.appendBodyCode("\n"); - } else { - String text = node.getText().trim(); - if (text.length() > 0) { - if (!text.endsWith(";")) { - text += ";"; - } - compiler.appendInitializerCode(text); - } - } - } - - public void registerScript(String script) throws CompilerException { - JavaParser p = new JavaParser(new StringReader(script)); - while (!p.Line()) { - SimpleNode node = p.popNode(); - if (node != null) { - scanScriptNode(node); - } - } - } - - class RegisterConstructor implements Runnable { - - final SimpleNode mainNode; - - public RegisterConstructor(SimpleNode mainNode) { - this.mainNode = mainNode; - } - - @Override - public void run() { - - String className = mainNode.getChild(0).getChild(1).firstToken.image; - String modifiers = mainNode.getChild(0).getChild(0).getText(); - - SimpleNode node = mainNode.getChild(0).getChild(1); - int nbArguments = node.getChild(0).jjtGetNumChildren(); - if (log.isDebugEnabled()) { - log.debug("Constructor found with " + nbArguments + " arguments : " + node.getText()); - } - assert node.getId() == JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION : "expected node to be ConstructorDeclaration, found " + JavaParserTreeConstants.jjtNodeName[node.getId()] + " instead"; - assert node.getChild(0).getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS : "expected node 0 to be FormalParameters, found " + JavaParserTreeConstants.jjtNodeName[node.getChild(1).getId()] + " instead"; - SimpleNode params = node.getChild(0); - StringBuilder bodyC = new StringBuilder(); - for (int i = 1; i < node.jjtGetNumChildren(); i++) { - bodyC.append(node.getChild(i).getText()); - } - String bodyContent = bodyC.toString().trim(); - JavaArgument[] arguments = new JavaArgument[nbArguments]; - for (int i = 0; i < nbArguments; i++) { - SimpleNode param = params.getChild(i); - String paramType = param.getChild(0).firstToken.image; - ClassDescriptor type = TagManager.resolveClass(paramType, compiler); - String paramName = param.getChild(2).firstToken.image; - if (log.isDebugEnabled()) { - log.debug("Parameter n°" + i + " --> [" + type + " : " + paramName + "]"); - } - JavaArgument arg = JavaElementFactory.newArgument(type.getName(), paramName); - arguments[i] = arg; - } - String[] modifierSplit = modifiers.trim().split("\\s"); - if (log.isDebugEnabled()) { - log.debug("Modifiers = " + Arrays.toString(modifierSplit)); - } - int finalModifiers = 0; - for (String mod : modifierSplit) { - mod = mod.trim(); - if ("public".equals(mod)) { - finalModifiers = Modifier.PUBLIC; - break; - } - if ("protected".equals(mod)) { - finalModifiers = Modifier.PROTECTED; - break; - } - if ("private".equals(mod)) { - finalModifiers = Modifier.PRIVATE; - break; - } - } - - if (!bodyContent.endsWith("$initialize();")) { - bodyContent += JAXXCompiler.getLineSeparator() + " $initialize();"; - } - if (log.isDebugEnabled()) { - log.debug("Final modifier to use : " + Modifier.toString(finalModifiers)); - log.debug("Constructor body :\n" + bodyContent); - } - JavaConstructor constructorMethod = JavaElementFactory.newConstructor( - finalModifiers, - className, - bodyContent, - arguments - ); - - compiler.getJavaFile().addConstructor(constructorMethod); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/spi/DefaultInitializer.java b/jaxx-compiler/src/main/java/jaxx/compiler/spi/DefaultInitializer.java deleted file mode 100644 index b5cf5cc..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/spi/DefaultInitializer.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.spi; - -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.beans.BeanInfoUtil; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import jaxx.compiler.tags.DefaultObjectHandler; -import jaxx.compiler.tags.ImportHandler; -import jaxx.compiler.tags.ScriptHandler; -import jaxx.compiler.tags.StyleHandler; -import jaxx.compiler.tags.TagHandler; -import jaxx.compiler.tags.TagManager; -import jaxx.compiler.tags.swing.ApplicationHandler; -import jaxx.compiler.tags.swing.CellHandler; -import jaxx.compiler.tags.swing.ItemHandler; -import jaxx.compiler.tags.swing.JAXXComboBoxHandler; -import jaxx.compiler.tags.swing.JAXXListHandler; -import jaxx.compiler.tags.swing.JAXXTabHandler; -import jaxx.compiler.tags.swing.JAXXTreeHandler; -import jaxx.compiler.tags.swing.JCheckBoxHandler; -import jaxx.compiler.tags.swing.JComboBoxHandler; -import jaxx.compiler.tags.swing.JInternalFrameHandler; -import jaxx.compiler.tags.swing.JListHandler; -import jaxx.compiler.tags.swing.JMenuHandler; -import jaxx.compiler.tags.swing.JPasswordFieldHandler; -import jaxx.compiler.tags.swing.JPopupMenuHandler; -import jaxx.compiler.tags.swing.JProgressBarHandler; -import jaxx.compiler.tags.swing.JRadioButtonHandler; -import jaxx.compiler.tags.swing.JScrollPaneHandler; -import jaxx.compiler.tags.swing.JSliderHandler; -import jaxx.compiler.tags.swing.JSpinnerHandler; -import jaxx.compiler.tags.swing.JSplitPaneHandler; -import jaxx.compiler.tags.swing.JTabbedPaneHandler; -import jaxx.compiler.tags.swing.JTextComponentHandler; -import jaxx.compiler.tags.swing.JToolBarHandler; -import jaxx.compiler.tags.swing.JTreeHandler; -import jaxx.compiler.tags.swing.JWindowHandler; -import jaxx.compiler.tags.swing.JXLayerHandler; -import jaxx.compiler.tags.swing.RowHandler; -import jaxx.compiler.tags.swing.TabHandler; -import jaxx.compiler.tags.swing.TableHandler; -import jaxx.compiler.tags.validator.BeanValidatorHandler; -import jaxx.compiler.tags.validator.ExcludeFieldValidatorHandler; -import jaxx.compiler.tags.validator.FieldValidatorHandler; -import jaxx.runtime.swing.Application; -import jaxx.runtime.swing.JAXXButtonGroup; -import jaxx.runtime.swing.JAXXComboBox; -import jaxx.runtime.swing.JAXXList; -import jaxx.runtime.swing.JAXXTab; -import jaxx.runtime.swing.JAXXTree; -import jaxx.runtime.swing.Table; -import jaxx.runtime.swing.editor.EnumEditor; -import jaxx.runtime.swing.editor.LocaleEditor; -import jaxx.runtime.validator.swing.SwingValidator; -import org.jdesktop.jxlayer.JXLayer; - -import javax.swing.JCheckBox; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JComboBox; -import javax.swing.JDialog; -import javax.swing.JEditorPane; -import javax.swing.JFormattedTextField; -import javax.swing.JFrame; -import javax.swing.JInternalFrame; -import javax.swing.JList; -import javax.swing.JMenu; -import javax.swing.JPasswordField; -import javax.swing.JPopupMenu; -import javax.swing.JProgressBar; -import javax.swing.JRadioButton; -import javax.swing.JRadioButtonMenuItem; -import javax.swing.JScrollPane; -import javax.swing.JSlider; -import javax.swing.JSpinner; -import javax.swing.JSplitPane; -import javax.swing.JTabbedPane; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import javax.swing.JTextPane; -import javax.swing.JToggleButton; -import javax.swing.JToolBar; -import javax.swing.JTree; -import javax.swing.JWindow; -import javax.swing.text.JTextComponent; -import java.awt.Component; - -/** - * Initializes support provided from JAXX (java, swing and validation). - * - * @plexus.component role-hint="default" role="jaxx.compiler.spi.Initializer" - */ -public class DefaultInitializer implements Initializer { - - @Override - public void initialize() { - - BeanInfoUtil.addJaxxBeanInfoPath("jaxx.runtime.swing"); - - registerDefaultNamespace("javax.swing.*", - JEditorPane.class, - JFormattedTextField.class, - JPasswordField.class, - JTextArea.class, - JTextField.class, - JTextPane.class - ); - - // - // Register tags - // - - registerTag(JAXXCompiler.JAXX_NAMESPACE, ScriptHandler.TAG_NAME, new ScriptHandler()); - registerTag(JAXXCompiler.JAXX_NAMESPACE, StyleHandler.TAG_NAME, new StyleHandler()); - registerTag(JAXXCompiler.JAXX_NAMESPACE, ImportHandler.TAG_NAME, new ImportHandler()); - - //TC-20091005 why the namespace was on awt ? ButtonGroup is from javax.swing - registerTag("javax.swing.*", "ButtonGroup", new DefaultObjectHandler(ClassDescriptorHelper.getClassDescriptor(JAXXButtonGroup.class))); -// TagManager.registerTag("java.awt.*", "ButtonGroup", new DefaultObjectHandler(ClassDescriptorHelper.getClassDescriptor(JAXXButtonGroup.class))); - - registerTag(JAXXCompiler.JAXX_NAMESPACE, TabHandler.TAG_NAME, new TabHandler()); - registerTag(JAXXCompiler.JAXX_NAMESPACE, RowHandler.TAG_NAME, new RowHandler()); - registerTag(JAXXCompiler.JAXX_NAMESPACE, CellHandler.TAG_NAME, new CellHandler()); - registerTag(JAXXCompiler.JAXX_NAMESPACE, ItemHandler.TAG_NAME, new ItemHandler()); - - - registerTag(JAXXCompiler.JAXX_NAMESPACE, BeanValidatorHandler.TAG, new BeanValidatorHandler(ClassDescriptorHelper.getClassDescriptor(SwingValidator.class))); - registerTag(JAXXCompiler.JAXX_NAMESPACE, FieldValidatorHandler.TAG, new FieldValidatorHandler()); - registerTag(JAXXCompiler.JAXX_NAMESPACE, ExcludeFieldValidatorHandler.TAG, new FieldValidatorHandler()); - - // - // Register beans - // - - registerBean(Object.class, DefaultObjectHandler.class); - registerBean(Component.class, DefaultComponentHandler.class); - - // check boxes - registerBean(JCheckBox.class, JCheckBoxHandler.class); - registerBean(JCheckBoxMenuItem.class, JCheckBoxHandler.class); - - // combo boxes - registerBean(JComboBox.class, JComboBoxHandler.class); - registerBean(EnumEditor.class, JComboBoxHandler.class); - registerBean(LocaleEditor.class, JComboBoxHandler.class); - registerBean(JAXXComboBox.class, JAXXComboBoxHandler.class); - - // radio boxes - registerBean(JRadioButton.class, JRadioButtonHandler.class); - registerBean(JRadioButtonMenuItem.class, JRadioButtonHandler.class); - registerBean(JToggleButton.class, JRadioButtonHandler.class); - - // Lists - registerBean(JList.class, JListHandler.class); - registerBean(JAXXList.class, JAXXListHandler.class); - - // Trees - registerBean(JTree.class, JTreeHandler.class); - registerBean(JAXXTree.class, JAXXTreeHandler.class); - - // Windows - registerBean(JDialog.class, JWindowHandler.class); - registerBean(JFrame.class, JWindowHandler.class); - registerBean(JWindow.class, JWindowHandler.class); - - // JXLayer - registerBean(JXLayer.class, JXLayerHandler.class); - - registerBean(Application.class, ApplicationHandler.class); - - registerBean(JInternalFrame.class, JInternalFrameHandler.class); - registerBean(JMenu.class, JMenuHandler.class); - registerBean(JPasswordField.class, JPasswordFieldHandler.class); - registerBean(JPopupMenu.class, JPopupMenuHandler.class); - registerBean(JProgressBar.class, JProgressBarHandler.class); - registerBean(JScrollPane.class, JScrollPaneHandler.class); - registerBean(JSlider.class, JSliderHandler.class); - registerBean(JSpinner.class, JSpinnerHandler.class); - registerBean(JSplitPane.class, JSplitPaneHandler.class); - registerBean(JTabbedPane.class, JTabbedPaneHandler.class); - registerBean(JTextComponent.class, JTextComponentHandler.class); - registerBean(JToolBar.class, JToolBarHandler.class); - - registerBean(Table.class, TableHandler.class); - registerBean(JAXXTab.class, JAXXTabHandler.class); - - registerBean(SwingValidator.class, BeanValidatorHandler.class); - - } - - protected void registerBean(Class<?> beanClass, - Class<? extends TagHandler> handlerClass) { - ClassDescriptor classDescriptor = - ClassDescriptorHelper.getClassDescriptor(beanClass); - - TagManager.registerBean(classDescriptor, handlerClass); - } - - protected void registerTag(String namespace, - String tagName, - TagHandler handler) { - TagManager.registerTag(namespace, tagName, handler); - } - - protected void registerDefaultNamespace(String namespace, - Class<?>... beanClass) { - - for (Class<?> c : beanClass) { - TagManager.registerDefaultNamespace(c.getSimpleName(), namespace); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/spi/Initializer.java b/jaxx-compiler/src/main/java/jaxx/compiler/spi/Initializer.java deleted file mode 100644 index a4f9389..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/spi/Initializer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.spi; - -import java.util.ServiceLoader; - -/** - * Performs SPI initialization, typically to register new tags, beans and converter. - * - * <b>Note:</b> To load such Initializer, we use the {@link ServiceLoader} mecanism. - * - * @see DefaultInitializer - */ -public interface Initializer { - - /** - * Performs SPI initialization, typically to register new - * tags, beans and converter. - */ - void initialize(); -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultComponentHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultComponentHandler.java deleted file mode 100644 index 7ac06b5..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultComponentHandler.java +++ /dev/null @@ -1,465 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.I18nHelper; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.UnsupportedAttributeException; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.SwingUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; - -import javax.swing.BorderFactory; -import javax.swing.border.TitledBorder; -import java.awt.Component; -import java.awt.Container; -import java.awt.Font; -import java.awt.event.ComponentListener; -import java.awt.event.ContainerListener; -import java.awt.event.FocusListener; -import java.awt.event.KeyEvent; -import java.beans.IntrospectionException; -import java.io.IOException; -import java.lang.reflect.Field; - -public class DefaultComponentHandler extends DefaultObjectHandler { - - - public static final String BORDER_ATTRIBUTE = "border"; - - public static final String ACTION_ICON_ATTRIBUTE = "actionIcon"; - - public static final String I18N_MNEMONIC_ATTRIBUTE = "i18nMnemonic"; - - public static final String CONTAINER_DELEGATE_ATTRIBUTE = "containerDelegate"; - - public static final String FONT_FACE_ATTRIBUTE = "font-face"; - - public static final String FONT_SIZE_ATTRIBUTE = "font-size"; - - public static final String FONT_STYLE_ATTRIBUTE = "font-style"; - - public static final String FONT_WEIGHT_ATTRIBUTE = "font-weight"; - - public static final String HEIGHT_ATTRIBUTE = "height"; - - public static final String ICON_ATTRIBUTE = "icon"; - - public static final String ICON_IMAGE_ATTRIBUTE = "iconImage"; - - public static final String NAME_ATTRIBUTE = "name"; - - public static final String WIDTH_ATTRIBUTE = "width"; - - public static final String X_ATTRIBUTE = "x"; - - public static final String Y_ATTRIBUTE = "y"; - - /** Logger */ - protected static final Log log = - LogFactory.getLog(DefaultComponentHandler.class); - - public static final String BORDER_FACTORY_PREFIX = BorderFactory.class.getSimpleName() + "."; - - public static final String TITLED_BORDER_PREFIX = TitledBorder.class.getSimpleName() + "("; - - /** container delegate (if any) */ - private String containerDelegate; - - public DefaultComponentHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, Component.class); - } - - @Override - protected void init() throws IntrospectionException { - if (jaxxBeanInfo == null) { - super.init(); - - containerDelegate = (String) getJAXXBeanInfo().getJAXXBeanDescriptor().getValue(CONTAINER_DELEGATE_ATTRIBUTE); - if (containerDelegate == null && ClassDescriptorHelper.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass().getSuperclass())) { - containerDelegate = ((DefaultComponentHandler) TagManager.getTagHandler(getBeanClass().getSuperclass())).getContainerDelegate(); - } - } - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("hasFocus", FocusListener.class); - addProxyEventInfo("isVisible", ComponentListener.class); - addProxyEventInfo("getBounds", ComponentListener.class); - addProxyEventInfo("getLocation", ComponentListener.class); - addProxyEventInfo("getLocationOnScreen", ComponentListener.class); - addProxyEventInfo("getSize", ComponentListener.class); - addProxyEventInfo("getX", ComponentListener.class); - addProxyEventInfo("getY", ComponentListener.class); - addProxyEventInfo("getWidth", ComponentListener.class); - addProxyEventInfo("getHeight", ComponentListener.class); - if (ClassDescriptorHelper.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass())) { - addProxyEventInfo("getComponentCount", ContainerListener.class); - } - } - - @Override - protected void setDefaults(CompiledObject object, - Element tag, - JAXXCompiler compiler) throws CompilerException { - super.setDefaults(object, tag, compiler); - setAttribute(object, NAME_ATTRIBUTE, object.getId(), false, compiler); - openComponent(object, tag, compiler); - } - - @Override - public void compileFirstPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - super.compileFirstPass(tag, compiler); - } - - @Override - public void compileSecondPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - super.compileSecondPass(tag, compiler); - closeComponent(compiler.getOpenComponent(), tag, compiler); - } - - protected void openComponent(CompiledObject object, - Element tag, - JAXXCompiler compiler) throws CompilerException { - String constraints = tag.getAttribute(CONSTRAINTS_ATTRIBUTE); - if (constraints != null && constraints.length() > 0) { - compiler.openComponent(object, constraints); - } else { - compiler.openComponent(object); - } - } - - protected void closeComponent(CompiledObject object, - Element tag, - JAXXCompiler compiler) throws CompilerException { - compiler.closeComponent(object); - } - - @Override - public boolean isPropertyInherited(String property) throws UnsupportedAttributeException { - return property.equals("font") || property.startsWith("font-") || property.equals("foreground") || property.equals("enabled"); - } - - @Override - public ClassDescriptor getPropertyType(CompiledObject object, - String propertyName, - JAXXCompiler compiler) throws CompilerException { - if (X_ATTRIBUTE.equals(propertyName) || - Y_ATTRIBUTE.equals(propertyName) || - WIDTH_ATTRIBUTE.equals(propertyName) || - HEIGHT_ATTRIBUTE.equals(propertyName) || - FONT_SIZE_ATTRIBUTE.equals(propertyName)) { - return ClassDescriptorHelper.getClassDescriptor(Integer.class); - } - if (FONT_FACE_ATTRIBUTE.equals(propertyName) || - FONT_STYLE_ATTRIBUTE.equals(propertyName) || - FONT_WEIGHT_ATTRIBUTE.equals(propertyName)) { - return ClassDescriptorHelper.getClassDescriptor(String.class); - } - return super.getPropertyType(object, propertyName, compiler); - } - - @Override - public String getGetPropertyCode(String id, - String name, - JAXXCompiler compiler) throws CompilerException { - if (FONT_FACE_ATTRIBUTE.equals(name)) { - return id + ".getFont().getFontName()"; - } - if (FONT_SIZE_ATTRIBUTE.equals(name)) { - return id + ".getFont().getSize()"; - } - if (FONT_WEIGHT_ATTRIBUTE.equals(name)) { - compiler.addImport(Font.class); - return "(" + id + ".getFont().getStyle() & Font.BOLD) != 0 ? \"bold\" : \"normal\""; - } - if (FONT_STYLE_ATTRIBUTE.equals(name)) { - compiler.addImport(Font.class); - return "(" + id + ".getFont().getStyle() & Font.ITALIC) != 0 ? \"italic\" : \"normal\""; - } - return super.getGetPropertyCode(id, name, compiler); - } - - @Override - public String getSetPropertyCode(String id, - String name, - String valueCode, - JAXXCompiler compiler) throws CompilerException { - if (X_ATTRIBUTE.equals(name)) { - return id + ".setLocation(" + valueCode + ", " + id + ".getY());"; - } - if (Y_ATTRIBUTE.equals(name)) { - return id + ".setLocation(" + id + ".getX(), " + valueCode + ");"; - } - if (WIDTH_ATTRIBUTE.equals(name)) { - String type = compiler.getImportedType(SwingUtil.class); -// compiler.setNeedSwingUtil(true); - // need to optimize case when both width and height are being assigned - return type + ".setComponentWidth(" + id + "," + valueCode + ");"; - } - if (HEIGHT_ATTRIBUTE.equals(name)) { -// compiler.setNeedSwingUtil(true); - String type = compiler.getImportedType(SwingUtil.class); - return type + ".setComponentHeight(" + id + "," + valueCode + ");"; - } - if (FONT_FACE_ATTRIBUTE.equals(name)) { - return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(new Font(" + valueCode + ", " + id + ".getFont().getStyle(), " + id + ".getFont().getSize()));\n}"; - } - if (FONT_SIZE_ATTRIBUTE.equals(name)) { - return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont((float) " + valueCode + "));\n}"; - } - if (FONT_WEIGHT_ATTRIBUTE.equals(name)) { - if (valueCode.equals("\"bold\"")) { - String type = compiler.getImportedType(Font.class); - return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | " + type + ".BOLD));\n}"; - } - if (valueCode.equals("\"normal\"")) { - String type = compiler.getImportedType(Font.class); - return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~" + type + ".BOLD));\n}"; - } - if (!valueCode.startsWith("\"")) { - String type = compiler.getImportedType(Font.class); - return "if (" + id + ".getFont() != null) {\n if ((" + valueCode + ").equals(\"bold\")) {\n " + - id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | " + type + ".BOLD));\n } else {\n " + - id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~" + type + ".BOLD));\n }\n}"; - } - compiler.reportError("font-weight must be either \"normal\" or \"bold\", found " + valueCode); - return ""; - } - if (FONT_STYLE_ATTRIBUTE.equals(name)) { - if (valueCode.equals("\"italic\"")) { - String type = compiler.getImportedType(Font.class); - return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | " + type + ".ITALIC));\n}"; - } - if (valueCode.equals("\"normal\"")) { - String type = compiler.getImportedType(Font.class); - return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~" + type + ".ITALIC));\n}"; - } - if (!valueCode.startsWith("\"")) { - String type = compiler.getImportedType(Font.class); - return "if (" + id + ".getFont() != null) {\n if ((" + valueCode + ").equals(\"italic\")) {\n " + - id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | " + type + ".ITALIC));\n } else {\n " + - id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~" + type + ".ITALIC));\n }\n}"; - } - compiler.reportError("font-style must be either \"normal\" or \"italic\", found " + valueCode); - return ""; - } - if (ClassDescriptorHelper.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass()) && name.equals(LAYOUT_ATTRIBUTE)) { - // handle containerDelegate (e.g. contentPane on JFrame) - String cDelegate = (String) getJAXXBeanInfo().getJAXXBeanDescriptor().getValue(CONTAINER_DELEGATE_ATTRIBUTE); - if (cDelegate != null) { - return id + '.' + cDelegate + "().setLayout(" + valueCode + ");"; - } - } - // ajout du support i18n - if (I18nHelper.isI18nableAttribute(name, compiler)) { - valueCode = I18nHelper.addI18nInvocation(id, name, valueCode, compiler); - } - - return super.getSetPropertyCode(id, name, valueCode, compiler); - } - - @Override - public void setAttribute(CompiledObject object, - String propertyName, - String stringValue, - boolean inline, - JAXXCompiler compiler) { - - if (propertyName.startsWith("_")) { - // client property - if (stringValue.startsWith("{")) { - stringValue = stringValue.substring(1, stringValue.length() - 1); - } - object.addClientProperty(propertyName.substring(1), stringValue); - //TC-20090327 rather not generating code here - //object.appendAdditionCode(object.getJavaCode() + ".putClientProperty(\"" + propertyName.substring(1) + "\", " + stringValue + ");"); - return; - } - if (BORDER_ATTRIBUTE.equals(propertyName)) { - if (stringValue.contains(BORDER_FACTORY_PREFIX)) { - compiler.addImport(BorderFactory.class); - } else if (stringValue.contains(TITLED_BORDER_PREFIX)) { - compiler.addImport(TitledBorder.class); - } - } - if (ICON_ATTRIBUTE.equals(propertyName)) { - if (!(stringValue.startsWith("{") || stringValue.endsWith("}"))) { - // this is a customized icon, add the icon creation code -// compiler.setNeedSwingUtil(true); - String type = compiler.getImportedType(SwingUtil.class); - - if (compiler.getConfiguration().isUseUIManagerForIcon()) { - stringValue = "{" + type + ".getUIManagerIcon(\"" + stringValue + "\")}"; - } else { - stringValue = "{" + type + ".createImageIcon(\"" + stringValue + "\")}"; - } - } - } else if (ICON_IMAGE_ATTRIBUTE.equals(propertyName)) { - if (!(stringValue.startsWith("{") || stringValue.endsWith("}"))) { - // this is a customized icon, add the icon creation code -// compiler.setNeedSwingUtil(true); - String type = - compiler.getImportedType(SwingUtil.class); - - if (compiler.getConfiguration().isUseUIManagerForIcon()) { - stringValue = "{" + type + ".getUIManagerIcon(\"" + stringValue + "\").getImage()}"; - } else { - stringValue = "{" + type + ".createImageIcon(\"" + stringValue + "\").getImage()}"; - } - } - } else if (ACTION_ICON_ATTRIBUTE.equals(propertyName)) { - // customized actionIcon property - if (stringValue.startsWith("{") && stringValue.endsWith("}")) { - // there is a script to define the action icon, this is forbidden - compiler.reportError("the actionIcon does not support script, remove braces..., fix the file " + compiler.getOutputClassName()); - return; - } - propertyName = ICON_ATTRIBUTE; -// compiler.setNeedSwingUtil(true); - String type = compiler.getImportedType(SwingUtil.class); - if (compiler.getConfiguration().isUseUIManagerForIcon()) { - stringValue = "{" + type + ".getUIManagerActionIcon(\"" + stringValue + "\")}"; - } else { - stringValue = "{" + type + ".createActionIcon(\"" + stringValue + "\")}"; - } - inline = true; - } else if (I18N_MNEMONIC_ATTRIBUTE.equals(propertyName)) { - propertyName = MNEMONIC_ATTRIBUTE; - stringValue = I18nHelper.addI18nMnemonicInvocation( - object, - I18N_MNEMONIC_ATTRIBUTE, - TypeManager.getJavaCode(stringValue), - compiler); - } - super.setAttribute(object, propertyName, stringValue, inline, compiler); - } - - @Override - protected void scanAttributesForDependencies(Element tag, - JAXXCompiler compiler) { - super.scanAttributesForDependencies(tag, compiler); - // check for clientProperty attributes - //FIXME make this works,... it seems jaxx compiler does not come here ? - //FIXME see the the firstPassHandler in JAXXCompiler ? - NamedNodeMap children = tag.getAttributes(); - for (int i = 0, max = children.getLength(); i < max; i++) { - Attr attr = (Attr) children.item(i); - String name = attr.getName(); - if (!name.startsWith("_")) { - continue; - } - String value = attr.getValue(); - if (value.startsWith("{")) { - compiler.reportWarning(tag, "an clientProperty attribute " + name.substring(1) + " does not required curly value but was : " + value, 0); - } - } - - } - - /** - * Maps string values onto integers, so that int-valued enumeration properties can be specified by strings. For - * example, when passed a key of 'alignment', this method should normally map the values 'left', 'center', and - * 'right' onto SwingConstants.LEFT, SwingConstants.CENTER, and SwingConstants.RIGHT respectively. - * - * You do not normally need to call this method yourself; it is invoked by {@link #convertFromString} when an - * int-valued property has a value which is not a valid number. By default, this method looks at the - * <code>enumerationValues</code> value of the <code>JAXXPropertyDescriptor</code>. - * - * @param key the name of the int-typed property - * @param value the non-numeric value that was specified for the property - * @throws IllegalArgumentException if the property is an enumeration, but the value is not valid - * @throws NumberFormatException if the property is not an enumeration - */ - @Override - protected int constantValue(String key, String value) { - if (key.equals(MNEMONIC_ATTRIBUTE) || - key.equals(DISPLAYED_MNEMONIC_ATTRIBUTE)) { - if (value.length() == 1) { - return value.charAt(0); - } - try { - Field vk = KeyEvent.class.getField(value); - return (Integer) vk.get(null); - } catch (NoSuchFieldException e) { - throw new IllegalArgumentException("mnemonics must be either a single character or the name of a field in KeyEvent (found: '" + value + "')"); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - return super.constantValue(key, value); - } - - /** - * Returns <code>true</code> if this component can contain other components. For children to be - * allowed, the component must be a subclass of <code>Container</code> and its <code>JAXXBeanInfo</code> - * must not have the value <code>false</code> for its <code>isContainer</code> value. - * - * @return <code>true</code> if children are allowed - */ - public boolean isContainer() { - boolean container = ClassDescriptorHelper.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass()); -// if (container) { -// try { -// init(); -// if (Boolean.FALSE.equals(getJAXXBeanInfo().getJAXXBeanDescriptor().getValue("isContainer"))) { -// container = false; -// } -// } catch (IntrospectionException e) { -// throw new RuntimeException(e); -// } -// } - safeInit(); - if (container) { - if (Boolean.FALSE.equals(getJAXXBeanInfo().getJAXXBeanDescriptor().getValue("isContainer"))) { - container = false; - } - } - return container; - } - - public String getContainerDelegate() { -// try { -// init(); -// return containerDelegate; -// } catch (IntrospectionException e) { -// throw new RuntimeException(e); -// } - safeInit(); - return containerDelegate; - - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultObjectHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultObjectHandler.java deleted file mode 100644 index ec9b096..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultObjectHandler.java +++ /dev/null @@ -1,1350 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompiledObjectDecorator; -import jaxx.compiler.CompilerException; -import jaxx.compiler.I18nHelper; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.UnsupportedAttributeException; -import jaxx.compiler.beans.JAXXBeanInfo; -import jaxx.compiler.beans.JAXXEventSetDescriptor; -import jaxx.compiler.beans.JAXXIntrospector; -import jaxx.compiler.beans.JAXXPropertyDescriptor; -import jaxx.compiler.binding.DataBindingHelper; -import jaxx.compiler.css.StylesheetHelper; -import jaxx.compiler.java.parser.ParseException; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.reflect.FieldDescriptor; -import jaxx.compiler.reflect.MethodDescriptor; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.ComponentDescriptor; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.JAXXObjectDescriptor; -import jaxx.runtime.bean.BeanTypeAware; -import jaxx.runtime.css.Stylesheet; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; - -import java.awt.BorderLayout; -import java.awt.GridLayout; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.io.IOException; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; - -/** - * Default handler for class tags. Class tags are tags which represent instances of Java classes, - * such as <code><JButton label='Close'/></code>. <code>DefaultObjectHandler</code> - * provides support for attributes and events which adhere to JavaBeans naming conventions as - * well as basic JAXX features like the <code>id</code> attribute and data binding by means of - * curly braces. - * - * Throughout this class, the word "member" refers to the name of a field or method (e.g. - * <code>"getDocument"</code>) and the word "property" refers to the JavaBeans-style simple - * name of a property (e.g. <code>"document"</code>). - */ -public class DefaultObjectHandler implements TagHandler { - - /** Logger. */ - private static final Log log = LogFactory.getLog(DefaultObjectHandler.class); - - public static final String HANDLER_ATTRIBUTE = "handler"; - - public static final String ABSTRACT_ATTRIBUTE = "abstract"; - - public static final String CONSTRAINTS_ATTRIBUTE = "constraints"; - - public static final String CONSTRUCTOR_PARAMS_ATTRIBUTE = "constructorParams"; - - public static final String DECORATOR_ATTRIBUTE = "decorator"; - - public static final String DISPLAYED_MNEMONIC_ATTRIBUTE = "displayedMnemonic"; - - public static final String DISPLAYED_MNEMONIC_INDEX_ATTRIBUTE = "displayedMnemonicIndex"; - - public static final String GENERIC_TYPE_ATTRIBUTE = "genericType"; - - public static final String ID_ATTRIBUTE = "id"; - - public static final String IMPLEMENTS_ATTRIBUTE = "implements"; - - public static final String INITIALIZER_ATTRIBUTE = "initializer"; - - public static final String JAVA_BEAN_ATTRIBUTE = "javaBean"; - - public static final String LAYOUT_ATTRIBUTE = "layout"; - - public static final String MNEMONIC_ATTRIBUTE = "mnemonic"; - - public static final String STYLE_CLASS_ATTRIBUTE = "styleClass"; - - public static final String SUPER_GENERIC_TYPE_ATTRIBUTE = "superGenericType"; - - public static final String GRID_LAYOUT_PREFIX = GridLayout.class.getSimpleName() + "("; - - public static final String BORDER_LAYOUT_PREFIX = BorderLayout.class.getSimpleName() + "("; - - /** The class that this handler provides support for. */ - private ClassDescriptor beanClass; - - /** The JAXXBeanInfo for the beanClass. */ - protected JAXXBeanInfo jaxxBeanInfo; - - /** Maps property names to their respective JAXXPropertyDescriptors. */ - private Map<String, JAXXPropertyDescriptor> properties; - - /** Maps event names to their respective JAXXEventSetDescriptors. */ - private Map<String, JAXXEventSetDescriptor> events; - - /** Maps property names to their respective ProxyEventInfos. */ - private Map<String, ProxyEventInfo> eventInfos; - - /** Maps XML tags to the CompiledObjects created from them. */ - protected static Map<Element, CompiledObject> objectMap = new WeakHashMap<>(); - - public ProxyEventInfo getEventInfo(String memberName) { - return eventInfos != null ? eventInfos.get(memberName) : null; - } - - /** - * Encapsulates information about a "proxy event handler", which is an event handler that - * fires PropertyChangeEvents when it is triggered. ProxyEventInfos simplify the data binding - * system by allowing all dependencies to fire the same kind of event even if they would - * normally throw something else, like <code>DocumentEvent</code>. - */ - public static class ProxyEventInfo { - - /** The name of the method or field being proxied, e.g. "getText". */ - String memberName; - - /** The "actual" event listener for the property in question, e.g. DocumentListener. */ - ClassDescriptor listenerClass; - - /** - * In cases where a different object (such as a model) is more directly responsible for - * managing the property, this is the name of the property where that object can be - * found, e.g. "document" (which is turned into a call to "getDocument()"). This property - * is also treated as a dependency of the data binding expression, and any updates to it - * (assuming it is bound) will cause the listener to be removed from the old value and - * attached to the new value, and the data binding to be processed. - */ - String modelName; - - /** The name of the method used to add the "native" event listener, e.g. "addDocumentListener". */ - String addMethod; - - /** The name of the method used to remove the "native" event listener, e.g. "removeDocumentListener". */ - String removeMethod; - - public String getAddMethod() { - return addMethod; - } - - public ClassDescriptor getListenerClass() { - return listenerClass; - } - - public String getMemberName() { - return memberName; - } - - public String getModelName() { - return modelName; - } - - public String getRemoveMethod() { - return removeMethod; - } - } - - /** - * Creates a new <code>DefaultObjectHandler</code> which provides support for the specified class. The - * class is not actually introspected until the {@link #compileFirstPass} method is invoked. - * - * @param beanClass the class which this handler supports - */ - public DefaultObjectHandler(ClassDescriptor beanClass) { - this.beanClass = beanClass; - } - - /** - * Performs introspection on the beanClass and stores the results. - * - * @throws IntrospectionException if any pb - */ - protected void init() throws IntrospectionException { - if (jaxxBeanInfo == null) { - // perform introspection & cache the results - jaxxBeanInfo = getJAXXBeanInfo(beanClass); - - JAXXPropertyDescriptor[] propertiesArray = - jaxxBeanInfo.getJAXXPropertyDescriptors(); - properties = new HashMap<>(); - for (int i = propertiesArray.length - 1; i >= 0; i--) { - properties.put(propertiesArray[i].getName(), propertiesArray[i]); - } - - JAXXEventSetDescriptor[] eventsArray = - jaxxBeanInfo.getJAXXEventSetDescriptors(); - events = new HashMap<>(); - for (int i = eventsArray.length - 1; i >= 0; i--) { - MethodDescriptor[] methods = eventsArray[i].getListenerMethods(); - for (MethodDescriptor method : methods) { - events.put(method.getName(), eventsArray[i]); - } - } - - configureProxyEventInfo(); - } - } - - /** @return the class which this <code>DefaultObjectHandler</code> supports. */ - public ClassDescriptor getBeanClass() { - return beanClass; - } - - /** - * @return the <code>JAXXBeanInfo</code> for the class which this <code>DefaultObjectHandler</code> - * supports. - */ - public JAXXBeanInfo getJAXXBeanInfo() { - try { - init(); - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - return jaxxBeanInfo; - } - - /** - * Returns the <code>JAXXBeanInfo</code> for the specified class. - * - * @param beanClass the bean class for which to retrieve <code>JAXXBeanInfo</code> - * @return the class' <code>JAXXBeanInfo</code> - * @throws IntrospectionException if any pb - */ - public static JAXXBeanInfo getJAXXBeanInfo(ClassDescriptor beanClass) throws IntrospectionException { - return JAXXIntrospector.getJAXXBeanInfo(beanClass); - } - - /** - * Returns the type of the named property. This is the return type of the property's <code>get</code> method; - * for instance <code>JLabel</code>'s <code>text</code> property is a <code>String</code>. - * - * @param object the object being compiled - * @param propertyName the simple JavaBeans-style name of the property - * @param compiler the current <code>JAXXCompiler</code> - * @return the property's type - * @throws CompilerException if the type cannot be determined - */ - public ClassDescriptor getPropertyType(CompiledObject object, - String propertyName, - JAXXCompiler compiler) { - safeInit(); - - JAXXPropertyDescriptor property = properties.get(propertyName); - if (property != null) { - return property.getPropertyType(); - } - throw new UnsupportedAttributeException( - "property '" + propertyName + "' not found in " + object); - } - - /** - * @param name name of the property - * @return <code>true</code> if the named member is <i>bound</i> (fires <code>PropertyChangeEvent</code> - * when modified). Members are either fields (represented by the simple name of the field) or <code>get/is</code> - * methods (represented by the simple name of the method, <b>not</b> the simplified JavaBeans-style name). - * Methods which are not actually bound in their native class, but for which proxy events have been - * configured (such as <code>JTextField.getText</code>, return <code>true</code>. - * @throws UnsupportedAttributeException if attribute is not supported - */ - public boolean isMemberBound(String name) throws UnsupportedAttributeException { - safeInit(); - - if (eventInfos != null && eventInfos.containsKey(name)) { - return true; - } - - if (name.equals("getClass")) { - return false; - } - - String propertyName = null; - if (name.startsWith("get")) { - propertyName = Introspector.decapitalize(name.substring("get".length())); - } else if (name.startsWith("is")) { - propertyName = Introspector.decapitalize(name.substring("is".length())); - } - JAXXPropertyDescriptor property = propertyName != null ? - properties.get(propertyName) : null; - if (property != null) { - return property.isBound(); - } - try { - FieldDescriptor field = getBeanClass().getFieldDescriptor(name); - return Modifier.isFinal(field.getModifiers()); // final fields might as well be considered bound -- they can't be modified anyway - } catch (NoSuchFieldException e) { - throw new UnsupportedAttributeException("cannot find property '" + name + "' of " + getBeanClass()); - } - } - - public static ClassDescriptor getEventClass(ClassDescriptor listenerClass) { - return listenerClass.getMethodDescriptors()[0].getParameterTypes()[0]; - } - - /** - * Configures the event handling for members which do not fire <code>PropertyChangeEvent</code> when - * modified. The default implementation does nothing. Subclasses should override this method to call - * <code>addProxyEventInfo</code> for each member which requires special handling. - */ - protected void configureProxyEventInfo() { - } - - /** - * Configures a proxy event handler which fires <code>PropertyChangeEvents</code> when a non-bound - * member is updated. This is necessary for all fields (which cannot be bound) and for methods that are - * not bound property <code>get</code> methods. The proxy event handler will attach the specified kind - * of listener to the class and fire a <code>PropertyChangeEvent</code> whenever the listener receives - * any kind of event. - * - * Even though this method can theoretically be applied to fields (in addition to methods), it would be an - * unusual situation in which that would actually work -- as fields cannot fire events when modified, it would - * be difficult to have a listener that was always notified when a field value changed. - * - * @param memberName the name of the field or method being proxied - * @param listenerClass the type of listener which receives events when the field or method is updated - */ - public void addProxyEventInfo(String memberName, Class<?> listenerClass) { - addProxyEventInfo(memberName, listenerClass, null); - } - - /** - * Configures a proxy event handler which fires <code>PropertyChangeEvents</code> when a non-bound - * member is updated. This is necessary for all fields (which cannot be bound) and for methods that are - * not bound property <code>get</code> methods. This variant attaches a listener to a property of the - * object (such as <code>model</code>) and not the object itself, which is useful when there is a model - * that is the "real" container of the information. The proxy event handler will attach the specified kind - * of listener to the property's value (retrieved using the property's <code>get</code> method) and fire - * a <code>PropertyChangeEvent</code> whenever the listener receives any kind of event. - * - * If the property is itself bound (typically the case with models), any updates to the property's value will - * cause the listener to be removed from the old property value and reattached to the new property value, - * as well as cause a <code>PropertyChangeEvent</code> to be fired. - * - * Even though this method can theoretically be applied to fields (in addition to methods), it would be an - * unusual situation in which that would actually work -- as fields cannot fire events when modified, it would - * be difficult to have a listener that was always notified when a field value changed. - * - * @param memberName the name of the field or method being proxied - * @param listenerClass the type of listener which receives events when the field or method is updated - * @param modelName the JavaBeans-style name of the model property - */ - public void addProxyEventInfo(String memberName, - Class<?> listenerClass, - String modelName) { - String listenerName = listenerClass.getName(); - listenerName = - listenerName.substring(listenerName.lastIndexOf(".") + 1); - addProxyEventInfo(memberName, - listenerClass, - modelName, - "add" + listenerName, - "remove" + listenerName - ); - } - - // TODO: remove this temporary method, complete switchover to ClassDescriptors - - public void addProxyEventInfo(String memberName, - Class<?> listenerClass, - String modelName, - String addMethod, - String removeMethod) { - try { - ClassDescriptor classDescriptor = - ClassDescriptorHelper.getClassDescriptor( - listenerClass.getName() - ); - - addProxyEventInfo(memberName, - classDescriptor, - modelName, - addMethod, - removeMethod - ); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - /** - * Configures a proxy event handler which fires <code>PropertyChangeEvents</code> when a non-bound - * member is updated. This is necessary for all fields (which cannot be bound) and for methods that are - * not bound property <code>get</code> methods. This variant attaches a listener to a property of the - * object (such as <code>model</code>) and not the object itself, which is useful when there is a model - * that is the "real" container of the information. The proxy event handler will attach the specified kind - * of listener to the property's value (retrieved using the property's <code>get</code> method) and fire - * a <code>PropertyChangeEvent</code> whenever the listener receives any kind of event. - * - * If the property is itself bound (typically the case with models), any updates to the property's value will - * cause the listener to be removed from the old property value and reattached to the new property value, - * as well as cause a <code>PropertyChangeEvent</code> to be fired. - * - * This variant of <code>addProxyEventInfo</code> allows the names of the methods that add and remove - * the event listener to be specified, in cases where the names are not simply <code>add<listenerClassName></code> - * and <code>remove<listenerClassName></code>. - * - * Even though this method can theoretically be applied to fields (in addition to methods), it would be an - * unusual situation in which that would actually work -- as fields cannot fire events when modified, it would - * be difficult to have a listener that was always notified when a field value changed. - * - * @param memberName the name of the field or method being proxied - * @param listenerClass the type of listener which receives events when the field or method is updated - * @param modelName the JavaBeans-style name of the model property - * @param addMethod add method name - * @param removeMethod remove method name - */ - public void addProxyEventInfo(String memberName, - ClassDescriptor listenerClass, - String modelName, - String addMethod, - String removeMethod) { - ProxyEventInfo info = new ProxyEventInfo(); - info.memberName = memberName; - info.listenerClass = listenerClass; - info.modelName = modelName; - info.addMethod = addMethod; - info.removeMethod = removeMethod; - if (eventInfos == null) { - eventInfos = new HashMap<>(); - } - eventInfos.put(memberName, info); - } - - @Override - public void compileFirstPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - scanAttributesForDependencies(tag, compiler); - compileChildrenFirstPass(tag, compiler); - } - - @Override - public void compileSecondPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - safeInit(); - CompiledObject object = objectMap.get(tag); - if (object == null) { - throw new IllegalStateException( - "unable to find CompiledObject associated with tag <" + - tag.getTagName() + ">; should have been registered " + - "before second pass" - ); - } - compiler.checkOverride(object); - String constructorParams = - tag.getAttribute(CONSTRUCTOR_PARAMS_ATTRIBUTE); - if (StringUtils.isNotEmpty(constructorParams)) { - object.setConstructorParams( - compiler.getScriptManager().trimScript(constructorParams)); - } - - setDefaults(object, tag, compiler); - setAttributes(object, tag, compiler); - //TC-20091105, can apply genericType everyWhere, should just test that class is generic (not possible actually) -// if (object.getGenericTypesLength() > 0 && !(object == compiler.getRootObject() || object.isJavaBean())) { -// // can ony be apply to root object or javaBean object -// compiler.reportWarning("'genericType' attribute can only be found on root, or a javaBean object tag but was found on tag " + tag); -// object.setGenericTypes(null); -// return; -// } - compileChildrenSecondPass(tag, compiler); - } - - public void registerCompiledObject(Element tag, JAXXCompiler compiler) { - String id = tag.getAttribute(ID_ATTRIBUTE); - if (id == null || id.length() == 0) { - id = compiler.getAutoId(getBeanClass().getSimpleName()); -// id = compiler.getAutoId(getBeanClass()); - } - CompiledObject object = createCompiledObject(id, compiler); - objectMap.put(tag, object); - String styleClass = tag.getAttribute(STYLE_CLASS_ATTRIBUTE).trim(); - if (styleClass.length() > 0) { - object.setStyleClass(styleClass); - } - compiler.registerCompiledObject(object); - } - - /** - * Creates the <code>CompiledObject</code> which will represent the object - * created by this <code>TagHandler</code>. - * - * @param id the <code>CompiledObject's</code> ID. - * @param compiler compiler to use - * @return the <code>CompiledObject</code> to use - */ - protected CompiledObject createCompiledObject(String id, - JAXXCompiler compiler) { - return new CompiledObject(id, getBeanClass(), compiler); - } - - /** - * Initializes the default settings of the object, prior to setting its - * attribute values. The default implementation does nothing. - * - * @param object the object to initialize - * @param tag the tag being compiled - * @param compiler the current <code>JAXXCompiler</code> - */ - protected void setDefaults(CompiledObject object, - Element tag, - JAXXCompiler compiler) { - } - - /** - * @param property property name to test - * @return <code>true</code> if the specified property should be inherited by child components when specified - * via CSS. - * @throws UnsupportedAttributeException if attribute is not supported - */ - public boolean isPropertyInherited(String property) throws UnsupportedAttributeException { - return false; - } - - /** - * @param name name of event - * @return <code>true</code> if the specified name has the form of an event handler attribute - * (e.g. "onActionPerformed"). - */ - public boolean isEventHandlerName(String name) { - return name.length() > 2 && - name.startsWith("on") && - Character.isUpperCase(name.charAt(2)); - } - - /** - * Scans all attributes for any dependency classes and adds them to the current compilation - * set. Called by <code>compileFirstPass()</code> (it is an error to add dependencies after - * pass 1 is complete). - * - * @param tag tag to scan - * @param compiler compiler to use - */ - protected void scanAttributesForDependencies(Element tag, - JAXXCompiler compiler) { - List<Attr> attributes = new ArrayList<>(); - NamedNodeMap children = tag.getAttributes(); - for (int i = 0; i < children.getLength(); i++) { - attributes.add((Attr) children.item(i)); - } - Collections.sort(attributes, getAttributeComparator()); - - for (Attr attribute : attributes) { - String name = attribute.getName(); - String value = attribute.getValue(); - if (name.equals(JAVA_BEAN_ATTRIBUTE)) { - //compiler.preprocessScript(value); - continue; - } - if (name.equals(CONSTRAINTS_ATTRIBUTE) || - isEventHandlerName(name)) { - // adds dependencies as a side effect - compiler.preprocessScript(value); - } else if (name.equals(CONSTRUCTOR_PARAMS_ATTRIBUTE)) { - //fix bug 178 : if a constructor parameter contains a comma - // the split will not works. - // using this hack will always works :) (but still a hack) - compiler.preprocessScript("java.util.Arrays.toString(" + value + ")"); -// for (String param : value.split("\\s*,\\s*")) { -// compiler.preprocessScript(param); -// } - } else if (value.startsWith("{") && value.endsWith("}")) { - compiler.preprocessScript(value.substring(1, value.length() - 1)); - } - } - } - - /** - * Processes the attributes of an XML tag. Four kinds of attributes are supported: simple property values (of any - * datatype supported by {@link #convertFromString}), data binding expressions (attributes containing curly-brace - * pairs), event listeners (attributes starting with 'on', such as 'onActionPerformed'), and JAXX-defined properties - * such as 'id'. - * - * @param object the object to be modified - * @param tag the tag from which to pull attributes - * @param compiler the current <code>JAXXCompiler</code> - */ - public void setAttributes(CompiledObject object, - Element tag, - JAXXCompiler compiler) { - List<Attr> attributes = new ArrayList<>(); - NamedNodeMap children = tag.getAttributes(); - - for (int i = 0; i < children.getLength(); i++) { - attributes.add((Attr) children.item(i)); - } - Collections.sort(attributes, getAttributeComparator()); - - CompiledObject rootObject = compiler.getRootObject(); - - Attr genericTypeAttribute = null; - for (Attr attribute : attributes) { - String name = attribute.getName(); - String value = attribute.getValue().trim(); - if (name.equals(ID_ATTRIBUTE) || - name.equals(CONSTRAINTS_ATTRIBUTE) || - name.equals(CONSTRUCTOR_PARAMS_ATTRIBUTE) || - name.equals(STYLE_CLASS_ATTRIBUTE) || - name.startsWith(XMLNS_ATTRIBUTE) || - JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { - // ignore, already handled - continue; - } - - if (compiler.isUseHandler()) { - if (name.startsWith(HANDLER_ATTRIBUTE)) { - // ignore, already handled - continue; - } - } - if (name.equals(JAVA_BEAN_ATTRIBUTE)) { - object.setJavaBean(true); - if (!value.isEmpty()) { - object.setJavaBeanInitCode(value); - } - continue; - } - if (name.equals(INITIALIZER_ATTRIBUTE)) { - if (!value.isEmpty()) { - object.setInitializer(value); - } else { - object.setInitializer("null"); - } - continue; - } - - if (name.equals(IMPLEMENTS_ATTRIBUTE)) { - if (object != rootObject) { - // can ony be apply to root object - compiler.reportError("'" + IMPLEMENTS_ATTRIBUTE + "' attribute can only be found on root tag but was found on tag " + tag); - return; - } - //tchemit 2011-01-29 reuse what was filled in symbols table - String[] interfaces = compiler.getSymbolTable().getInterfaces(); -// String[] interfaces = value.split(","); - compiler.setExtraInterfaces(interfaces); - continue; - } - - if (name.equals(ABSTRACT_ATTRIBUTE)) { - if (object != rootObject) { - // can ony be apply to root object - compiler.reportError("'" + ABSTRACT_ATTRIBUTE + "' attribute can only be found on root tag but was found on tag " + tag); - return; - } - compiler.setAbstractClass(true); - continue; - } - - if (name.equals(GENERIC_TYPE_ATTRIBUTE)) { - //TC-20090313 check after all attributes been processed - genericTypeAttribute = attribute; - continue; - } - - if (name.equals(SUPER_GENERIC_TYPE_ATTRIBUTE)) { - if (object != rootObject) { - // can ony be apply to root object - compiler.reportError("'" + SUPER_GENERIC_TYPE_ATTRIBUTE + "' attribute can only be found on root tag but was found on tag " + tag); - return; - } - compiler.setSuperGenericType(value); - continue; - } - - if (name.equals(DECORATOR_ATTRIBUTE)) { - if (!value.isEmpty()) { - CompiledObjectDecorator decorator = - compiler.getEngine().getDecorator(value); - object.setDecorator(decorator); - } - continue; - } - - if (isEventHandlerName(name)) { - // event handler - if (!value.endsWith(";") && !value.endsWith("}")) { - value += ";"; - } - addEventHandler(object, - Introspector.decapitalize(name.substring(2)), - value, - compiler - ); - continue; - } - // simple property - setAttribute(object, name, value, true, compiler); - } - - if (genericTypeAttribute != null) { - String name = genericTypeAttribute.getName(); - String value = genericTypeAttribute.getValue().trim(); - if (object == rootObject) { - compiler.setGenericType(value); - } else { - object.setGenericTypes(value.split(",")); - if (object.getSimpleType() != null) { - - // reload the simpleType - object.setSimpleType(object.getSimpleType() + "<" + value + ">"); - } - } - if (ClassDescriptorHelper.getClassDescriptor(BeanTypeAware.class).isAssignableFrom(object.getObjectClass())) { - String fqn = compiler.getImportedTypeForSimpleName(value); - if (fqn != null) { - // add beanType from genericType - if (log.isDebugEnabled()) { - log.debug("Add beanType property: " + value + " to " + object); - } - - setAttribute(object, BeanTypeAware.PROPERTY_BEAN_TYPE, "{" + value + ".class}", true, compiler); - } - - - } - } - - } - - /** - * Returns a <code>Comparator</code> which defines the ordering in which the tag's attributes should be processed. The - * default implementation sorts the attributes according to the order defined by the {@link #getAttributeOrdering} method. - * - * @return a <code>Comparator</code> defining the order of attribute processing - */ - protected Comparator<Attr> getAttributeComparator() { - return new Comparator<Attr>() { - - @Override - public int compare(Attr a, Attr b) { - int aOrder = getAttributeOrdering(a); - int bOrder = getAttributeOrdering(b); - - return aOrder - bOrder; - } - }; - } - - /** - * Returns the priority with which a particular attribute should be processed. Lower numbers should be processed before - * higher numbers. This value is used by the {@link #getAttributeComparator} method to define the sort ordering. - * - * @param attr the attribute to treate - * @return the attribute's priority - */ - protected int getAttributeOrdering(Attr attr) { - if (attr.getName().equals(DISPLAYED_MNEMONIC_INDEX_ATTRIBUTE) || - attr.getName().equals(DISPLAYED_MNEMONIC_ATTRIBUTE) || - attr.getName().equals(MNEMONIC_ATTRIBUTE)) { - return 1; - } - return 0; - } - - /** - * Set a single property on an object. The value may be either a simple value or contain data binding expressions. - * Simple values are first converted to the property's type using {@link #convertFromString(String, String, Class)}. - * - * @param object the object on which to set the property - * @param propertyName the name of the property to set - * @param stringValue the raw string value of the property from the XML - * @param compiler the current <code>JAXXCompiler</code> - */ - public void setAttributeFromCss(CompiledObject object, - String propertyName, - String stringValue, - JAXXCompiler compiler) { - - try { - - object.addProperty(propertyName, stringValue); - ClassDescriptor type = getPropertyType(object, propertyName, compiler); - String binding = DataBindingHelper.processDataBindings(stringValue); - boolean withBinding = binding != null; - - if (!withBinding) { - // no bindings, convert from string - - // add support for i18n attributes (otherwise already done in DefaultComponentHandler) - if (I18nHelper.isI18nableAttribute(propertyName, compiler)) { - stringValue = I18nHelper.addI18nInvocation(object.getId(), propertyName, stringValue, compiler); - } - - try { - Class<?> typeClass = type != null ? - ClassDescriptorHelper.getClass(type.getName(), type.getClassLoader()) : - null; - Object value = convertFromString(propertyName, - stringValue, - typeClass - ); - setProperty(object, propertyName, value, compiler); - return; - } catch (NumberFormatException e) { - compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); - } catch (IllegalArgumentException e) { - compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); - } catch (ClassNotFoundException e) { - compiler.reportError("could not find class " + type.getName()); - } - } - String setPropertyCode = getSetPropertyCode(object.getJavaCode(), propertyName, binding, compiler); - if (propertyName.equals(LAYOUT_ATTRIBUTE)) { - - // try to add the layout class in imports - if (setPropertyCode.contains(BORDER_LAYOUT_PREFIX)) { - compiler.addImport(BorderLayout.class); - } else if (setPropertyCode.contains(GRID_LAYOUT_PREFIX)) { - compiler.addImport(GridLayout.class); - } - // handle containerDelegate (e.g. contentPane on JFrame) - // have to set layout early, before children are added - object.appendInitializationCode(setPropertyCode); - } - compiler.getBindingHelper().registerDataBinding( - object.getId() + "." + propertyName, - binding, - setPropertyCode - ); - } catch (UnsupportedAttributeException e) { - compiler.reportError("class " + object.getObjectClass().getName() + " does not support attribute '" + propertyName + "'"); - } - } - - /** - * Set a single property on an object. The value may be either a simple value or contain data binding expressions. - * Simple values are first converted to the property's type using {@link #convertFromString(String, String, Class)}. - * - * @param object the object on which to set the property - * @param propertyName the name of the property to set - * @param stringValue the raw string value of the property from the XML - * @param inline <code>true</code> if the value was directly specified as an inline class tag attribute, <code>false</code> otherwise (a default value, specified in CSS, etc.) - * @param compiler the current <code>JAXXCompiler</code> - */ - public void setAttribute(CompiledObject object, - String propertyName, - String stringValue, - boolean inline, - JAXXCompiler compiler) { - try { - //--------------------------------------------------------------------- - // BE WARE, Test if removing this code hurts..., anyway we have a bug on it: - // For some component (example : jaxx.runtime.swing.editor.NumberEditor) we do not have one component - // This is disturbing, must find how why... And this happens only on a mvn clean install on all project - // Everything is fine otherwise... - // - // With new binding design, we will know if there is a binding on the property - // of the jaxxObject, and could add it only if required... - //--------------------------------------------------------------------- - //FIXME TC-20091105 we should to this later when all binding are compiled - // because we don't know yet if this is a databinding -// if (ClassDescriptorHelper.getClassDescriptor(JAXXObject.class).isAssignableFrom(object.getObjectClass())) { -// // check for data binding & remove if found -// JAXXObjectDescriptor jaxxObjectDescriptor = object.getObjectClass().getJAXXObjectDescriptor(); -// if (jaxxObjectDescriptor.getComponentDescriptors().length == 0) { -// compiler.reportWarning("JAXXObject component " + object.getObjectClass() + " should have at least one component!"); -//// throw new IllegalStateException("JAXXObject component " + object.getObjectClass() + " should have at least one component!"); -// } else { -// ComponentDescriptor root = jaxxObjectDescriptor.getComponentDescriptors()[0]; -// //TC-20091026 do not prefix binding by object id if on root object -// String prefix; -// if (object == compiler.getRootObject()) { -// prefix = ""; -// } else { -// prefix = object.getJavaCode() + "."; -// } -// object.appendInitializationCode(prefix + "removeDataBinding(" + compiler.getJavaCode(root.getId() + "." + propertyName) + ");"); -// } -// } - object.addProperty(propertyName, stringValue); - ClassDescriptor type = getPropertyType(object, propertyName, compiler); - String binding = DataBindingHelper.processDataBindings(stringValue); - boolean withBinding = binding != null; - - if (inline) { - compiler.addInlineStyle(object, propertyName, withBinding); - } - if (!withBinding) { - // no bindings, convert from string - try { - Class<?> typeClass = type != null ? - ClassDescriptorHelper.getClass(type.getName(), type.getClassLoader()) : - null; - Object value = convertFromString(propertyName, - stringValue, - typeClass - ); - setProperty(object, propertyName, value, compiler); - return; - } catch (NumberFormatException e) { - compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); - } catch (IllegalArgumentException e) { - compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); - } catch (ClassNotFoundException e) { - compiler.reportError("could not find class " + type.getName()); - } - } - String setPropertyCode = getSetPropertyCode(object.getJavaCode(), propertyName, binding, compiler); - if (propertyName.equals(LAYOUT_ATTRIBUTE)) { - - // try to add the layout class in imports - if (setPropertyCode.contains(BORDER_LAYOUT_PREFIX)) { - compiler.addImport(BorderLayout.class); - } else if (setPropertyCode.contains(GRID_LAYOUT_PREFIX)) { - compiler.addImport(GridLayout.class); - } - // handle containerDelegate (e.g. contentPane on JFrame) - // have to set layout early, before children are added - object.appendInitializationCode(setPropertyCode); - } - compiler.getBindingHelper().registerDataBinding( - object.getId() + "." + propertyName, - binding, - setPropertyCode - ); - } catch (UnsupportedAttributeException e) { - compiler.reportError("class " + object.getObjectClass().getName() + " does not support attribute '" + propertyName + "'"); - } - } - - public void applyStylesheets(CompiledObject object, JAXXCompiler compiler) { - applyStylesheets(object, compiler, null); - } - - private void applyStylesheets(CompiledObject object, - JAXXCompiler compiler, - Stylesheet overrides) { - applyStylesheets(object, compiler, overrides, true); - } - - private void applyStylesheets(CompiledObject object, - JAXXCompiler compiler, - Stylesheet overrides, - boolean recurse) { - - Stylesheet stylesheet = compiler.getStylesheet(); - - ClassDescriptor objectClass = object.getObjectClass(); - ClassDescriptor jaxxObjectClassDescriptor = - ClassDescriptorHelper.getClassDescriptor(JAXXObject.class); - - // to apply styleSheet to a jaxx object, - // since 2.0.2, this process can be skip if configuration - // autoRecurseInCss is set to false since this does not work - boolean applyInside = - recurse && - jaxxObjectClassDescriptor.isAssignableFrom(objectClass) && - // new since 2.0.2 to skip old buggy mode - compiler.getConfiguration().isAutoRecurseInCss(); - - try { - - if (!applyInside) { - - // this is the safe mode to use, just apply stlySheet to object - if (stylesheet != null) { - StylesheetHelper.applyTo(object, - compiler, - stylesheet, - overrides - ); - } - return; - } - - //FIXME TC-20100430 This is an old mode which try to apply inside a - // detected jaxx object stysheets (cascade) : - // It does not work in fact and must be repair... - - JAXXObjectDescriptor jaxxObjectDescriptor = - objectClass.getJAXXObjectDescriptor(); - ComponentDescriptor[] descriptors = - jaxxObjectDescriptor.getComponentDescriptors(); - for (ComponentDescriptor descriptor : descriptors) { - ClassDescriptor classDescriptor = - ClassDescriptorHelper.getClassDescriptor( - descriptor.getJavaClassName() - ); - boolean isRoot = classDescriptor != objectClass; - String id = isRoot ? object.getId() + ' ' + descriptor.getId() : "( " + object.getId() + " ) " + descriptor.getId(); - CompiledObject child = new CompiledObject(id, - "((" + JAXXCompiler.getCanonicalName(classDescriptor) + ") " + - object.getJavaCode() + ".getObjectById(" + TypeManager.getJavaCode(descriptor.getId()) + "))", - classDescriptor, - compiler, - true); - ComponentDescriptor parentDescriptor = descriptor.getParent(); - CompiledObject currentObject = child; - while (parentDescriptor != null) { - CompiledObject parent = new CompiledObject("internal", ClassDescriptorHelper.getClassDescriptor(parentDescriptor.getJavaClassName()), compiler); - currentObject.setParent(parent); - currentObject = parent; - parentDescriptor = parentDescriptor.getParent(); - } - currentObject.setParent(object); - String styleClass = object.getStyleClass(); - if (styleClass == null) { - styleClass = descriptor.getStyleClass(); - } - child.setStyleClass(styleClass); - Stylesheet mergedStylesheet = overrides; - Stylesheet childOverrides = jaxxObjectDescriptor.getStylesheet(); - if (childOverrides != null) { - if (mergedStylesheet == null) { - mergedStylesheet = childOverrides; - } else { - mergedStylesheet.add(childOverrides.getRules()); - } - } - TagManager.getTagHandler(objectClass).applyStylesheets(child, compiler, mergedStylesheet, isRoot); - object.appendInitializationCode(child.getInitializationCode(compiler)); - } - } catch (ParseException e) { - compiler.reportError("Java parser exception on "+object+" in his css rules: "+e.getMessage()); - } catch (ClassNotFoundException e) { - throw new CompilerException(e); - } catch (IllegalArgumentException e) { - compiler.reportError(e.getMessage()); - } - } - - /** - * Adds the necessary Java code to a <code>CompiledObject</code> to add an event listener at runtime. - * - * @param object the <code>CompiledObject</code> to which the event listener should be added - * @param name the name of the event listener, such as <code>"actionPerformed"</code> - * @param value the Java code snippet to execute when the event is fired - * @param compiler the current <code>JAXXCompiler</code> - */ - public void addEventHandler(CompiledObject object, - String name, - String value, - JAXXCompiler compiler) { - JAXXEventSetDescriptor descriptorSet = events.get(name); - if (descriptorSet != null) { - MethodDescriptor[] listenerMethods = - descriptorSet.getListenerMethods(); - MethodDescriptor listenerMethod = null; - for (MethodDescriptor listenerMethod1 : listenerMethods) { - if (listenerMethod1.getName().equals(name)) { - listenerMethod = listenerMethod1; - break; - } - } - if (listenerMethod == null) { - throw new RuntimeException("expected to find method '" + name + "' in JAXXEventSetDescriptor.getListenerMethods()"); - } - try { - value = compiler.preprocessScript(value); - object.addEventHandler( - name, - descriptorSet.getAddListenerMethod(), - listenerMethod, - value, - compiler - ); - } catch (CompilerException e) { - compiler.reportError("While parsing event handler for '" + name + "': " + e.getMessage()); - } - } else { - compiler.reportError("could not find event '" + name + "' for object " + object); - } - } - - /** - * Returns a snippet of Java code which will retrieve an object property at runtime. Typically the code is - * just a call to the property's <code>get</code> method, but it can be arbitrarily complex. - * - * @param javaCode Java code for the object whose property is being retrieved - * @param name the name of the property to retrieve - * @param compiler the current <code>JAXXCompiler</code> - * @return the snippet - * @throws CompilerException if a compilation error occurs - */ - public String getGetPropertyCode(String javaCode, - String name, - JAXXCompiler compiler) { - safeInit(); - - JAXXPropertyDescriptor property = properties.get(name); - if (property != null) { - if (property.getReadMethodDescriptor() != null) { - return javaCode + '.' + property.getReadMethodDescriptor().getName() + "()"; - } - throw new UnsupportedAttributeException("property '" + name + "' of " + getBeanClass().getName() + " has no read method"); - } - throw new UnsupportedAttributeException("property '" + name + "' could not be found in class " + getBeanClass().getName()); - } - - /** - * Returns a snippet of Java code which will set an object property at runtime. Typically the code is - * just a call to the property's <code>set</code> method, but it can be arbitrarily complex. - * - * @param javaCode Java code for the object whose property is being set - * @param name the name of the property to set - * @param valueCode Java expression representing the value to set the property to - * @param compiler the current <code>JAXXCompiler</code> - * @return the snippet - * @throws CompilerException if a compilation error occurs - */ - public String getSetPropertyCode(String javaCode, - String name, - String valueCode, - JAXXCompiler compiler) { - JAXXPropertyDescriptor property = properties.get(name); - if (property != null) { - if (property.getWriteMethodDescriptor() != null) { - //TC-20091026 do not prefix by javaCode if on root object - String prefix; - if (compiler.getRootObject().getJavaCode().equals(javaCode)) { - prefix = ""; - } else { - prefix = javaCode + "."; - } - return prefix + property.getWriteMethodDescriptor().getName() + '(' + valueCode + ");"; - } - throw new UnsupportedAttributeException("property '" + name + "' of " + getBeanClass().getName() + " is read-only"); - } - throw new UnsupportedAttributeException("property '" + name + "' could not be found in class " + getBeanClass().getName()); - } - - /** - * Appends Java code to a <code>CompiledObject</code> in order to implement a property assignment. - * <code>setProperty</code> is invoked in response to most XML attributes (those which are not more - * complicated cases, like data bindings or event handlers). - * - * By the time it reaches this method, the <code>value</code> has already been converted from its XML - * string representation to the appropriate destination type for the property (i.e. if - * <code>JLabel.foreground</code> is being set, <code>value</code> will be a <code>Color</code>). - * - * @param object the object being modified - * @param name the name of the property to set - * @param value the value to set the property to - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if a compilation error occurs - */ - public void setProperty(CompiledObject object, - String name, - Object value, - JAXXCompiler compiler) { - object.appendInitializationCode( - getSetPropertyCode(object.getJavaCodeForProperty(name), - name, - TypeManager.getJavaCode(value), - compiler - ) - ); - } - - /** - * Maps string values onto integers, so that int-valued enumeration properties can be specified by strings. For - * example, when passed a key of 'alignment', this method should normally map the values 'left', 'center', and - * 'right' onto SwingConstants.LEFT, SwingConstants.CENTER, and SwingConstants.RIGHT respectively. - * - * You do not normally need to call this method yourself; it is invoked by {@link #convertFromString} when an - * int-valued property has a value which is not a valid number. By default, this method looks at the - * <code>enumerationValues</code> value of the <code>JAXXPropertyDescriptor</code>. - * - * @param key the name of the int-typed property - * @param value the non-numeric value that was specified for the property - * @return the constant integer value - * @throws IllegalArgumentException if the property is an enumeration, but the value is not valid - * @throws NumberFormatException if the property is not an enumeration - */ - protected int constantValue(String key, String value) { - JAXXBeanInfo JAXXBeanInfo = getJAXXBeanInfo(); - JAXXPropertyDescriptor[] props = - JAXXBeanInfo.getJAXXPropertyDescriptors(); - String lowercaseValue = value.toLowerCase(); - for (JAXXPropertyDescriptor property : props) { - if (property.getName().equals(key)) { - Object[] values = (Object[]) - property.getValue("enumerationValues"); - if (values != null) { - for (int j = 0; j < values.length - 2; j += 3) { - if (((String) values[j]).toLowerCase().equals(lowercaseValue)) { - return (Integer) values[j + 1]; - } - } - - StringBuilder message = - new StringBuilder("value of '" + - key + "' must be one of: ["); - for (int j = 0; j < values.length - 2; j += 3) { - if (j != 0) { - message.append(", "); - } - message.append(((String) values[j]).toLowerCase()); - } - message.append("] (found '").append(value).append("')"); - throw new IllegalArgumentException(message.toString()); - } - } - } - throw new NumberFormatException(value); - } - - /** - * As {@link TypeManager#convertFromString(String, Class)}, except that it additionally supports constant names - * for <code>int</code>-valued types. - * - * @param key the name of the property whose value is being converted - * @param value the raw string value of the property as it appears in the XML - * @param type the datatype to convert the string into - * @return the converted object - * @see #constantValue - */ - protected Object convertFromString(String key, String value, Class<?> type) { - if (type == null || Object.class.equals(type)) { - return value; - } - - try { - return TypeManager.convertFromString(value, type); - } catch (NumberFormatException e) { - if (int.class.equals(type) || Integer.class.equals(type)) { - return constantValue(key, value); - } - throw e; - } - } - - /** - * Compiles the child tags of the current tag. The default implementation invokes {@link #compileChildTagFirstPass} - * for each child tag. - * - * @param tag the tag whose children to run - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if a compilation error occurs - * @throws IOException if an I/O error occurs - */ - protected void compileChildrenFirstPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node node = children.item(i); - int nodeType = node.getNodeType(); - if (nodeType == Node.ELEMENT_NODE) { - Element child = (Element) node; - compileChildTagFirstPass(child, compiler); - } - } - } - - /** - * Compiles the child tags of the current tag. The default implementation invokes {@link #compileChildTagFirstPass} - * for each child tag. - * - * @param tag the tag whose children to run - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if a compilation error occurs - * @throws IOException if an I/O error occurs - */ - protected void compileChildrenSecondPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node node = children.item(i); - int nodeType = node.getNodeType(); - if (nodeType == Node.ELEMENT_NODE) { - Element child = (Element) node; - compileChildTagSecondPass(child, compiler); - } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { - String text = ((Text) node).getData().trim(); - if (text.length() > 0) { - compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); - } - } - } - } - - /** - * Compiles a child of the current tag. The default implementation calls {@link JAXXCompiler#compileFirstPass - * JAXXCompiler.compileFirstPass}. - * - * @param tag the child tag to run - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if a compilation error occurs - * @throws IOException if an I/O error occurs - */ - protected void compileChildTagFirstPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - compiler.compileFirstPass(tag); - } - - /** - * Compiles a child of the current tag. The default implementation calls {@link JAXXCompiler#compileFirstPass - * JAXXCompiler.compileSecondPass}. - * - * @param tag the child tag to run - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if a compilation error occurs - * @throws IOException if an I/O error occurs - */ - protected void compileChildTagSecondPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - compiler.compileSecondPass(tag); - } - - @Override - public String toString() { - return getClass().getName() + "[" + getBeanClass().getName() + "]"; - } - - protected void safeInit() { - try { - init(); - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/ImportHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/ImportHandler.java deleted file mode 100644 index d05be76..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/ImportHandler.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags; - -import jaxx.compiler.JAXXCompiler; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; - -import java.io.IOException; -import java.io.LineNumberReader; -import java.io.StringReader; - -/** - * Handles the <code><import></code> tag. - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Id$ - * @since 2.1 - */ -public class ImportHandler implements TagHandler { - - /** Logger */ - protected static final Log log = LogFactory.getLog(ImportHandler.class); - - public static final String TAG_NAME = "import"; - - @Override - public void compileFirstPass(Element tag, - JAXXCompiler compiler) throws IOException { - - StringBuilder script = new StringBuilder(); - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - switch (child.getNodeType()) { - case Node.ELEMENT_NODE: - compiler.reportError( - "<import> tag may not contain child elements: " + - tag); - case Node.TEXT_NODE: // fall through - case Node.CDATA_SECTION_NODE: - String txt = ((Text) child).getData(); - if (log.isDebugEnabled()) { - log.debug("Will treate imports :[\n" + txt + "\n]"); - } - String eol = JAXXCompiler.getLineSeparator(); - LineNumberReader reader = new LineNumberReader(new StringReader(txt.trim())); - try { - String line; - while ((line = reader.readLine()) != null) { - line = line.trim(); - if (line.isEmpty()) { - continue; - } - script.append("import ").append(line); - if (!line.endsWith(";")) { - script.append(';'); - } - script.append(eol); - } - } finally { - reader.close(); - } - } - } - - String scriptString = script.toString().trim(); - if (!scriptString.isEmpty()) { - compiler.registerScript(script.toString()); - } - } - - @Override - public void compileSecondPass(Element tag, JAXXCompiler compiler) { - // nothing to do - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/ScriptHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/ScriptHandler.java deleted file mode 100644 index 2ea6264..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/ScriptHandler.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.UnsupportedAttributeException; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; - -import java.io.File; -import java.io.IOException; - -/** - * Handles the <code><script></code> tag. - * - * @author Ethan Nicholas - */ -public class ScriptHandler implements TagHandler { - - public static final String TAG_NAME = "script"; - - public static final String SOURCE_ATTRIBUTE = "source"; - - @Override - public void compileFirstPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - File scriptFile = null; - NamedNodeMap attributes = tag.getAttributes(); - for (int i = 0; i < attributes.getLength(); i++) { - Attr attribute = (Attr) attributes.item(i); - String name = attribute.getName(); - String attrValue = attribute.getValue(); - if (name.equals(SOURCE_ATTRIBUTE)) { - String filename = attrValue.replace('/', File.separatorChar); - scriptFile = new File(compiler.getBaseDir(), filename); - String content = compiler.loadFile(scriptFile); - compiler.registerScript(content, scriptFile); -// StringWriter scriptBuffer = new StringWriter(); -// FileReader in = new FileReader(scriptFile); -// try { -// char[] readBuffer = new char[2048]; -// int c; -// while ((c = in.read(readBuffer)) > 0) { -// scriptBuffer.write(readBuffer, 0, c); -// } -// } catch (FileNotFoundException e) { -// compiler.reportError( -// "script file not found: " + scriptFile); -// } finally { -// in.close(); -// } -// compiler.registerScript(scriptBuffer.toString(), scriptFile); - } else if (!name.startsWith(XMLNS_ATTRIBUTE) && - !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals( - attribute.getNamespaceURI())) { - throw new UnsupportedAttributeException(name); - } - } - - StringBuilder script = new StringBuilder(); - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - switch (child.getNodeType()) { - case Node.ELEMENT_NODE: - compiler.reportError( - "<script> tag may not contain child elements: " + - tag); - case Node.TEXT_NODE: // fall through - case Node.CDATA_SECTION_NODE: - script.append(((Text) child).getData()); - } - } - - String scriptString = script.toString().trim(); - if (scriptString.length() > 0) { - if (scriptFile != null) { - compiler.reportError( - "<script> tag has both a source attribute and an " + - "inline script"); - } - compiler.registerScript(script.toString()); - } - } - - @Override - public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - // nothing to do - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/StyleHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/StyleHandler.java deleted file mode 100644 index 6dfe719..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/StyleHandler.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.UnsupportedAttributeException; -import jaxx.compiler.css.StylesheetHelper; -import jaxx.runtime.css.Stylesheet; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; - -import java.io.File; -import java.io.IOException; - -/** - * Handles the <code><style></code> tag. - * - * @author Ethan Nicholas - */ -public class StyleHandler implements TagHandler { - - public static final String TAG_NAME = "style"; - - public static final String SOURCE_ATTRIBUTE = "source"; - - @Override - public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - boolean source = false; - NamedNodeMap attributes = tag.getAttributes(); - for (int i = 0; i < attributes.getLength(); i++) { - Attr attribute = (Attr) attributes.item(i); - String name = attribute.getName(); - String attrValue = attribute.getValue(); - if (name.equals(SOURCE_ATTRIBUTE)) { - source = true; - File styleFile = new File(compiler.getBaseDir(), attrValue.replace('/', File.separatorChar)); - if (!styleFile.exists()) { - compiler.reportError("stylesheet file not found: " + styleFile); - } else { - compiler.registerStyleSheetFile(styleFile, true); - } - } else if (!name.startsWith(XMLNS_ATTRIBUTE) && - !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { - throw new UnsupportedAttributeException(name); - } - } - - StringBuilder style = new StringBuilder(); - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - switch (child.getNodeType()) { - case Node.ELEMENT_NODE: - compiler.reportError("<style> tag may not contain child elements: " + tag); - case Node.TEXT_NODE: // fall through - case Node.CDATA_SECTION_NODE: - style.append(((Text) child).getData()); - } - } - - String styleString = style.toString().trim(); - if (styleString.length() > 0) { - if (source) { - compiler.reportError("<style> tag has both a source attribute and an inline stylesheet"); - } - try { - Stylesheet stylesheet = StylesheetHelper.processStylesheet(style.toString()); - compiler.registerStylesheet(stylesheet); - } catch (CompilerException e) { - String message = "Inline Css content is not valid"; - if (e instanceof jaxx.compiler.css.parser.ParseException) { - jaxx.compiler.css.parser.ParseException parseException = (jaxx.compiler.css.parser.ParseException) e; - - message += " (line: " + parseException.getLine() + " - col:" + parseException.getColumn() + ") "; - } - compiler.reportError(message, e); - } - } - } - - @Override - public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/TagHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/TagHandler.java deleted file mode 100644 index bc8b9af..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/TagHandler.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import org.w3c.dom.Element; - -import java.io.IOException; - -/** - * Implementations of <code>TagHandler</code> produce Java source code from XML tags. - * <code>TagHandlers</code> are mapped to particular XML tags (such as <JFrame>) in {@link JAXXCompiler}. - * There is only one <code>TagHandler</code> for any given XML tag, and therefore implementations must be - * stateless. - * - * @author Ethan Nicholas - */ -public interface TagHandler { - - String XMLNS_ATTRIBUTE = "xmlns"; - - /** - * Performs the first pass of compilation on an XML tag from a JAXX source file. - * <code>TagHandler</code> implementations affect the generated <code>.java</code> - * file by calling methods in the <code>JAXXCompiler</code>. - * - * @param tag the XML tag to compile - * @param compiler the active JAXXCompiler - * @throws CompilerException if a compilation error occurs - * @throws IOException if an I/O error occurs - */ - void compileFirstPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException; - - /** - * Performs the second pass of compilation on an XML tag from a JAXX source file. - * <code>TagHandler</code> implementations affect the generated <code>.java</code> - * file by calling methods in the <code>JAXXCompiler</code>. - * - * @param tag the XML tag to compile - * @param compiler the active JAXXCompiler - * @throws CompilerException if a compilation error occurs - * @throws IOException if an I/O error occurs - */ - void compileSecondPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException; -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/TagManager.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/TagManager.java deleted file mode 100644 index a8b162d..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/TagManager.java +++ /dev/null @@ -1,646 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags; - -import jaxx.compiler.ClassMap; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * Manages TagHandlers, including automatically compiling .jaxx files - * corresponding to class tags. - */ -public class TagManager { - - /** Logger */ - protected static final Log log = LogFactory.getLog(TagManager.class); - - /** Maps simple tag names to their default namespaces (package names). */ - private static Map<String, String> defaultNamespaces = - new HashMap<>(); - - /** Maps qualified tag names to the TagHandlers responsible for processing them. */ - private static Map<QName, TagHandler> registeredTags = - new HashMap<>(); - - /** Keeps track of whether or not named classes exist. */ - private static Map<String, Boolean> classExistenceCache = - new HashMap<>(); - - /** - * Maps bean classes to their TagHandler classes. The mapping is to - * TagHandler classes, rather than to TagHandler instances, - * because subclasses of the bean class should be handled by the same - * TagHandler (assuming no more specific mappings exist), which requires - * creating a new instance of the TagHandler. - */ - private static ClassMap<Class<? extends TagHandler>> registeredBeans = - new ClassMap<>(); - - // still targeting 1.4, so I can't use javax.xml.namespace.QName - - private static class QName { - - private String namespaceURI; - - private String localPart; - - public QName(String namespaceURI, String localPart) { - if (localPart == null) { - throw new NullPointerException(); - } - this.namespaceURI = namespaceURI; - this.localPart = localPart; - } - - public String getNamespaceURI() { - return namespaceURI; - } - - public String getLocalPart() { - return localPart; - } - - @Override - public boolean equals(Object o) { - if (o == null || !(o instanceof QName)) { - return false; - } - QName qname = (QName) o; - return qname.getNamespaceURI().equals(getNamespaceURI()) && - qname.getLocalPart().equals(getLocalPart()); - } - - @Override - public int hashCode() { - return (namespaceURI != null ? namespaceURI.hashCode() : 0) ^ - getLocalPart().hashCode(); - } - } - - private TagManager() { /* not instantiable */ } - - public static void reset() { - registeredBeans.clear(); - registeredTags.clear(); - defaultNamespaces.clear(); - } - - /** - * Maps a class tag to a specific <code>TagHandler</code>. - * - * When a tag representing the bean class is encountered (either the - * class' simple name, if it is unambiguous, or its fully-qualified name), - * the specified <code>TagHandler</code> will be invoked to run it. - * - * @param <T> type of handler - * @param beanClass the class to associate with a <code>TagHandler</code> - * @param handler the <code>TagHandler</code> class, which must descend - * from <code>DefaultObjectHandler</code> - * @throws IllegalArgumentException if the handler class does not descend - * from <code>DefaultObjectHandler</code> - */ - public static <T extends TagHandler> void registerBean(ClassDescriptor beanClass, - Class<T> handler) { - if (!DefaultObjectHandler.class.isAssignableFrom(handler)) { - throw new IllegalArgumentException( - "handler class must be a subclass of DefaultObjectHandler"); - } - registeredBeans.put(beanClass, handler); - if (log.isDebugEnabled()) { - log.debug(beanClass + " : " + handler); - } - String name = beanClass.getName(); - int dotPos = name.lastIndexOf("."); - String namespace = name.substring(0, dotPos + 1) + "*"; - name = name.substring(dotPos + 1); - registerDefaultNamespace(name, namespace); - } - - /** - * Sets the default namespace for a tag. - * - * When the tag is encountered with no namespace specified, the specified - * namespace will be assumed. Mapping the same tag to two or more default - * namespaces removes the mapping and marks the entry as being ambiguous - * (by putting a <code>null</code> value into the map); this causes an - * error to be thrown if the tag is used without a namespace being specified. - * - * Java package names on tags are automatically converted into namespaces - * (e.g. <javax.swing.JButton/> and - * <JButton xmlns="javax.swing.*"/> are equivalent), so tags with - * package names are considered to have namespaces specified. - * - * @param tag tag name - * @param namespace namespace - */ - public static void registerDefaultNamespace(String tag, String namespace) { - if (defaultNamespaces.containsKey(tag) && - !defaultNamespaces.get(tag).equals(namespace)) { - defaultNamespaces.put(tag, null); // tag name is now ambiguous - } else { - defaultNamespaces.put(tag, namespace); - } - } - - /** - * Registers a <code>TagHandler</code> for a tag. - * - * When a tag with the given name and namespace is encountered, the - * <code>TagHandler's compileFirstPass</code> and <code>compileSecondPass</code> - * methods will be invoked to handle it. - * - * It is not an error to register an already-registered tag and namespace - * combination. The new mapping will replace the old mapping. - * - * @param <T> type of handler - * @param namespace the tag's namespace - * @param tag the simple name of the tag - * @param handler the <code>TagHandler</code> which should process the tag - */ - public static <T extends TagHandler> void registerTag(String namespace, - String tag, - T handler) { - if (namespace == null) { - namespace = "*"; - } - //System.out.println("registerTag "+namespace+" : "+tag+" : "+handler); - if (log.isDebugEnabled()) { - log.debug(tag + " : " + handler); - } - registeredTags.put(new QName(namespace, tag), handler); - registerDefaultNamespace(tag, namespace); - } - - /** - * Returns the <code>TagHandler</code> that should be used to process the - * specified tag. - * - * If the tag represents the class name of an uncompiled <code>.jaxx</code> - * file, the <code>.jaxx</code> is first compiled. - * - * @param namespace the tag's namespace (may be <code>null</code>) - * @param tag the tag's simple name - * @param compiler the current <code>JAXXCompiler</code> - * @return the <code>TagHandler</code> for the tag - * @throws CompilerException ? - */ - public static TagHandler getTagHandler(String namespace, - String tag, - JAXXCompiler compiler) throws CompilerException { - return getTagHandler(namespace, tag, false, compiler); - } - - private static String getNamespace(ClassDescriptor beanClass) { - String packageName = beanClass.getPackageName(); - return packageName != null ? packageName + ".*" : "*"; - - } - - private static String getSimpleName(ClassDescriptor beanClass) { - String packageName = beanClass.getPackageName(); - if (packageName != null) { - assert beanClass.getName().startsWith(packageName); - return beanClass.getName().substring(packageName.length() + 1); - } - return beanClass.getName(); - } - - /** - * @param klass the java class - * @return the <code>TagHandler</code> that should be used to process the - * specified class. - * Only <code>TagHandlers</code> previously registered with - * <code>registerBean</code> are considered. - * @throws CompilerException ? - */ - public static DefaultObjectHandler getTagHandler(Class<?> klass) throws CompilerException { - - ClassDescriptor beanClass = ClassDescriptorHelper.getClassDescriptor(klass); - return getTagHandler(beanClass); - } - - /** - * @param beanClass the tag class - * @return the <code>TagHandler</code> that should be used to process the - * specified class. - * - * Only <code>TagHandlers</code> previously registered with - * <code>registerBean</code> are considered. - * @throws CompilerException ? - */ - public static DefaultObjectHandler getTagHandler(ClassDescriptor beanClass) throws CompilerException { - try { - if (beanClass == null) { - throw new NullPointerException( - "beanClass parameter can not be null"); - } - if (beanClass.getName() == null) { - throw new NullPointerException( - "beanClass name can not be null : " + beanClass); - } - - String namespace = getNamespace(beanClass); - String tag = getSimpleName(beanClass); - DefaultObjectHandler handler = (DefaultObjectHandler) - registeredTags.get(new QName(namespace, tag)); - if (handler == null) { - Class<? extends TagHandler> handlerClass = - registeredBeans.get(beanClass); - if (handlerClass == null) { - if (beanClass.isInterface()) { - - // if an interface is a tag, avoid big problems... - - return null; - } - throw new CompilerException( - "unable to find handler for " + beanClass); - } - Constructor<? extends TagHandler> constructor = - handlerClass.getConstructor(ClassDescriptor.class); - handler = (DefaultObjectHandler) - constructor.newInstance(beanClass); - registerTag(namespace, tag, handler); - } - return handler; - } catch (InstantiationException e) { - throw new RuntimeException(e); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - private static boolean classExists(String className, JAXXCompiler compiler) { - if (classExistenceCache.containsKey(className)) { - return classExistenceCache.get(className); - } - - boolean found = false; - ClassLoader classLoader = compiler.getClassLoader(); - try { - Class.forName(className, true, classLoader); - found = true; - } catch (ClassNotFoundException e) { - // ignore ? - } catch (NoClassDefFoundError e) { - // we obtain this instead of ClassNotFoundException on - // case-insensitive file systems when looking up a class with the - // wrong case - } - - if (!found) { - // couldn't find .class, check for .java - URL javaURL = classLoader.getResource(className.replace('.', '/') + ".java"); - found = javaURL != null; - } - - if (!found) { - // couldn't find .java, check for .jaxx - URL jaxxURL = classLoader.getResource(className.replace('.', '/') + ".jaxx"); - found = jaxxURL != null; - } - - classExistenceCache.put(className, found); - - return found; - } - - private static String determinePackage(String simpleClassName, - String defaultPackage, - JAXXCompiler compiler) { - String namespace = null; - Set<String> classes = compiler.getImportedClasses(); - for (String className : classes) { - // search class imports (e.g. import java.util.Date;) - if (className.equals(simpleClassName) || - className.endsWith("." + simpleClassName)) { - namespace = className.substring(0, className.lastIndexOf(".") + 1) + "*"; - } - } - if (namespace == null) { - // search package imports (e.g. import java.util.*;) - Set<String> searchList = compiler.getImportedPackages(); - if (defaultPackage != null) { - if (!defaultPackage.endsWith("*")) { - throw new IllegalArgumentException( - "defaultPackage must end in '*', found '" + - defaultPackage + "'"); - } - String fqn = defaultPackage.substring( - 0, defaultPackage.length() - 1) + simpleClassName; - if (classExists(fqn, compiler)) { - return defaultPackage; - } - } - for (String currentPackage : searchList) { - String className = currentPackage + simpleClassName; - if (classExists(className, compiler)) { - if (namespace != null) { - // we've already found the same name in another package - compiler.reportError( - "symbol '" + simpleClassName + - "' is ambiguous, found matching classes " + - namespace.substring(0, namespace.length() - 1) + - simpleClassName + " and " + currentPackage + - simpleClassName + - ". Use fully-qualified name to disambiguate." - ); - return null; - } - namespace = currentPackage + "*"; - } - } - } - - return namespace; - } - - /** - * Returns the <code>TagHandler</code> that should be used to process the - * specified tag. - * - * The <code>namespacePrefix</code> parameter is used only for error - * checking, as it is an error to specify conflicting package names using - * both a fully-qualified tag name and a namespace prefix, but it is not - * an error to specify conflicting package names using a fully-qualified - * tag name and a <i>default</i> namespace (i.e. - * <awt:javax.swing.JButton xmlns:awt='java.awt.*'/> - * is an error, whereas <javax.swing.JButton xmlns='java.awt.*'/> is not). - * - * @param namespace the tag's namespace (may be <code>null</code>) - * @param tag the tag's simple name (which can include - * fully-qualified Java class names) - * @param namespacePrefix <code>true</code> if the namespace was specified - * by means of a namespace prefix (as opposed to a - * default namespace) - * @param compiler the current <code>JAXXCompiler</code> - * @return the <code>TagHandler</code> for the tag - * @throws CompilerException ? - */ - public static TagHandler getTagHandler(String namespace, - String tag, - boolean namespacePrefix, - JAXXCompiler compiler) throws CompilerException { - if (tag == null) { - throw new NullPointerException("tag parameter can not be null"); - } - if (namespace == null && defaultNamespaces.containsKey(tag)) { - namespace = defaultNamespaces.get(tag); - if (namespace == null) { - - // defaultNamespaces map contains a null value, which is put - // there to indicate ambiguity - compiler.reportError( - "tag '" + tag + "' is ambiguous; specify " + - "fully-qualified name (package and class) to " + - "disambiguate" - ); - return null; - } - } - - TagHandler handler = registeredTags.get(new QName(namespace, tag)); - if (handler == null) { - if (namespace == null || namespace.endsWith("*")) { - String className; - if (namespace != null) { - className = resolveClassName( - namespace.substring(0, namespace.length() - 1) + tag, - compiler - ); - if (className == null) { - className = resolveClassName(tag, compiler); - if (namespacePrefix && - !className.startsWith( - namespace.substring( - 0, - namespace.length() - 1))) { - - // namespace was specified, but we found it in a - // different package - ignore - className = null; - } - } - } else { - className = resolveClassName(tag, compiler); - } - if (className != null) { - int dotPos = className.lastIndexOf("."); - namespace = className.substring(0, dotPos + 1) + "*"; - tag = className.substring(dotPos + 1); - handler = registeredTags.get(new QName(namespace, tag)); - if (handler == null) { - try { - ClassDescriptor beanClass = - ClassDescriptorHelper.getClassDescriptor( - className, - compiler.getClassLoader() - ); - handler = getTagHandler(beanClass); - } catch (ClassNotFoundException e) { - log.error(e); -// e.printStackTrace(); - } - } - } - } - } - return handler; - } - - /** - * Resolves a simple class name (like <code>Object</code> or - * <code>String</code>) to its fully-qualified name. - * - * Inner classes should be represented as they would appear in Java source - * code (e.g. JPopupMenu.Separator). Fully-qualified names, such as - * <code>java.lang.Object</code> are legal and will be returned unmodified - * (and in fact it is generally impossible to even know whether a given - * reference is fully qualified until it has been resolved). - * - * Returns <code>null</code> if no matching class could be found. - * - * @param name name to resolve - * @param compiler run to use - * @return the resolved fqn class name - */ - public static String resolveClassName(String name, JAXXCompiler compiler) { - if (name.endsWith("[]")) { - return resolveClassName( - name.substring(0, name.length() - 2), compiler) + "[]"; - } - if (name.contains("<")) { - - // strip off generic types - name = name.substring(0, name.indexOf("<")); - } - - name = name.intern(); - if (name.equals("boolean") || - name.equals("byte") || - name.equals("short") || - name.equals("int") || - name.equals("long") || - name.equals("float") || - name.equals("double") || - name.equals("char")) { - return name; - } - - String result = null; - String originalName = name; - String defaultNamespace = null; - if (defaultNamespaces.containsKey(name)) { - defaultNamespace = defaultNamespaces.get(name); - if (defaultNamespace == null) { - - // defaultNamespaces map contains a null value, which is put - // there to indicate ambiguity - compiler.reportError( - "class '" + name + "' is ambiguous; specify " + - "fully-qualified name (package and class) to " + - "disambiguate" - ); - return null; - } - } - if (defaultNamespace != null && defaultNamespace.endsWith("*")) { - result = defaultNamespace.substring( - 0, defaultNamespace.length() - 1) + name; - } - - if (result == null) { - // Inner class names (like JPopupMenu.Separator) present a special - // challenge. The name before the dot might be a package name, - // or it might be a class name. - // - // If it's a class name, it might be fully qualified, or it might - // not. And it's also not actually the correct name of the class, - // as far as the JVM is concerned -- the correct name uses a dollar - // sign instead of a dot (javax.swing.JPopupMenu$Separator). - // And there could be more than one inner class -- it's possible to - // have com.mycompany.Outer$Inner$Innerer$Innerest. - // - // The basic strategy is to run by treating the part before the - // last dot as a package name, as that is by far the most likely case. - // - // If we don't find the class there, change the last dot to a - // dollar sign and try again. - - // Suppose we have the tag - // <com.mycompany.Outer.Inner.Innerer.Innerest/>, - // matching the class above. Resolution proceeds like this: - // com.mycompany.Outer.Inner.Innerer.* : Innerest - // com.mycompany.Outer.Inner.* : Innerer$Innerest - // com.mycompany.Outer.* : Inner$Innerer$Innerest - // com.mycompany.* : Outer$Inner$Innerer$Innerest - // And at this point we have a match with the class Outer$Inner$Innerer$Innerest in package com.mycompany. - int dotPos = originalName.lastIndexOf('.'); - for (; ; ) { - String namespace = dotPos != -1 ? originalName.substring(0, dotPos) + ".*" : "*"; - name = originalName.substring(dotPos + 1).replace('.', '$'); - String packageName = determinePackage(name, namespace, compiler); - if (packageName != null) { - assert packageName.endsWith("*"); - if (packageName.equals(namespace) || - namespace.equals("*")) { - // check for an alias (like javax.swing.JComboBox actually being jaxx.runtime.swing.JAXXComboBox) - TagHandler handler = - registeredTags.get(new QName(namespace, name)); - - if (handler != null) { - - // determine alias by looking at handler - ClassDescriptor alias = - ((DefaultObjectHandler) handler).getBeanClass(); - - // make sure the same handler is used for both the - // aliased and non-aliased names, in order to avoid - // "no CompiledObject has been registered" error - // the line below doesn't bother to handle the case - // where the aliased class name doesn't have a - // package, since it's a pretty safe assumption that - // that will never happen - assert alias.getPackageName() != null && alias.getPackageName().length() > 0 : "aliasing with no package name has not been implemented"; - registeredTags.put( - new QName(alias.getPackageName() + ".*", alias.getName().substring(alias.getPackageName().length() + 1)), - handler - ); - result = alias.getName(); - break; - } else { // no alias - result = packageName.substring(0, packageName.length() - 1) + name; - break; - } - } - // else we found a class by the same name, but in the wrong package - } - - if (dotPos <= 0) { - break; - } - dotPos = originalName.lastIndexOf('.', dotPos - 1); - } - } - - if (result != null && !result.equals(originalName)) { - - // check for aliases against the new name as well - result = resolveClassName(result, compiler); - } - - return result; - } - - public static ClassDescriptor resolveClass(String className, - JAXXCompiler compiler) { - try { - className = resolveClassName(className, compiler); - if (className == null) { - return null; - } - return ClassDescriptorHelper.getClassDescriptor( - className, - compiler.getClassLoader() - ); - } catch (ClassNotFoundException e) { - return null; - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/ApplicationHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/ApplicationHandler.java deleted file mode 100644 index ea61a89..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/ApplicationHandler.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.swing.Application; -import org.w3c.dom.Element; - -import javax.swing.WindowConstants; - -public class ApplicationHandler extends JWindowHandler { - - public static final String ATTRIBUTE_LOOK_AND_FEEL = "lookAndFeel"; - - public static final String ATTRIBUTE_DEFAULT_CLOSE_OPERATION = "defaultCloseOperation"; - - public ApplicationHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), - beanClass, - Application.class - ); - } - - @Override - public void setAttribute(CompiledObject object, - String propertyName, - String stringValue, - boolean inline, - JAXXCompiler compiler) throws CompilerException { - if (propertyName.equals(ATTRIBUTE_LOOK_AND_FEEL) && - stringValue != null && - !stringValue.trim().startsWith("{")) { - compiler.appendBodyCode("{ " + object.getJavaCode() + ".setLookAndFeel(" + TypeManager.getJavaCode(stringValue) + "); }" + JAXXCompiler.getLineSeparator()); - } else { - super.setAttribute(object, - propertyName, - stringValue, - inline, - compiler - ); - } - } - - @Override - protected void setDefaults(CompiledObject object, - Element tag, - JAXXCompiler compiler) throws CompilerException { - super.setDefaults(object, tag, compiler); - setAttribute(object, - ATTRIBUTE_DEFAULT_CLOSE_OPERATION, - String.valueOf(WindowConstants.EXIT_ON_CLOSE), - false, - compiler - ); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/CellHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/CellHandler.java deleted file mode 100644 index 5707cc9..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/CellHandler.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.UnsupportedAttributeException; -import jaxx.compiler.tags.TagHandler; -import jaxx.compiler.types.TypeManager; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; - -import java.awt.GridBagConstraints; -import java.awt.Insets; -import java.io.IOException; - -public class CellHandler implements TagHandler { - - public static final String TAG_NAME = "cell"; - - public static final String ATTRIBUTE_INSETS = "insets"; - - public static final String ATTRIBUTE_WEIGHTX = "weightx"; - - public static final String ATTRIBUTE_WEIGHTY = "weighty"; - - public static final String ATTRIBUTE_COLUMNS = "columns"; - - public static final String ATTRIBUTE_ROWS = "rows"; - - public static final String ATTRIBUTE_FILL = "fill"; - - enum Fill { - none(GridBagConstraints.NONE), - horizontal(GridBagConstraints.HORIZONTAL), - vertical(GridBagConstraints.VERTICAL), - both(GridBagConstraints.BOTH); - - private final int intValue; - - Fill(int intValue) { - this.intValue = intValue; - } - - public int getIntValue() { - return intValue; - } - } - - public static final String ATTRIBUTE_ANCHOR = "anchor"; - - enum Anchor { - north(GridBagConstraints.NORTH), - northeast(GridBagConstraints.NORTHEAST), - east(GridBagConstraints.EAST), - southeast(GridBagConstraints.SOUTHEAST), - south(GridBagConstraints.SOUTH), - southwest(GridBagConstraints.SOUTHEAST), - west(GridBagConstraints.WEST), - northwest(GridBagConstraints.NORTHWEST), - center(GridBagConstraints.CENTER); - - private final int intValue; - - Anchor(int intValue) { - this.intValue = intValue; - } - - public int getIntValue() { - return intValue; - } - } - - @Override - public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - compileChildrenFirstPass(tag, compiler); - } - - @Override - public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - Node parent = tag.getParentNode(); - if (parent.getNodeType() != Node.ELEMENT_NODE || !parent.getLocalName().equals("row")) { - compiler.reportError("cell tag may only appear within row tag"); - return; - } - - TableHandler.CompiledTable table = (TableHandler.CompiledTable) compiler.getOpenComponent(); - table.newCell(); - GridBagConstraints c = table.getCellConstraints(); - setAttributes(c, tag); - compileChildrenSecondPass(tag, compiler); - } - - public static void setAttribute(GridBagConstraints c, String name, String value) throws CompilerException { - value = value.trim(); - if (name.equals(ATTRIBUTE_INSETS)) { - c.insets = (Insets) TypeManager.convertFromString(value, Insets.class); - } else if (name.equals(ATTRIBUTE_WEIGHTX)) { - c.weightx = Double.parseDouble(value); - } else if (name.equals(ATTRIBUTE_WEIGHTY)) { - c.weighty = Double.parseDouble(value); - } else if (name.equals(ATTRIBUTE_COLUMNS)) { - c.gridwidth = Integer.parseInt(value); - } else if (name.equals(ATTRIBUTE_ROWS)) { - c.gridheight = Integer.parseInt(value); - } else if (name.equals(ATTRIBUTE_FILL)) { - Fill fill = Fill.valueOf(value); - if (fill == null) { - throw new CompilerException("invalid value for fill attribute: '" + value + "'"); - } - c.fill = fill.getIntValue(); - } else if (name.equals(ATTRIBUTE_ANCHOR)) { - Anchor anchor = Anchor.valueOf(value); - if (anchor == null) { - throw new CompilerException("invalid value for anchor attribute: '" + value + "'"); - } - c.anchor = anchor.getIntValue(); -// if (value.equals(ANCHOR_VALUE_NORTH)) { -// c.anchor = GridBagConstraints.NORTH; -// } else if (value.equals(ANCHOR_VALUE_NORTHEAST)) { -// c.anchor = GridBagConstraints.NORTHEAST; -// } else if (value.equals(ANCHOR_VALUE_EAST)) { -// c.anchor = GridBagConstraints.EAST; -// } else if (value.equals(ANCHOR_VALUE_SOUTHEAST)) { -// c.anchor = GridBagConstraints.SOUTHEAST; -// } else if (value.equals(ANCHOR_VALUE_SOUTH)) { -// c.anchor = GridBagConstraints.SOUTH; -// } else if (value.equals(ANCHOR_VALUE_SOUTHWEST)) { -// c.anchor = GridBagConstraints.SOUTHWEST; -// } else if (value.equals(ANCHOR_VALUE_WEST)) { -// c.anchor = GridBagConstraints.WEST; -// } else if (value.equals(ANCHOR_VALUE_NORTHWEST)) { -// c.anchor = GridBagConstraints.NORTHWEST; -// } else if (value.equals(ANCHOR_VALUE_CENTER)) { -// c.anchor = GridBagConstraints.CENTER; -// } else { -// throw new IllegalArgumentException("invalid value for anchor attribute: '" + value + "'"); -// } - } else { - throw new UnsupportedAttributeException(name); - } - } - - public static void setAttributes(GridBagConstraints c, Element tag) throws CompilerException { - NamedNodeMap children = tag.getAttributes(); - for (int i = 0; i < children.getLength(); i++) { - Attr attribute = (Attr) children.item(i); - String name = attribute.getName(); - String value = attribute.getValue(); - if (!name.startsWith("xmlns") && !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { - setAttribute(c, name, value); - } - } - } - - protected void compileChildrenFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node node = children.item(i); - int nodeType = node.getNodeType(); - if (nodeType == Node.ELEMENT_NODE) { - Element child = (Element) node; - compileChildTagFirstPass(child, compiler); - } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { - String text = ((Text) node).getData().trim(); - if (text.length() > 0) { - compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); - } - } - } - } - - protected void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node node = children.item(i); - int nodeType = node.getNodeType(); - if (nodeType == Node.ELEMENT_NODE) { - Element child = (Element) node; - compileChildTagSecondPass(child, compiler); - } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { - String text = ((Text) node).getData().trim(); - if (text.length() > 0) { - compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); - } - } - } - } - - protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - compiler.compileFirstPass(tag); - } - - protected void compileChildTagSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - compiler.compileSecondPass(tag); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/CompiledItemContainer.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/CompiledItemContainer.java deleted file mode 100644 index 5f9df6d..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/CompiledItemContainer.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.runtime.swing.Item; - -import java.util.ArrayList; -import java.util.List; -import java.util.Stack; - -/** Compiled representation of a class that contains Items arranged in a list or tree structure (JComboBox, JList, JTree). */ -class CompiledItemContainer extends CompiledObject { - - private List<Item> items = new ArrayList<>(); - - private Stack<Item> openNodes = new Stack<>(); - - public CompiledItemContainer(String id, ClassDescriptor objectClass, JAXXCompiler compiler) throws CompilerException { - super(id, objectClass, compiler); - } - - public void openItem(Item item) { - if (openNodes.isEmpty()) { - items.add(item); - } else { - Item openNode = openNodes.peek(); - openNode.addChild(item); - } - openNodes.add(item); - } - - public void closeItem(Item item) { - if (!item.equals(openNodes.pop())) { - throw new IllegalArgumentException(item + " was not at the top of the item stack"); - } - } - - public List<Item> getItems() { - return items; - } - - public void setItems(List<Item> items) { - this.items = items; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/ItemHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/ItemHandler.java deleted file mode 100644 index a442c9b..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/ItemHandler.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.UnsupportedAttributeException; -import jaxx.compiler.binding.DataBindingHelper; -import jaxx.compiler.tags.TagHandler; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.swing.Item; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; - -import java.io.IOException; -import java.util.List; - -public class ItemHandler implements TagHandler { - - public static final String TAG_NAME = "item"; - - private String DATA_BINDING = "<data binding has not been processed yet>"; - - public static final String ATTRIBUTE_ID = "id"; - - @Override - public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - compileChildrenFirstPass(tag, compiler); - } - - @Override - public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - String id = tag.getAttribute(ATTRIBUTE_ID); - if (id == null || id.length() == 0) { - id = compiler.getAutoId(Item.class.getSimpleName()); -// id = compiler.getAutoId(ClassDescriptorHelper.getClassDescriptor(Item.class)); - } - String label = null; - String value = null; - boolean selected = false; - NamedNodeMap children = tag.getAttributes(); - - for (int i = 0; i < children.getLength(); i++) { - Attr attribute = (Attr) children.item(i); - String name = attribute.getName(); - String attrValue = attribute.getValue(); - if (name.equals(ATTRIBUTE_ID)) { - // already handled - continue; - } - DataBindingHelper bindingHelper = compiler.getBindingHelper(); - if (name.equals(Item.LABEL_PROPERTY)) { - String labelBinding = DataBindingHelper.processDataBindings(attrValue); - if (labelBinding != null) { - bindingHelper.registerDataBinding(id + ".label", labelBinding, id + ".setLabel(" + labelBinding + ");"); -// bindingHelper.registerDataBinding(labelBinding, id + ".label", id + ".setLabel(" + labelBinding + ");"); - } else { - label = attrValue; - } - continue; - } - if (name.equals(Item.VALUE_PROPERTY)) { - String valueBinding = DataBindingHelper.processDataBindings(attrValue); - if (valueBinding != null) { - value = DATA_BINDING; - bindingHelper.registerDataBinding(id + ".value", valueBinding, id + ".setValue(" + valueBinding + ");"); -// bindingHelper.registerDataBinding(valueBinding, id + ".value", id + ".setValue(" + valueBinding + ");"); - } else { - value = attrValue; - } - continue; - } - if (name.equals(Item.SELECTED_PROPERTY)) { - String selectedBinding = DataBindingHelper.processDataBindings(attrValue); - if (selectedBinding != null) { - bindingHelper.registerDataBinding(id + ".selected", selectedBinding, id + ".setSelected(" + selectedBinding + ");"); -// bindingHelper.registerDataBinding(selectedBinding, id + ".selected", id + ".setSelected(" + selectedBinding + ");"); - } else { - selected = (Boolean) TypeManager.convertFromString(attrValue, Boolean.class); - } - continue; - } - - if (!name.startsWith("xmlns") && !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { - throw new UnsupportedAttributeException(name); - } - } - - Item item = new Item(id, label, value, selected); - CompiledItemContainer list = (CompiledItemContainer) compiler.getOpenComponent(); - if (value == null) { - compiler.reportError("<item> tag is missing required 'value' attribute"); - } else { - if (!value.equals(DATA_BINDING)) { - List<Item> items = list.getItems(); - for (Item item1 : items) { - if (item1.getValue().equals(value)) { - compiler.reportError("This container already has an <item> tag with the value '" + value + "'"); - break; - } - } - } - list.openItem(item); - compileChildrenSecondPass(tag, compiler); - list.closeItem(item); - } - } - - protected void compileChildrenFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node node = children.item(i); - int nodeType = node.getNodeType(); - if (nodeType == Node.ELEMENT_NODE) { - Element child = (Element) node; - compileChildTagFirstPass(child, compiler); - } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { - String text = ((Text) node).getData().trim(); - if (text.length() > 0) { - compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); - } - } - } - } - - protected void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node node = children.item(i); - int nodeType = node.getNodeType(); - if (nodeType == Node.ELEMENT_NODE) { - Element child = (Element) node; - compileChildTagSecondPass(child, compiler); - } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { - String text = ((Text) node).getData().trim(); - if (text.length() > 0) { - compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); - } - } - } - } - - protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - compiler.compileFirstPass(tag); - } - - protected void compileChildTagSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - compiler.compileSecondPass(tag); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXComboBoxHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXComboBoxHandler.java deleted file mode 100644 index 433a84d..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXComboBoxHandler.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.swing.Item; -import jaxx.runtime.swing.JAXXComboBox; -import org.w3c.dom.Element; - -import java.awt.event.ItemListener; -import java.io.IOException; -import java.util.List; - -public class JAXXComboBoxHandler extends DefaultComponentHandler { - - public JAXXComboBoxHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JAXXComboBox.class); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("getSelectedIndex", ItemListener.class); - addProxyEventInfo("getSelectedItem", ItemListener.class); - } - - @Override - protected CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { - return new CompiledItemContainer(id, getBeanClass(), compiler); - } - - @Override - public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - super.compileChildrenSecondPass(tag, compiler); - CompiledItemContainer list = (CompiledItemContainer) compiler.getOpenComponent(); - List<Item> items = list.getItems(); - if (items != null && !items.isEmpty()) { - String listName = list.getId() + "$items"; - list.appendAdditionCode("java.util.List<jaxx.runtime.swing.Item> " + listName + " = new java.util.ArrayList<jaxx.runtime.swing.Item>();"); - for (Item item : items) { - String id = item.getId(); - CompiledObject compiledItem = new CompiledObject(id, ClassDescriptorHelper.getClassDescriptor(Item.class), compiler); - compiledItem.setConstructorParams(TypeManager.getJavaCode(id) + ", " + TypeManager.getJavaCode(item.getLabel()) + ", " + TypeManager.getJavaCode(item.getValue()) + ", " + item.isSelected()); - compiler.registerCompiledObject(compiledItem); - list.appendAdditionCode(listName + ".add(" + id + ");"); - } - list.appendAdditionCode(list.getId() + ".setItems(" + listName + ");"); - } - } -} - - - diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXListHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXListHandler.java deleted file mode 100644 index 1200ae2..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXListHandler.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.swing.Item; -import jaxx.runtime.swing.JAXXList; -import org.w3c.dom.Element; - -import javax.swing.event.ListSelectionListener; -import java.io.IOException; -import java.util.List; - -public class JAXXListHandler extends DefaultComponentHandler { - - public JAXXListHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JAXXList.class); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("getSelectedIndex", ListSelectionListener.class, "selectionModel"); - addProxyEventInfo("getSelectedIndices", ListSelectionListener.class, "selectionModel"); - addProxyEventInfo("getSelectedValue", ListSelectionListener.class, "selectionModel"); - addProxyEventInfo("getSelectedValues", ListSelectionListener.class, "selectionModel"); - } - - @Override - public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { - return new CompiledItemContainer(id, getBeanClass(), compiler); - } - - @Override - public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - super.compileChildrenSecondPass(tag, compiler); - CompiledItemContainer list = (CompiledItemContainer) compiler.getOpenComponent(); - List<Item> items = list.getItems(); - if (items != null && !items.isEmpty()) { - String listName = list.getId() + "$items"; - //TODO Add the correct generic type - list.appendAdditionCode("java.util.List<jaxx.runtime.swing.Item> " + listName + " = new java.util.ArrayList<jaxx.runtime.swing.Item>();"); - for (Item item : items) { - String id = item.getId(); - CompiledObject compiledItem = new CompiledObject(id, ClassDescriptorHelper.getClassDescriptor(Item.class), compiler); - compiledItem.setConstructorParams(TypeManager.getJavaCode(id) + ", " + TypeManager.getJavaCode(item.getLabel()) + ", " + TypeManager.getJavaCode(item.getValue()) + ", " + item.isSelected()); - compiler.registerCompiledObject(compiledItem); - list.appendAdditionCode(listName + ".add(" + id + ");"); - } - list.appendAdditionCode(list.getId() + ".setItems(" + listName + ");"); - } - } -} - - - diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXTabHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXTabHandler.java deleted file mode 100644 index aaea97f..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXTabHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.reflect.ClassDescriptor; - -/** @author Tony Chemit - chemit@codelutin.com */ -public class JAXXTabHandler extends TableHandler { - - public JAXXTabHandler(ClassDescriptor beanClass) { - super(beanClass); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXTreeHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXTreeHandler.java deleted file mode 100644 index 8429221..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXTreeHandler.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.swing.Item; -import jaxx.runtime.swing.JAXXTree; -import org.w3c.dom.Element; - -import javax.swing.event.TreeSelectionListener; -import java.io.IOException; -import java.util.List; - -public class JAXXTreeHandler extends DefaultComponentHandler { - - public JAXXTreeHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JAXXTree.class); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("getSelectionCount", TreeSelectionListener.class, "selectionModel"); - addProxyEventInfo("getSelectionPath", TreeSelectionListener.class, "selectionModel"); - addProxyEventInfo("getSelectionPaths", TreeSelectionListener.class, "selectionModel"); - addProxyEventInfo("getSelectionRows", TreeSelectionListener.class, "selectionModel"); - addProxyEventInfo("getSelectionValue", TreeSelectionListener.class, "selectionModel"); - } - - @Override - public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { - return new CompiledItemContainer(id, getBeanClass(), compiler); - } - - private void createItems(CompiledObject tree, List<Item> items, String addMethod, JAXXCompiler compiler) throws CompilerException { - for (Item item : items) { - String id = item.getId(); - CompiledObject compiledItem = new CompiledObject(id, ClassDescriptorHelper.getClassDescriptor(Item.class), compiler); - compiledItem.setConstructorParams(TypeManager.getJavaCode(id) + ", " + TypeManager.getJavaCode(item.getLabel()) + ", " + TypeManager.getJavaCode(item.getValue()) + ", " + item.isSelected()); - compiler.registerCompiledObject(compiledItem); - tree.appendAdditionCode(addMethod + "(" + id + ");"); - createItems(tree, item.getChildren(), id + ".addChild", compiler); - } - } - - @Override - public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - super.compileChildrenSecondPass(tag, compiler); - CompiledItemContainer tree = (CompiledItemContainer) compiler.getOpenComponent(); - List<Item> items = tree.getItems(); - if (items != null && !items.isEmpty()) { - String listName = tree.getId() + "$items"; - tree.appendAdditionCode("java.util.List<jaxx.runtime.swing.Item> " + listName + " = new java.util.ArrayList<jaxx.runtime.swing.Item>();"); - createItems(tree, items, listName + ".add", compiler); - tree.appendAdditionCode(tree.getId() + ".setItems(" + listName + ");"); - } - } -} - - - diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JCheckBoxHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JCheckBoxHandler.java deleted file mode 100644 index fa313c2..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JCheckBoxHandler.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; - -import javax.swing.AbstractButton; -import javax.swing.event.ChangeListener; - -public class JCheckBoxHandler extends DefaultComponentHandler { - - public JCheckBoxHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, AbstractButton.class); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("isSelected", ChangeListener.class, "model"); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JComboBoxHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JComboBoxHandler.java deleted file mode 100644 index dcbbdf1..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JComboBoxHandler.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import javax.swing.JComboBox; -import java.awt.event.ItemListener; -import java.io.IOException; - -public class JComboBoxHandler extends DefaultComponentHandler { - - public JComboBoxHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JComboBox.class); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("getSelectedIndex", ItemListener.class); - addProxyEventInfo("getSelectedItem", ItemListener.class); - } - - @Override - public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - if (children.getLength() > 0) { - compiler.reportError("JComboBox does not accept childs"); - throw new CompilerException("JComboBox does not accept childs"); - } - } -} - - - diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JInternalFrameHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JInternalFrameHandler.java deleted file mode 100644 index a966f28..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JInternalFrameHandler.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import org.w3c.dom.Element; - -import javax.swing.JInternalFrame; -import javax.swing.JMenuBar; -import javax.swing.WindowConstants; - -public class JInternalFrameHandler extends DefaultComponentHandler { - - public JInternalFrameHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JInternalFrame.class); - } - - @Override - public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { - return new CompiledObject(id, getBeanClass(), compiler) { - - @Override - public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { - if (ClassDescriptorHelper.getClassDescriptor(JMenuBar.class).isAssignableFrom(child.getObjectClass())) { - appendAdditionCode(getId() + ".setJMenuBar(" + child.getId() + ");"); - } else { - super.addChild(child, constraints, compiler); - } - } - }; - } - - @Override - protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { - super.setDefaults(object, tag, compiler); - setAttribute(object, "visible", "true", false, compiler); - setAttribute(object, "closable", "true", false, compiler); - setAttribute(object, "defaultCloseOperation", String.valueOf(WindowConstants.DISPOSE_ON_CLOSE), false, compiler); - } - - @Override - public void setAttributes(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { - super.setAttributes(object, tag, compiler); - compiler.appendInitializerCode(object.getId() + ".pack();\n"); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JListHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JListHandler.java deleted file mode 100644 index 17e17bd..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JListHandler.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import javax.swing.JList; -import javax.swing.event.ListSelectionListener; -import java.io.IOException; - -public class JListHandler extends DefaultComponentHandler { - - public JListHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JList.class); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("getSelectedIndex", ListSelectionListener.class, "selectionModel"); - addProxyEventInfo("getSelectedIndices", ListSelectionListener.class, "selectionModel"); - addProxyEventInfo("getSelectedValue", ListSelectionListener.class, "selectionModel"); - addProxyEventInfo("getSelectedValues", ListSelectionListener.class, "selectionModel"); - } - - @Override - public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - if (children.getLength() > 0) { - compiler.reportError("JList does not accept childs"); - throw new CompilerException("JList does not accept childs"); - } - } -} - - - diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JMenuHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JMenuHandler.java deleted file mode 100644 index d657b67..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JMenuHandler.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; - -import javax.swing.JMenu; -import javax.swing.event.MenuListener; - -public class JMenuHandler extends DefaultComponentHandler { - - public JMenuHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JMenu.class); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("isSelected", MenuListener.class); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JPasswordFieldHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JPasswordFieldHandler.java deleted file mode 100644 index 91dc4da..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JPasswordFieldHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; - -import javax.swing.JPasswordField; -import javax.swing.event.DocumentListener; - -public class JPasswordFieldHandler extends JTextComponentHandler { - - public JPasswordFieldHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JPasswordField.class); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("getPassword", DocumentListener.class, "document"); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JPopupMenuHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JPopupMenuHandler.java deleted file mode 100644 index d472d77..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JPopupMenuHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import org.w3c.dom.Element; - -import javax.swing.JPopupMenu; - -public class JPopupMenuHandler extends DefaultComponentHandler { - - public JPopupMenuHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JPopupMenu.class); - } - - @Override - public boolean isContainer() { - return true; - } - - @Override - protected void openComponent(CompiledObject object, Element tag, JAXXCompiler compiler) { - compiler.openInvisibleComponent(object); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JProgressBarHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JProgressBarHandler.java deleted file mode 100644 index a4d8dad..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JProgressBarHandler.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; - -import javax.swing.JProgressBar; -import javax.swing.event.ChangeListener; - -public class JProgressBarHandler extends DefaultComponentHandler { - - public JProgressBarHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JProgressBar.class); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("getValue", ChangeListener.class, "change"); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JRadioButtonHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JRadioButtonHandler.java deleted file mode 100644 index 89c148f..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JRadioButtonHandler.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.UnsupportedAttributeException; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.swing.JAXXButtonGroup; - -import javax.swing.AbstractButton; -import javax.swing.ButtonGroup; -import javax.swing.event.ChangeListener; - -public class JRadioButtonHandler extends DefaultComponentHandler { - - private static final String VALUE_PROPERTY = JAXXButtonGroup.VALUE_CLIENT_PROPERTY.substring(1); - - private static final String BUTTON_GROUP_PROPERTY = JAXXButtonGroup.BUTTON8GROUP_CLIENT_PROPERTY.substring(1); - - public JRadioButtonHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, AbstractButton.class); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("isSelected", ChangeListener.class, "model"); - } - - @Override - public ClassDescriptor getPropertyType(CompiledObject object, String name, JAXXCompiler compiler) throws CompilerException { - if (name.equals(BUTTON_GROUP_PROPERTY)) { - return null; // accepts either a String or a ButtonGroup - } else if (name.equals(VALUE_PROPERTY)) { - return ClassDescriptorHelper.getClassDescriptor(Object.class); - } else { - return super.getPropertyType(object, name, compiler); - } - } - - @Override - public boolean isMemberBound(String name) throws UnsupportedAttributeException { - return !(name.equals(BUTTON_GROUP_PROPERTY) || name.equals(VALUE_PROPERTY)) && super.isMemberBound(name); - } - - // handle buttonGroup assignment in addition block rather than initialization block - @Override - public void setProperty(CompiledObject object, String name, Object value, JAXXCompiler compiler) { - if (name.equals(BUTTON_GROUP_PROPERTY)) { - object.appendAdditionCode(getSetPropertyCode(object.getJavaCode(), name, TypeManager.getJavaCode(value), compiler)); - } else { - super.setProperty(object, name, value, compiler); - } - } - - @Override - public String getSetPropertyCode(String id, String name, String valueCode, JAXXCompiler compiler) throws CompilerException { - if (name.equals(BUTTON_GROUP_PROPERTY)) { - if (valueCode.startsWith("\"") && valueCode.endsWith("\"")) { - valueCode = valueCode.substring(1, valueCode.length() - 1); - CompiledObject buttonGroup = compiler.getCompiledObject(valueCode); - if (buttonGroup == null) { - buttonGroup = new CompiledObject(valueCode, ClassDescriptorHelper.getClassDescriptor(JAXXButtonGroup.class), compiler); - compiler.registerCompiledObject(buttonGroup); - } - } - String type = compiler.getImportedType( - ButtonGroup.class.getName()); - - return "{ " + type + " $buttonGroup = " + valueCode + "; " + id + ".putClientProperty(\"$buttonGroup\", $buttonGroup); $buttonGroup.add(" + id + "); }\n"; - } else if (name.equals(VALUE_PROPERTY)) { - String type = compiler.getImportedType( - JAXXButtonGroup.class.getName()); - return "{ " + id + ".putClientProperty(\"" + JAXXButtonGroup.VALUE_CLIENT_PROPERTY + "\", " + valueCode + "); Object $buttonGroup = " + id + ".getClientProperty(\"" + JAXXButtonGroup.BUTTON8GROUP_CLIENT_PROPERTY + "\");" + - " if ($buttonGroup instanceof " + type + ") { ((" + type + ") $buttonGroup).updateSelectedValue(); } }\n"; - } else { - return super.getSetPropertyCode(id, name, valueCode, compiler); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JScrollPaneHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JScrollPaneHandler.java deleted file mode 100644 index 1469ced..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JScrollPaneHandler.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import org.apache.commons.lang3.StringUtils; - -import javax.swing.JScrollPane; - -public class JScrollPaneHandler extends DefaultComponentHandler { - - public static class JScrollPaneCompiledObject extends CompiledObject { - - boolean hasChild; - - boolean hasColumnViewHeader; - - public static final String COLUMN_HEADER_VIEW = "columnHeaderView"; - - public JScrollPaneCompiledObject(String id, - ClassDescriptor beanclass, - JAXXCompiler compiler) { - super(id, beanclass, compiler); - } - - @Override - public void addChild(CompiledObject child, - String constraints, - JAXXCompiler compiler) throws CompilerException { - if (constraints != null) { - compiler.reportError("JScrollPane does not accept constraints"); - } - - if (!hasChild) { - // first child is always the view port component - super.addChild(child, constraints, compiler); - hasChild = true; - return; - } - - if (!hasColumnViewHeader) { - - // try to add a column view header - String property = - (String) getProperties().get(COLUMN_HEADER_VIEW); - - if (log.isDebugEnabled()) { - log.info("property to match " + property + " against child " + child.getId()); - } - if (!StringUtils.isEmpty(property) && - ("{" + child.getId() + "}").equals(property)) { - hasColumnViewHeader = true; - return; - } - } - - compiler.reportError( - "JScrollPane may only have one child (found another child : " + child.getId() + ")."); - - } - } - - public JScrollPaneHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), - beanClass, - JScrollPane.class - ); - } - - @Override - public CompiledObject createCompiledObject(String id, - JAXXCompiler compiler) throws CompilerException { - return new JScrollPaneCompiledObject(id, getBeanClass(), compiler); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSliderHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSliderHandler.java deleted file mode 100644 index 5d38db4..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSliderHandler.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; - -import javax.swing.JSlider; -import javax.swing.event.ChangeListener; - -public class JSliderHandler extends DefaultComponentHandler { - public static final String ATTRIBUTE_VALUE = "value"; - - public JSliderHandler(ClassDescriptor beanClass) { - super(beanClass); - if (!ClassDescriptorHelper.getClassDescriptor(JSlider.class).isAssignableFrom(beanClass)) { - throw new IllegalArgumentException(getClass().getName() + " does not support the class " + beanClass.getName()); - } - } - - @Override - protected int getAttributeOrdering(Attr attr) { - if (attr.getName().equals(ATTRIBUTE_VALUE)) { - return 1; - } else { - return super.getAttributeOrdering(attr); - } - } - - @Override - protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { - super.setDefaults(object, tag, compiler); - setAttribute(object, ATTRIBUTE_VALUE, "0", false, compiler); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("getValue", ChangeListener.class, "model"); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSpinnerHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSpinnerHandler.java deleted file mode 100644 index 32d0317..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSpinnerHandler.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import org.w3c.dom.Element; - -import javax.swing.JSpinner; -import javax.swing.SpinnerNumberModel; -import javax.swing.event.ChangeListener; - -public class JSpinnerHandler extends DefaultComponentHandler { - - public static String MINIMUM_PROPERTY = "minimum"; - - public static String MAXIMUM_PROPERTY = "maximum"; - - public static String VALUE_PROPERTY = "value"; - - public JSpinnerHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JSpinner.class); - } - - public static class CompiledSpinner extends CompiledObject { - - Integer minimum; - - Integer maximum; - - Integer value; - - public CompiledSpinner(String id, ClassDescriptor objectClass, JAXXCompiler compiler) throws CompilerException { - super(id, objectClass, compiler); - } - } - - @Override - public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { - return new CompiledSpinner(id, getBeanClass(), compiler); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("getValue", ChangeListener.class, "model"); - } - - @Override - public ClassDescriptor getPropertyType(CompiledObject object, String propertyName, JAXXCompiler compiler) throws CompilerException { - if (propertyName.equals(MINIMUM_PROPERTY) || propertyName.equals(MAXIMUM_PROPERTY) || - propertyName.equals(VALUE_PROPERTY)) { - return ClassDescriptorHelper.getClassDescriptor(Integer.class); - } - return super.getPropertyType(object, propertyName, compiler); - } - - @Override - public void setProperty(CompiledObject object, String name, Object value, JAXXCompiler compiler) throws CompilerException { - if (name.equals(MINIMUM_PROPERTY)) { - ((CompiledSpinner) object).minimum = (Integer) value; - } else if (name.equals(MAXIMUM_PROPERTY)) { - ((CompiledSpinner) object).maximum = (Integer) value; - } else if (name.equals(VALUE_PROPERTY)) { - ((CompiledSpinner) object).value = (Integer) value; - } else { - super.setProperty(object, name, value, compiler); - } - } - - @Override - protected void closeComponent(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { - CompiledSpinner spinner = (CompiledSpinner) object; - if (spinner.minimum != null || - spinner.maximum != null || - spinner.value != null) { - if (spinner.getConstructorParams() != null) { - compiler.reportError("constructorParams and minimum/maximum may not both be specified for the same JSpinner"); - } - if (spinner.minimum == null) { - spinner.minimum = Math.min(0, spinner.maximum != null ? spinner.maximum : 0); - } - if (spinner.maximum == null) { - spinner.maximum = Math.max(100, spinner.minimum.intValue()); - } - if (spinner.value == null) { - spinner.value = spinner.minimum; - } - String type = compiler.getImportedType(SpinnerNumberModel.class); - - spinner.setConstructorParams("new " + type + "(" + spinner.value + ", " + spinner.minimum + ", " + spinner.maximum + ", 1)"); - } - - super.closeComponent(object, tag, compiler); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSplitPaneHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSplitPaneHandler.java deleted file mode 100644 index 7a60aa2..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSplitPaneHandler.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; - -import javax.swing.JSplitPane; - -public class JSplitPaneHandler extends DefaultComponentHandler { - - public static final String ATTRIBUTE_ORIENTATION = "orientation"; - - public static final String ORIENTATION_VALUE_HORIZONTAL = "horizontal"; - - public static final String ORIENTATION_VALUE_VERTICAL = "vertical"; - - public static final String ORIENTATION_VALUE_VERTICAL_SPLIT = "vertical_split"; - - public static final String ORIENTATION_VALUE_HORIZONTAL_SPLIT = "horizontal_split"; - - public JSplitPaneHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JSplitPane.class); - } - -// protected Component createRawComponent(Element tag) { -// return new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); -// } - - /** - * Add support for <code>orientation="vertical"</code> and <code>orientation="horizontal"</code>. The - * values required by the JAXXBeanInfo are the unwieldy <code>vertical_split</code> and <code>horizontal_split</code> - * (which are also recognized). - */ - @Override - protected int constantValue(String key, String value) { - if (key.equals(ATTRIBUTE_ORIENTATION)) { - value = value.trim().toLowerCase(); - if (value.equals(ORIENTATION_VALUE_HORIZONTAL) || - value.equals(ORIENTATION_VALUE_HORIZONTAL_SPLIT)) { - return JSplitPane.HORIZONTAL_SPLIT; - } - if (value.equals(ORIENTATION_VALUE_VERTICAL) || - value.equals(ORIENTATION_VALUE_VERTICAL_SPLIT)) { - return JSplitPane.VERTICAL_SPLIT; - } - throw new IllegalArgumentException("orientation must be 'horizontal' or 'vertical', found '" + value + "'"); - } - return super.constantValue(key, value); - } - - @Override - public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { - return new CompiledObject(id, getBeanClass(), compiler) { - - private int count; - - @Override - public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { - if (constraints != null) { - compiler.reportError("JSplitPane does not accept constraints"); - } - if (count == 0) { - super.addChild(child, "JSplitPane.LEFT", compiler); - } else if (count == 1) { - super.addChild(child, "JSplitPane.RIGHT", compiler); - } else { - compiler.reportError("JSplitPane is limited to two children"); - } - count++; - } - }; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTabbedPaneHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTabbedPaneHandler.java deleted file mode 100644 index cb502c0..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTabbedPaneHandler.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.I18nHelper; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.swing.TabInfo; -import jaxx.runtime.swing.TabInfoPropertyChangeListener; - -import javax.swing.Icon; -import javax.swing.JTabbedPane; -import javax.swing.event.ChangeListener; -import java.awt.Color; -import java.awt.event.ContainerListener; - -public class JTabbedPaneHandler extends DefaultComponentHandler { - - public static final String ATTRIBUTE_TITLE = "title"; - - public static final String ATTRIBUTE_TOOL_TIP_TEXT = "toolTipText"; - - public JTabbedPaneHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JTabbedPane.class); - } - - public static class CompiledTabbedPane extends CompiledObject { - - private static final TabInfo USED = new TabInfo("ALREADY USED"); - - int tabCount; - - TabInfo tabInfo; - - - public CompiledTabbedPane(String id, ClassDescriptor objectClass, JAXXCompiler compiler) throws CompilerException { - super(id, objectClass, compiler); - } - - @Override - public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { - if (constraints != null) { - compiler.reportError("JTabbedPane tabs may not have constraints"); - } - - super.addChild(child, constraints, compiler); - - if (tabInfo == null) { - compiler.reportError("JTabbedPaneHandler may only have 'tab' tags as children (found " + child.getObjectClass() + ")"); - return; - } else if (USED.equals(tabInfo)) { - compiler.reportError("<tab> tags may only have one child component"); - return; - } - - int tabIndex = ++tabCount - 1; - String type = compiler.getImportedType(TabInfoPropertyChangeListener.class); - appendAdditionCode(tabInfo.getId() + ".addPropertyChangeListener(new " + type + "(" + getId() + ", " + tabIndex + "));"); - - String title = tabInfo.getTitle(); - if (title != null) { - if (I18nHelper.isI18nAttribute(ATTRIBUTE_TITLE)) { - if (!title.startsWith("t(\"")) { - // we did not have the invocation code, add it - title = I18nHelper.addI18nInvocation(getId(), ATTRIBUTE_TITLE, TypeManager.getJavaCode(title), compiler); - } - } else { - title = TypeManager.getJavaCode(title); - } - appendAdditionCode(getId() + ".setTitleAt(" + tabIndex + ", " + title + ");"); - } - - String toolTipText = tabInfo.getToolTipText(); - if (toolTipText != null) { - if (I18nHelper.isI18nAttribute(ATTRIBUTE_TOOL_TIP_TEXT)) { - if (!toolTipText.startsWith("t(\"")) { - // we did not have the invocation code, add it - toolTipText = I18nHelper.addI18nInvocation(getId(), ATTRIBUTE_TOOL_TIP_TEXT, TypeManager.getJavaCode(toolTipText), compiler); - } - } else { - toolTipText = TypeManager.getJavaCode(toolTipText); - } - appendAdditionCode(getId() + ".setToolTipTextAt(" + tabIndex + ", " + toolTipText + ");"); - } - - boolean enabled = tabInfo.isEnabled(); - if (!enabled) { - appendAdditionCode(getId() + ".setEnabledAt(" + tabIndex + ", false);"); - } - - Color foreground = tabInfo.getForeground(); - if (foreground != null) { - appendAdditionCode(getId() + ".setForegroundAt(" + tabIndex + ", " + TypeManager.getJavaCode(foreground) + ");"); - } - - Color background = tabInfo.getBackground(); - if (background != null) { - appendAdditionCode(getId() + ".setBackgroundAt(" + tabIndex + ", " + TypeManager.getJavaCode(background) + ");"); - } - - int mnemonic = tabInfo.getMnemonic(); - if (mnemonic != -1) { - appendAdditionCode(getId() + ".setMnemonicAt(" + tabIndex + ", " + mnemonic + ");"); - } - - int displayedMnemonicIndex = tabInfo.getDisplayedMnemonicIndex(); - if (displayedMnemonicIndex != -1) { - appendAdditionCode(getId() + ".setDisplayedMnemonicIndexAt(" + tabIndex + ", " + displayedMnemonicIndex + ");"); - } - - Icon icon = tabInfo.getIcon(); - if (icon != null) { - appendAdditionCode(getId() + ".setIconAt(" + tabIndex + ", " + icon + ");"); - } - - Icon disabledIcon = tabInfo.getDisabledIcon(); - if (disabledIcon != null) { - appendAdditionCode(getId() + ".setDisabledIconAt(" + tabIndex + ", " + disabledIcon + ");"); - } - - String tabComponent = tabInfo.getTabComponentStr(); - if (tabComponent != null) { - appendAdditionCode(getId() + ".setTabComponentAt(" + tabIndex + ", " + tabComponent + ");"); - } - - tabInfo = USED; - } - } - - @Override - public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { - return new CompiledTabbedPane(id, getBeanClass(), compiler); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("getSelectedIndex", ChangeListener.class); - addProxyEventInfo("getSelectedComponent", ChangeListener.class); - addProxyEventInfo("getTabCount", ContainerListener.class); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTextComponentHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTextComponentHandler.java deleted file mode 100644 index a9d88bf..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTextComponentHandler.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import jaxx.runtime.SwingUtil; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; - -import javax.swing.JTextArea; -import javax.swing.event.DocumentListener; -import javax.swing.text.JTextComponent; - -public class JTextComponentHandler extends DefaultComponentHandler { - - private static final int DEFAULT_COLUMNS = 15; - - public static final String ATTRIBUTE_LINE_WRAP = "lineWrap"; - - public static final String ATTRIBUTE_WRAP_STYLE_WORD = "wrapStyleWord"; - - public static final String ATTRIBUTE_COLUMNS = "columns"; - - public static final String ATTRIBUTE_TEXT = "text"; - - public JTextComponentHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), - beanClass, - JTextComponent.class); - } - - @Override - protected void setDefaults(CompiledObject object, - Element tag, - JAXXCompiler compiler) throws CompilerException { - super.setDefaults(object, tag, compiler); - try { - object.getObjectClass().getMethodDescriptor("setColumns", - ClassDescriptorHelper.getClassDescriptor(int.class) - ); - setAttribute(object, - ATTRIBUTE_COLUMNS, - String.valueOf(DEFAULT_COLUMNS), - false, - compiler - ); - } catch (NoSuchMethodException e) { - // ignore ? - } - - if (ClassDescriptorHelper.getClassDescriptor(JTextArea.class).isAssignableFrom(object.getObjectClass())) { - setAttribute(object, ATTRIBUTE_LINE_WRAP, "true", false, compiler); - setAttribute(object, ATTRIBUTE_WRAP_STYLE_WORD, "true", false, compiler); - } - } - - @Override - public String getSetPropertyCode(String id, - String name, - String valueCode, - JAXXCompiler compiler) throws CompilerException { - if (name.equals(ATTRIBUTE_TEXT)) { - String prefix = compiler.getImportedType(SwingUtil.class); - return prefix + ".setText(" + - id + ", " + valueCode + ");" + - JAXXCompiler.getLineSeparator(); - } - return super.getSetPropertyCode(id, name, valueCode, compiler); - } - - @Override - protected int getAttributeOrdering(Attr attr) { - // delay text in case other attributes affect how it's processed, as is the case - // with JEditorPane's contentType - if (ATTRIBUTE_TEXT.equals(attr.getName())) { - return 1; - } - return super.getAttributeOrdering(attr); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("getText", DocumentListener.class, "document"); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JToolBarHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JToolBarHandler.java deleted file mode 100644 index b4152a2..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JToolBarHandler.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; - -import javax.swing.JToolBar; - -public class JToolBarHandler extends DefaultComponentHandler { - - public static final String ATTRIBUTE_ORIENTATION = "orientation"; - - enum Orientation { - horizontal(JToolBar.HORIZONTAL), - vertical(JToolBar.VERTICAL); - - private final int intValue; - - Orientation(int intValue) { - this.intValue = intValue; - } - - public int getIntValue() { - return intValue; - } - } - - public JToolBarHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), - beanClass, - JToolBar.class - ); - } - - /** - * Add support for <code>orientation="vertical"</code> and <code>orientation="horizontal"</code>. These values should - * have been supported without any special effort on my part, but JToolBar's BeanInfo doesn't contain the enum attribute - * for the orientation property. - */ - @Override - protected int constantValue(String key, String value) { - if (ATTRIBUTE_ORIENTATION.equals(key)) { - value = value.trim().toLowerCase(); - Orientation fill = Orientation.valueOf(value); - if (fill == null) { - throw new CompilerException( - "invalid value for orientation attribute: '" + value + - "'"); - } - return fill.getIntValue(); - } - return super.constantValue(key, value); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTreeHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTreeHandler.java deleted file mode 100644 index 3e08f7d..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTreeHandler.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import javax.swing.JTree; -import javax.swing.event.TreeSelectionListener; -import java.io.IOException; - -public class JTreeHandler extends DefaultComponentHandler { - - public JTreeHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JTree.class); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("getSelectionCount", TreeSelectionListener.class, "selectionModel"); - addProxyEventInfo("getSelectionPath", TreeSelectionListener.class, "selectionModel"); - addProxyEventInfo("getSelectionPaths", TreeSelectionListener.class, "selectionModel"); - addProxyEventInfo("getSelectionRows", TreeSelectionListener.class, "selectionModel"); - addProxyEventInfo("getSelectionValue", TreeSelectionListener.class, "selectionModel"); - } - - @Override - public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - if (children.getLength() > 0) { - compiler.reportError("JTree does not accept childs"); - throw new CompilerException("JTree does not accept childs"); - } - } -} - - - diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JWindowHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JWindowHandler.java deleted file mode 100644 index 5d68583..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JWindowHandler.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import org.w3c.dom.Element; - -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JMenuBar; -import javax.swing.JWindow; -import java.io.IOException; -import java.util.Map; - -public class JWindowHandler extends DefaultComponentHandler { - - public JWindowHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JWindow.class, JFrame.class, JDialog.class); - } - - @Override - public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { - return new CompiledObject(id, getBeanClass(), compiler) { - - @Override - public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { - if (ClassDescriptorHelper.getClassDescriptor(JMenuBar.class).isAssignableFrom(child.getObjectClass())) { - appendAdditionCode(getId() + ".setJMenuBar(" + child.getId() + ");"); - } else { - super.addChild(child, constraints, compiler); - } - } - }; - } - - @Override - protected void openComponent(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { - if (compiler.getOpenComponent() != null) { - compiler.openInvisibleComponent(object); - } else { - super.openComponent(object, tag, compiler); - } - } - - @Override - public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - super.compileSecondPass(tag, compiler); - CompiledObject object = objectMap.get(tag); - Map<?, ?> properties = object.getProperties(); - if (!properties.containsKey("width") && !properties.containsKey("height")) { - compiler.appendLateInitializer(object.getId() + ".pack();\n"); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JXLayerHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JXLayerHandler.java deleted file mode 100644 index aa7c6ca..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JXLayerHandler.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import org.apache.commons.collections4.CollectionUtils; -import org.jdesktop.jxlayer.JXLayer; - -import java.awt.Component; - -/** - * To deal with JXLayer, since from version 3.0.4, we can not use any longer - * the {@link JXLayer#add(Component)} ! but must now use the - * method {@link JXLayer#setView(Component)}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.4 - */ -public class JXLayerHandler extends DefaultComponentHandler { - - public static final String ATTRIBUTE_ORIENTATION = "orientation"; - - public static final String ORIENTATION_VALUE_HORIZONTAL = "horizontal"; - - public static final String ORIENTATION_VALUE_VERTICAL = "vertical"; - - public static final String ORIENTATION_VALUE_VERTICAL_SPLIT = "vertical_split"; - - public static final String ORIENTATION_VALUE_HORIZONTAL_SPLIT = "horizontal_split"; - - public JXLayerHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JXLayer.class); - } - - @Override - public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { - return new CompiledObject(id, getBeanClass(), compiler) { - - @Override - public void addChild(CompiledObject child, - String constraints, - JAXXCompiler compiler) throws CompilerException { - - if (constraints != null) { - compiler.reportError("JXLayer does not accept constraints"); - return; - } - if (CollectionUtils.isNotEmpty(getChilds())) { - - // already one child, authrozied only one child... - compiler.reportError("JXLayer is limited to one children"); - return; - } - super.addChild(child, constraints, compiler); - - } - - @Override - protected ChildRef newChildRef(CompiledObject child, String constraints, String delegateCode) { - return new ChildRef(child, - constraints, - child.getJavaCode(), - delegateCode) { - @Override - public void addToAdditionCode(StringBuilder buffer, boolean isRootObject) { - //TC-20091026 do not prefix if on root object - String prefix; - if (isRootObject) { - prefix = ""; - } else { - prefix = getJavaCode() + getDelegateCode() + "."; - } - buffer.append(prefix); - buffer.append("setView("); - buffer.append(getChildJavaCode()); - buffer.append(");"); - buffer.append(JAXXCompiler.getLineSeparator()); - } - }; - } - }; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/RowHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/RowHandler.java deleted file mode 100644 index 58ddacc..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/RowHandler.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.TagHandler; -import jaxx.runtime.swing.Table; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; - -import java.awt.GridBagConstraints; -import java.io.IOException; - -public class RowHandler implements TagHandler { - - public static final String TAG_NAME = "row"; - - @Override - public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - compileChildrenFirstPass(tag, compiler); - } - - @Override - public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - if (!ClassDescriptorHelper.getClassDescriptor(Table.class).isAssignableFrom(compiler.getOpenComponent().getObjectClass())) { - compiler.reportError("row tag may only appear within Table tag"); - return; - } - - TableHandler.CompiledTable table = (TableHandler.CompiledTable) compiler.getOpenComponent(); - table.newRow(); - GridBagConstraints c = table.getRowConstraints(); - CellHandler.setAttributes(c, tag); - compileChildrenSecondPass(tag, compiler); - } - - public void compileChildrenFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node node = children.item(i); - int nodeType = node.getNodeType(); - if (nodeType == Node.ELEMENT_NODE) { - Element child = (Element) node; - if (!child.getLocalName().equals(CellHandler.TAG_NAME)) { - compiler.reportError("tag '" + tag.getLocalName() + "' may only contain cell tags as children"); - } - compileChildTagFirstPass(child, compiler); - } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { - String text = ((Text) node).getData().trim(); - if (text.length() > 0) { - compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); - } - } - } - } - - public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node node = children.item(i); - int nodeType = node.getNodeType(); - if (nodeType == Node.ELEMENT_NODE) { - Element child = (Element) node; - if (!child.getLocalName().equals(CellHandler.TAG_NAME)) { - compiler.reportError("tag '" + tag.getLocalName() + "' may only contain cell tags as children"); - } - compileChildTagSecondPass(child, compiler); - } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { - String text = ((Text) node).getData().trim(); - if (text.length() > 0) { - compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); - } - } - } - } - - protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - compiler.compileFirstPass(tag); - } - - protected void compileChildTagSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - compiler.compileSecondPass(tag); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/TabHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/TabHandler.java deleted file mode 100644 index a3829f0..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/TabHandler.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.I18nHelper; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.binding.DataBindingHelper; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.TagHandler; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.swing.TabInfo; -import org.apache.commons.lang3.StringUtils; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; - -import javax.swing.Icon; -import javax.swing.JTabbedPane; -import java.awt.Color; -import java.io.IOException; - -public class TabHandler implements TagHandler { - - public static final String TAG_NAME = "tab"; - - public static final String ATTRIBUTE_ID = "id"; - - public static final String ATTRIBUTE_TITLE = "title"; - - public static final String ATTRIBUTE_TOOL_TIP_TEXT = "toolTipText"; - - public static final String ATTRIBUTE_ICON = "icon"; - - public static final String ATTRIBUTE_ENABLED = "enabled"; - - public static final String ATTRIBUTE_DISABLED_ICON = "disabledIcon"; - - public static final String ATTRIBUTE_MNEMONIC = "mnemonic"; - - public static final String ATTRIBUTE_DISPLAYED_MNEMONIC_INDEX = "displayedMnemonicIndex"; - - public static final String ATTRIBUTE_FOREGROUND = "foreground"; - - public static final String ATTRIBUTE_BACKGROUND = "background"; - - public static final String ATTRIBUTE_TAB_COMPONENT = "tabComponent"; - - @Override - public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - compileChildrenFirstPass(tag, compiler); - } - - @Override - public void compileSecondPass(Element tag, final JAXXCompiler compiler) throws CompilerException, IOException { - if (!ClassDescriptorHelper.getClassDescriptor(JTabbedPane.class).isAssignableFrom(compiler.getOpenComponent().getObjectClass())) { - compiler.reportError("tab tag may only appear within JTabbedPane tag"); - return; - } - - JTabbedPaneHandler.CompiledTabbedPane tabs = (JTabbedPaneHandler.CompiledTabbedPane) compiler.getOpenComponent(); - - String id = tag.getAttribute(ATTRIBUTE_ID); - if (id == null || id.length() == 0) { - id = compiler.getAutoId(TabInfo.class.getSimpleName()); -// id = compiler.getAutoId(ClassDescriptorHelper.getClassDescriptor(TabInfo.class)); - } - TabInfo tabInfo = new TabInfo(id); - CompiledObject compiledTabInfo = new CompiledObject(id, ClassDescriptorHelper.getClassDescriptor(TabInfo.class), compiler); - compiler.registerCompiledObject(compiledTabInfo); - //id = tabInfo.getId(); - tabs.tabInfo = tabInfo; - setAttributes(compiledTabInfo, tabs, tag, compiler); - compileChildrenSecondPass(tag, compiler); - tabs.tabInfo = null; - } - - public static void setAttribute(CompiledObject compiledTabInfo, JTabbedPaneHandler.CompiledTabbedPane tabs, String name, String value, JAXXCompiler compiler) throws CompilerException { - value = value.trim(); - TabInfo tabInfo = tabs.tabInfo; - String id = tabInfo.getId(); - String binding = DataBindingHelper.processDataBindings(value); - if (binding != null) { - compiler.getBindingHelper().registerDataBinding(id + "." + name, binding, id + ".set" + StringUtils.capitalize(name) + "(" + binding + ");"); -// compiler.getBindingHelper().registerDataBinding(binding, id + "." + name, id + ".set" + StringUtils.capitalize(name) + "(" + binding + ");"); - return; - } - - String valueCode = TypeManager.getJavaCode(value); - - // add i18n support - if (I18nHelper.isI18nableAttribute(name, compiler)) { - value = valueCode = I18nHelper.addI18nInvocation(id, name, valueCode, compiler); - } - if (name.equals(ATTRIBUTE_ID)) { - // ignore, already handled - } else if (name.equals(ATTRIBUTE_TITLE)) { - tabInfo.setTitle(value); - compiledTabInfo.appendInitializationCode(id + ".setTitle(" + valueCode + ");"); - //compiledTabInfo.appendInitializationCode(id + ".setTitle(" + TypeManager.getJavaCode(value) + ");"); - } else if (name.equals(ATTRIBUTE_TOOL_TIP_TEXT)) { - tabInfo.setToolTipText(value); - compiledTabInfo.appendInitializationCode(id + ".setToolTipText(" + valueCode + ");"); - //compiledTabInfo.appendInitializationCode(id + ".setToolTipText(" + TypeManager.getJavaCode(value) + ");"); - } else if (name.equals(ATTRIBUTE_ICON)) { - Icon icon = (Icon) TypeManager.convertFromString(value, Icon.class); - tabInfo.setIcon(icon); - compiledTabInfo.appendInitializationCode(id + ".setIcon(" + TypeManager.getJavaCode(icon) + ");"); - } else if (name.equals(ATTRIBUTE_ENABLED)) { - boolean enabled = (Boolean) TypeManager.convertFromString(value, Boolean.class); - tabInfo.setEnabled(enabled); - compiledTabInfo.appendInitializationCode(id + ".setEnabled(" + enabled + ");"); - } else if (name.equals(ATTRIBUTE_DISABLED_ICON)) { - Icon disabledIcon = (Icon) TypeManager.convertFromString(value, Icon.class); - tabInfo.setDisabledIcon(disabledIcon); - compiledTabInfo.appendInitializationCode(id + ".setDisabledIcon(" + TypeManager.getJavaCode(disabledIcon) + ");"); - } else if (name.equals(ATTRIBUTE_MNEMONIC)) { - int mnemonic = (Character) TypeManager.convertFromString(value, char.class); - tabInfo.setMnemonic(mnemonic); - compiledTabInfo.appendInitializationCode(id + ".setMnemonic(" + mnemonic + ");"); - } else if (name.equals(ATTRIBUTE_DISPLAYED_MNEMONIC_INDEX)) { - int displayedMnemonicIndex = (Integer) TypeManager.convertFromString(value, int.class); - tabInfo.setDisplayedMnemonicIndex(displayedMnemonicIndex); - compiledTabInfo.appendInitializationCode(id + ".setDisplayedMnemonicIndex(" + displayedMnemonicIndex + ");"); - } else if (name.equals(ATTRIBUTE_FOREGROUND)) { - Color foreground = (Color) TypeManager.convertFromString(value, Color.class); - tabInfo.setForeground(foreground); - compiledTabInfo.appendInitializationCode(id + ".setForeground(" + TypeManager.getJavaCode(foreground) + ");"); - } else if (name.equals(ATTRIBUTE_BACKGROUND)) { - Color background = (Color) TypeManager.convertFromString(value, Color.class); - tabInfo.setBackground(background); - compiledTabInfo.appendInitializationCode(id + ".setBackground(" + TypeManager.getJavaCode(background) + ");"); - } else if (name.equals(ATTRIBUTE_TAB_COMPONENT)) { - tabInfo.setTabComponentStr(TypeManager.getJavaCode(value)); - compiledTabInfo.appendInitializationCode(id + ".setTabComponent(" + TypeManager.getJavaCode(value) + ");"); - } else { - compiler.reportError("The <tab> tag does not support the attribute '" + name + "'"); - } - } - - public void setAttributes(CompiledObject compiledTabInfo, JTabbedPaneHandler.CompiledTabbedPane tabs, Element tag, JAXXCompiler compiler) throws CompilerException { - NamedNodeMap children = tag.getAttributes(); - for (int i = 0; i < children.getLength(); i++) { - Attr attribute = (Attr) children.item(i); - String name = attribute.getName(); - String value = attribute.getValue(); - if (!name.startsWith("xmlns") && !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { - setAttribute(compiledTabInfo, tabs, name, value, compiler); - } - } - } - - protected void compileChildrenFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node node = children.item(i); - int nodeType = node.getNodeType(); - if (nodeType == Node.ELEMENT_NODE) { - Element child = (Element) node; - compileChildTagFirstPass(child, compiler); - } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { - String text = ((Text) node).getData().trim(); - if (text.length() > 0) { - compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); - } - } - } - } - - protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - compiler.compileFirstPass(tag); - } - - protected void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node node = children.item(i); - int nodeType = node.getNodeType(); - if (nodeType == Node.ELEMENT_NODE) { - Element child = (Element) node; - compileChildTagSecondPass(child, compiler); - } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { - String text = ((Text) node).getData().trim(); - if (text.length() > 0) { - compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); - } - } - } - } - - protected void compileChildTagSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - compiler.compileSecondPass(tag); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/TableHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/TableHandler.java deleted file mode 100644 index 5353a38..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/TableHandler.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.swing; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.UnsupportedAttributeException; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultComponentHandler; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.swing.Table; - -import java.awt.GridBagConstraints; -import java.awt.Insets; -import java.util.ArrayList; -import java.util.List; - -public class TableHandler extends DefaultComponentHandler { - - public static final Insets DEFAULT_INSETS = new Insets(3, 3, 3, 3); - - public TableHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass(getClass(), - beanClass, - Table.class); - } - - @Override - public void setAttribute(CompiledObject object, - String propertyName, - String stringValue, - boolean inline, - JAXXCompiler compiler) throws CompilerException { - try { - if (object instanceof CompiledTable) { - CellHandler.setAttribute( - ((CompiledTable) object).getTableConstraints(), - propertyName, - stringValue - ); - } else { - super.setAttribute(object, - propertyName, - stringValue, - inline, - compiler); - } - } catch (UnsupportedAttributeException e) { - super.setAttribute(object, - propertyName, - stringValue, - inline, - compiler - ); - } - } - - class CompiledTable extends CompiledObject { - - private List<Integer> rowSpans = new ArrayList<>(); - - private GridBagConstraints tableConstraints; - - private GridBagConstraints rowConstraints; - - private GridBagConstraints cellConstraints; - - private boolean emptyCell; - - public CompiledTable(String id, - ClassDescriptor objectClass, - JAXXCompiler compiler) throws CompilerException { - super(id, objectClass, compiler); - tableConstraints = new GridBagConstraints(); - tableConstraints.gridx = -1; - tableConstraints.gridy = -1; - tableConstraints.insets = DEFAULT_INSETS; - } - - @Override - public void addChild(CompiledObject child, - String constraints, - JAXXCompiler compiler) throws CompilerException { - if (constraints != null) { - compiler.reportError("Table does not accept constraints"); - } - GridBagConstraints c = getCellConstraints(); - if (c == null) { - compiler.reportError("Table tag may only contain row tags"); - return; - } - if (!emptyCell) { - compiler.reportError( - "Table cells may only have one child component"); - } - while (rowSpans.size() < c.gridx + c.gridwidth) { - rowSpans.add(null); - } - for (int x = c.gridx; x < c.gridx + c.gridwidth; x++) { - rowSpans.set(x, c.gridheight); - } - - super.addChild(child, TypeManager.getJavaCode(c), compiler); - - emptyCell = false; - - compiler.addImport(GridBagConstraints.class); - compiler.addImport(Insets.class); - } - - public GridBagConstraints getTableConstraints() { - return tableConstraints; - } - - public GridBagConstraints getRowConstraints() { - return rowConstraints; - } - - public GridBagConstraints getCellConstraints() { - return cellConstraints; - } - - public void newRow() { - tableConstraints.gridy++; - tableConstraints.gridx = -1; - rowConstraints = (GridBagConstraints) tableConstraints.clone(); - - for (int x = 0; x < rowSpans.size(); x++) { - int rowSpan = rowSpans.get(x); - if (rowSpan > 0) { - rowSpans.set(x, rowSpan - 1); - } - } - } - - public void newCell() { - emptyCell = true; - rowConstraints.gridx++; - while (rowConstraints.gridx < rowSpans.size() && - rowSpans.get(rowConstraints.gridx) > 0) { - rowConstraints.gridx++; - } - cellConstraints = (GridBagConstraints) rowConstraints.clone(); - } - } - - @Override - public CompiledObject createCompiledObject(String id, - JAXXCompiler compiler) throws CompilerException { - return new CompiledTable(id, getBeanClass(), compiler); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/BeanValidatorHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/BeanValidatorHandler.java deleted file mode 100644 index a2b6676..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/BeanValidatorHandler.java +++ /dev/null @@ -1,1092 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.validator; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.beans.JAXXBeanInfo; -import jaxx.compiler.beans.JAXXPropertyDescriptor; -import jaxx.compiler.binding.DataBindingHelper; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.DefaultObjectHandler; -import jaxx.compiler.types.TypeManager; -import jaxx.runtime.validator.swing.SwingValidator; -import jaxx.runtime.validator.swing.SwingValidatorUtil; -import jaxx.runtime.validator.swing.ui.AbstractBeanValidatorUI; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Element; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -public class BeanValidatorHandler extends DefaultObjectHandler { - - public static final String TAG = "BeanValidator"; - - public static final String BEAN_ATTRIBUTE = "bean"; - - public static final String BEAN_CLASS_ATTRIBUTE = "beanClass"; - - public static final String BEAN_INITIALIZER_ATTRIBUTE = "beanInitializer"; - - public static final String ERROR_LIST_MODEL_ATTRIBUTE = "errorListModel"; - - public static final String ERROR_TABLE_MODEL_ATTRIBUTE = "errorTableModel"; - - public static final String ERROR_LIST_ATTRIBUTE = "errorList"; - - public static final String ERROR_TABLE_ATTRIBUTE = "errorTable"; - - public static final String ERROR_LIST_MODEL_DEFAULT = "errorListModel"; - - public static final String ERROR_TABLE_MODEL_DEFAULT = "errorTableModel"; - - public static final String ERROR_LIST_DEFAULT = "errorList"; - - public static final String ERROR_TABLE_DEFAULT = "errorTable"; - - public static final String AUTOFIELD_ATTRIBUTE = "autoField"; - - public static final String UI_CLASS_ATTRIBUTE = "uiClass"; - - public static final String STRICT_MODE_ATTRIBUTE = "strictMode"; - - public static final String CONTEXT_ATTRIBUTE = "context"; - -// /** -// * @deprecated since 2.4.1, now use the {@link #CONTEXT_ATTRIBUTE}. -// */ -// @Deprecated -// public static final String CONTEXT_NAME_ATTRIBUTE = "contextName"; - //public static final String SCOPE_ATTRIBUTE = "scope"; - - public static final String PARENT_VALIDATOR_ATTRIBUTE = "parentValidator"; - - /** Logger */ - static Log log = LogFactory.getLog(BeanValidatorHandler.class); - - protected static Map<JAXXCompiler, List<CompiledBeanValidator>> validators = - new HashMap<>(); - - protected static Map<JAXXCompiler, List<String>> validatedComponents = - new HashMap<>(); - - public BeanValidatorHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorHelper.checkSupportClass( - getClass(), - beanClass, - SwingValidator.class - ); - } - - @Override - protected CompiledObject createCompiledObject(String id, - JAXXCompiler compiler) { - return new CompiledBeanValidator(id, getBeanClass(), compiler); - } - - @Override - protected void compileChildTagFirstPass( - Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - if (log.isDebugEnabled()) { - log.debug(tag); - } - if (!tag.getLocalName().equals(FieldValidatorHandler.TAG)) { - compiler.reportError( - "tag '" + tag.getParentNode().getLocalName() + - "' may only contain " + FieldValidatorHandler.TAG + - " as children, but found : " + tag.getLocalName()); - } else { - compiler.compileFirstPass(tag); - } - } - - @Override - public void compileSecondPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - - super.compileSecondPass(tag, compiler); - - CompiledBeanValidator info = (CompiledBeanValidator) objectMap.get(tag); - - boolean error = info.addErrorListModel(tag, this, compiler); - - if (!error) { - error = info.addErrorList(tag, compiler); - } - - if (!error) { - error = info.addErrorTableModel(tag, this, compiler); - } - - if (!error) { - error = info.addErrorTable(tag, compiler); - } - - if (!error) { - error = info.addUiClass(this, compiler); - } - - if (!error) { - error = info.addBean(tag, this, compiler); - } - - if (!error) { - error = info.addParentValidator(tag, this, compiler); - } - - if (error) { - log.warn("error were detected in second compile pass " + - "of CompiledObject [" + info + "]"); - } - - // close the compiled object - compiler.closeComponent(info); - } - - @Override - protected void setDefaults(CompiledObject object, - Element tag, - JAXXCompiler compiler) { - // open the compiled object - compiler.openInvisibleComponent(object); - } - - @Override - public void setAttribute(CompiledObject object, - String propertyName, - String stringValue, - boolean inline, - JAXXCompiler compiler) { - if (log.isDebugEnabled()) { - log.debug(propertyName + " : " + stringValue + " for " + object); - } -// if (CONTEXT_ATTRIBUTE.equals(propertyName)) { -// if (stringValue != null && !stringValue.trim().isEmpty()) { -// // usage of a deprecated contextName, says it to user... -// compiler.reportWarning("You are using a validator attribute named 'contextName' which is deprecated, prefer use now a context attribute."); -// } -// } - // delegate to the compiled object with is statefull - // (but not the tag handler) - object.addProperty(propertyName, stringValue); - } - - /** - * The compiled objet representing a BeanValidator to be generated in - * JAXXObject - * - * @author Tony Chemit - chemit@codelutin.com - */ - public static class CompiledBeanValidator extends CompiledObject { - - /** - * Map of field to add into validator. - * - * Keys are editors, Values are bean properties. - */ - protected Multimap<String, String> fields; - - /** - * Map of field to exclude. - * - * Keys are bean properties, Values are editors. - */ - protected Map<String, String> excludeFields; - - protected String bean; - - protected String beanClass; - - protected String context; - - protected String uiClass; - - protected String errorListModel; - - protected String errorList; - - protected Boolean autoField; - - protected Boolean strictMode; - - protected JAXXBeanInfo beanDescriptor; - - protected String errorTableModel; - - protected String errorTable; - - protected String parentValidator; - - public CompiledBeanValidator(String id, - ClassDescriptor objectClass, - JAXXCompiler compiler) { - //TC-20090524 Use the real class descriptor, not the one by default, - //TC-20090524 otherwise can not override the validator class while generation - //super(id, objectClass, compiler); - super(id, getDescriptor(objectClass, compiler), compiler); - fields = ArrayListMultimap.create(); - excludeFields = new TreeMap<>(); - if (log.isDebugEnabled()) { - log.debug("validator objectClass " + getObjectClass()); - } - } - - protected static ClassDescriptor getDescriptor( - ClassDescriptor objectClass, - JAXXCompiler compiler) { - Class<?> validatorClass = SwingValidator.class; -// compiler.getConfiguration().getValidatorClass(); - return ClassDescriptorHelper.getClassDescriptor(validatorClass); - } - - public Multimap<String, String> getFields() { - return fields; - } - - public boolean containsFieldEditor(String editorName) { - return fields.containsKey(editorName); - } - - public boolean containsFieldPropertyName(String propertyName) { - return fields.containsValue(propertyName); - } - - public Set<String> getFieldEditors() { - return fields.keySet(); - } - -// public Set<String> getFieldIds() { -// return fields.values(); -// } - - public boolean containsExcludeFieldEditor(String editorName) { - return excludeFields.containsValue(editorName); - } - - protected boolean containsExcludeFieldPropertyName(String editorName) { - return excludeFields.containsKey(editorName); - } - -// public Map<String, String> getExcludeFields() { -// return excludeFields; -// } - -// public Set<String> getExcludeFieldEditors() { -// return new HashSet<String>(excludeFields.values()); -// } - - public Set<String> getExcludeFieldPropertyNames() { - return excludeFields.keySet(); - } - - protected void removeFieldPropertyName(String propertyName) { - //must find the editor for this property - for (String editor : fields.keySet()) { - if (fields.containsEntry(editor, propertyName)) { - - fields.remove(editor, propertyName); - break; - } - } - } - - public void addField(String propertyName, String editor) { - fields.put(editor, propertyName); - } - - public void addExcludeField(String propertyName, String editor) { - excludeFields.put(propertyName, editor); - } - - public Collection<String> getFieldPropertyNames(String editor) { - return fields.get(editor); - } - -// public void setFields(Map<String, String> fields) { -// this.fields = fields; -// } - -// public void setExcludeFields(Map<String, String> excludeFields) { -// this.excludeFields = excludeFields; -// } - - @Override - public void addProperty(String property, String value) { - - if (BEAN_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - bean = value.trim(); - } - return; - } - -// if (CONTEXT_NAME_ATTRIBUTE.equals(property)) { -// if (value != null && !value.trim().isEmpty()) { -// context= value.trim(); -// } -// -// return; -// } - - if (CONTEXT_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - context = value.trim(); - } - return; - } - - if (BEAN_CLASS_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - beanClass = value.trim(); - } - return; - } - - if (ERROR_LIST_MODEL_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - errorListModel = value.trim(); - } - return; - } - - if (ERROR_LIST_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - errorList = value.trim(); - } - return; - } - - if (ERROR_TABLE_MODEL_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - errorTableModel = value.trim(); - } - return; - } - - if (ERROR_TABLE_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - errorTable = value.trim(); - } - return; - } - - if (UI_CLASS_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - uiClass = value.trim(); - } - return; - } - - if (AUTOFIELD_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - autoField = (Boolean) TypeManager.convertFromString( - value.trim(), - Boolean.class - ); - } - return; - } - - if (STRICT_MODE_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - strictMode = (Boolean) TypeManager.convertFromString( - value.trim(), - Boolean.class - ); - } - return; - } - - if (PARENT_VALIDATOR_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - parentValidator = value.trim(); - } - return; - } - - throw new CompilerException("property " + property + - " is not allowed on object " + this); - } - - public String getBean() { - return bean; - } - - public String getErrorListModel() { - return errorListModel; - } - - public boolean getAutoField() { - return autoField != null && autoField; - } - - public boolean getStrictMode() { - return strictMode != null && strictMode; - } - - public String getUiClass() { - return uiClass; - } - - public String getBeanClass() { - return beanClass; - } - - public String getContext() { - return context; - } - - public String getParentValidator() { - return parentValidator; - } - - public JAXXBeanInfo getBeanDescriptor(JAXXCompiler compiler) { - if (beanDescriptor == null && foundBean()) { - -// String beanClassName = null; - try { - //TC-20090111 beanClass is mandatory - // get the real bean class name (from bean or beanClass) - /*if (beanClass != null) { - beanClassName = beanClass; - } else { - beanClassName = compiler.getSymbolTable().getClassTagIds().get(bean); - if (beanClassName == null) { - compiler.reportError("could not find class of the bean '" + bean + "'"); - return null; - } - }*/ - ClassDescriptor beanClassDescriptor = - ClassDescriptorHelper.getClassDescriptor(beanClass); - beanDescriptor = DefaultObjectHandler.getJAXXBeanInfo( - beanClassDescriptor); - - } catch (Exception e) { - compiler.reportError( - "could not load class " + beanClass); - } - } - return beanDescriptor; - } - - @Override - public void addChild(CompiledObject child, - String constraints, - JAXXCompiler compiler) throws CompilerException { - // do nothing - compiler.reportError("can not add CompiledObject in the tag '" + - TAG + " (only field tags)"); - } - - public boolean foundBean() { - return !(beanClass == null || beanClass.isEmpty()); - } - - protected boolean addUiClass(BeanValidatorHandler handler, - JAXXCompiler compiler) { - boolean withError = false; - if (uiClass == null && - compiler.getConfiguration().getDefaultErrorUI() != null) { - uiClass = compiler.getConfiguration().getDefaultErrorUI().getName(); - } - if (uiClass != null) { - try { - ClassDescriptor uiClazz = - ClassDescriptorHelper.getClassDescriptor(uiClass); - if (!ClassDescriptorHelper.getClassDescriptor(AbstractBeanValidatorUI.class).isAssignableFrom(uiClazz)) { - compiler.reportError( - "attribute 'ui' :'" + uiClass + - "' is not assignable from class " + - AbstractBeanValidatorUI.class - ); - withError = true; - } else { - String prefix = compiler.getImportedType(uiClazz.getName()); - String code = handler.getSetPropertyCode( - getJavaCode(), - UI_CLASS_ATTRIBUTE, - prefix + ".class", - compiler - ); - appendAdditionCode(code); - } - } catch (ClassNotFoundException e) { - compiler.reportError("class not found '" + uiClass + "'"); - withError = true; - } - } - - return withError; - } - - protected boolean addErrorListModel(Element tag, - BeanValidatorHandler handler, - JAXXCompiler compiler) { - if (errorListModel == null) { - // try with the default "errors" - if (!compiler.checkReference( - tag, - ERROR_LIST_MODEL_DEFAULT, - false, - ERROR_LIST_MODEL_ATTRIBUTE)) { - return false; - } - errorListModel = ERROR_LIST_MODEL_DEFAULT; - } else { - if (errorListModel.startsWith("{") && - errorListModel.endsWith("}")) { - // this is a script, no check here - errorListModel = errorListModel.substring( - 1, - errorListModel.length() - 1).trim(); - } else if (!compiler.checkReference( - tag, - errorListModel, - true, - ERROR_LIST_MODEL_ATTRIBUTE)) { - // errorListModel is not defined - return true; - } - } - - String code = handler.getSetPropertyCode( - getJavaCode(), - ERROR_LIST_MODEL_ATTRIBUTE, - errorListModel, - compiler - ); - appendAdditionCode(code); - - return false; - } - - protected boolean addErrorTableModel(Element tag, - BeanValidatorHandler handler, - JAXXCompiler compiler) { - if (errorTableModel == null) { - // try with the default "errors" - if (!compiler.checkReference( - tag, - ERROR_TABLE_MODEL_DEFAULT, - false, - ERROR_LIST_MODEL_ATTRIBUTE)) { - return false; - } - errorTableModel = ERROR_TABLE_MODEL_DEFAULT; - } else { - if (errorTableModel.startsWith("{") && - errorTableModel.endsWith("}")) { - // this is a script, no check here - errorTableModel = errorTableModel.substring( - 1, errorTableModel.length() - 1).trim(); - } else if (!compiler.checkReference( - tag, - errorTableModel, - true, - ERROR_TABLE_MODEL_ATTRIBUTE)) { - // errorListModel is not defined - return true; - } - } - - String code = handler.getSetPropertyCode( - getJavaCode(), - ERROR_TABLE_MODEL_ATTRIBUTE, - errorTableModel, - compiler - ); - appendAdditionCode(code); - - return false; - - } - - protected boolean addParentValidator(Element tag, - BeanValidatorHandler handler, - JAXXCompiler compiler) { - if (parentValidator != null) { - String initializer; - if (parentValidator.startsWith("{") && - parentValidator.endsWith("}")) { - - // todo : should be able to bind - initializer = parentValidator.substring( - 1, - parentValidator.length() - 1 - ); - - } else { - // the attribute referes an existing widget - if (!compiler.checkReference( - tag, - parentValidator, - true, - PARENT_VALIDATOR_ATTRIBUTE)) { - // parentValidator is not defined - return true; - } - initializer = parentValidator; - } - String code = handler.getSetPropertyCode( - getJavaCode(), - PARENT_VALIDATOR_ATTRIBUTE, - initializer, - compiler - ); - appendAdditionCode(code); - } - return false; - } - - protected boolean addErrorList(Element tag, JAXXCompiler compiler) { - - if (errorList == null) { - // try with the default "errorList" - if (!compiler.checkReference( - tag, - ERROR_LIST_DEFAULT, - false, - ERROR_LIST_ATTRIBUTE)) { - return false; - } - errorList = ERROR_LIST_DEFAULT; - } else { - if (!compiler.checkReference( - tag, - errorList, - true, - ERROR_LIST_ATTRIBUTE)) { - return true; - } - } - - String prefix = compiler.getImportedType(SwingValidatorUtil.class); - - String code = prefix + - ".registerErrorListMouseListener(" + errorList + ");"; - appendAdditionCode(code); - - return false; - } - - protected boolean addErrorTable(Element tag, JAXXCompiler compiler) { - - if (errorTable == null) { - // try with the default "errorList" - if (!compiler.checkReference(tag, - ERROR_TABLE_DEFAULT, - false, - ERROR_TABLE_ATTRIBUTE)) { - return false; - } - errorTable = ERROR_TABLE_DEFAULT; - } else { - if (!compiler.checkReference(tag, - errorTable, - true, - ERROR_TABLE_ATTRIBUTE)) { - return true; - } - } - - String prefix = compiler.getImportedType(SwingValidatorUtil.class); - - String code = prefix + - ".registerErrorTableMouseListener(" + errorTable + - ");"; - appendAdditionCode(code); - - return false; - } - - protected boolean addBean(Element tag, - BeanValidatorHandler handler, - JAXXCompiler compiler) { - - if (beanClass == null || beanClass.isEmpty()) { - // try to guest beanClass from bean attribute - if (bean != null && !bean.isEmpty()) { - beanClass = compiler.getSymbolTable().getClassTagIds().get(bean); - if (beanClass == null) { - compiler.reportError( - "could not find class of the bean '" + bean + - "', and no beanClass was setted"); - return true; - } - } - } - if (beanClass == null) { - compiler.reportError( - "tag '" + tag + "' requires a 'beanClass' attribute, " + - "and could not guest it from 'bean' attribute " + - "(no bean attribute setted...)"); - return true; - } - - JAXXBeanInfo beanInfo = getBeanDescriptor(compiler); - if (beanInfo == null) { - compiler.reportError( - tag, - "could not find descriptor of class " + beanClass - ); - return true; - } - - String beanInitializer = null; - if (bean != null) { - - if (bean.startsWith("{") && bean.endsWith("}")) { - - String labelBinding = - DataBindingHelper.processDataBindings(bean); - if (labelBinding != null) { - compiler.getBindingHelper().registerDataBinding( - getId() + ".bean", - labelBinding, - getId() + ".setBean(" + labelBinding + ");" - ); - } -// // just has an intializer -// beanInitializer = bean.substring(1, bean.length() - 1); -// // this is not a real bean, so delete it - bean = null; - } else { - - if (!compiler.checkReference(tag, - bean, - true, - BEAN_ATTRIBUTE)) { - // could not find bean in compiled object - return true; - } - - if (isBeanUsedByValidator(compiler, bean)) { - compiler.reportError( - "the bean '" + bean + "' is already used in " + - "another the validator, can not used it in '" + - tag + "'" - ); - return true; - } - - /*if (beanInitializer != null) { - compiler.reportWarning("tag '" + tag + "' found a 'bean' and a 'beanInitializer' attributes, 'beanInitializer' is skipped"); - }*/ - beanInitializer = bean; - } - } - - if (beanInitializer != null) { - String code = handler.getSetPropertyCode( - getJavaCode(), - BEAN_ATTRIBUTE, - compiler.checkJavaCode(beanInitializer), - compiler - ); - appendAdditionCode(code); - } - - String beanClassName = beanInfo.getJAXXBeanDescriptor().getClassDescriptor().getName(); - String type = compiler.getImportedType(beanClassName); - // contextName must be in constructor to able to init validator with his correct contextName - String constructorParams = type + ".class, " + - TypeManager.getJavaCode(context); -// setConstructorParams(constructorParams); - String validatorFactoryFqn = - compiler.getConfiguration().getValidatorFactoryFQN(); - - String prefix = compiler.getImportedType(validatorFactoryFqn); - setInitializer( - prefix + ".newValidator(" + constructorParams + ")" - ); - - // add generic type to validator - setGenericTypes(beanClassName); - - if (getAutoField()) { - registerAutoFieldBean(tag, compiler, beanInfo); - } - - if (getBeanDescriptor(compiler) != null) { - - // add fieldrepresentation invocations -// addFieldRepresentations(tag, compiler); - - // register the validator in compiler - registerValidator(compiler, this); - - } - - return false; - } - - private void registerValidator( - JAXXCompiler compiler, - CompiledBeanValidator compiledBeanValidator) { - List<CompiledBeanValidator> vals = validators.get(compiler); - if (vals == null) { - vals = new ArrayList<>(); - validators.put(compiler, vals); - } - vals.add(compiledBeanValidator); - List<String> ids = validatedComponents.get(compiler); - if (ids == null) { - ids = new ArrayList<>(); - validatedComponents.put(compiler, ids); - } -// ids.addAll(compiledBeanValidator.getFields().values()); - ids.addAll(compiledBeanValidator.getFieldEditors()); - } - -// /** -// * Register in buffer all field representation to init (and to record in method {@link JAXXValidator#registerValidatorFields()} -// * -// * @param compiler the compiler used -// * @param javaFile generated file -// * @param buffer the buffer where to add code -// * @since 2.2.1 -// */ -// public void addFieldRepresentations(JAXXCompiler compiler, -// JavaFile javaFile, -// StringBuilder buffer) { -// for (String component : fields.keySet()) { -//// String component = entry.getKey(); -// Collection<String> propertyNames = fields.get(component); -// List<String> keyCodes = -// Lists.newArrayListWithCapacity(propertyNames.size()); -// for (String propertyName : propertyNames) { -// if (!checkBeanProperty(compiler, propertyName)) { -// // property not find on bean -// continue; -// } -// String keyCode = TypeManager.getJavaCode(propertyName); -// keyCodes.add(keyCode); -// } -// -// if (keyCodes.isEmpty()) { -// // no property -// continue; -// } -// String keyCode = Joiner.on(", ").join(keyCodes); -// if (keyCodes.size()>1) { -// keyCode = "{ " + keyCode+" }"; -// } -//// String propertyName = entry.getKey(); -// -// String validatorId = TypeManager.getJavaCode(getId()); -// -// String editorCode = TypeManager.getJavaCode(component); -// JavaField editor = javaFile.getField(component); -// String annotation = ValidatorField.class.getSimpleName() + -// "( validatorId = " + validatorId + "," + -// " propertyName = " + keyCode + "," + -// " editorName = " + editorCode + "" + -// ")"; -// editor.addAnnotation(annotation); -// -//// if (!compiler.checkReference(tag, component, true, null)) { -//// // editor component not find on ui -//// continue; -//// } -// -//// buffer.append(getJavaCode()); -//// buffer.append(".setFieldRepresentation("); -//// buffer.append(keyCode); -//// buffer.append(", "); -//// buffer.append(component); -//// buffer.append(");\n"); -// } -// } - - protected void registerAutoFieldBean(Element tag, - JAXXCompiler compiler, - JAXXBeanInfo beanInfo) { - for (JAXXPropertyDescriptor beanProperty : - beanInfo.getJAXXPropertyDescriptors()) { - String descriptionName = beanProperty.getName(); - if (log.isDebugEnabled()) { - log.debug("try to bind on bean " + - beanInfo.getJAXXBeanDescriptor().getName() + - " property " + descriptionName); - } - if (beanProperty.getWriteMethodDescriptor() == null) { - // read-only property - continue; - } -// if (fields.containsKey(descriptionName)) { - if (containsFieldPropertyName(descriptionName)) { - // already defined in field - continue; - } -// if (excludeFields.containsKey(descriptionName)) { - if (containsExcludeFieldPropertyName(descriptionName)) { - // exclude field - continue; - } - if (!compiler.checkReference(tag, - descriptionName, - getStrictMode(), - null)) { - // no editor component found - continue; - } - // ok add the field mapping - registerField(descriptionName, descriptionName, compiler); - } - -// for (Entry<String, String> entry : excludeFields.entrySet()) { - for (String key : getExcludeFieldPropertyNames()) { -// String key = entry.getKey(); -// if (fields.containsKey(key)) { - if (containsFieldPropertyName(key)) { - compiler.reportWarning( - "field '" + key + "' can not be used and " + - "excluded at same time ! (field is skipped) " + - "for validator " + this - ); -// fields.remove(key); - removeFieldPropertyName(key); - } - } - } - - public void registerField(String id, - String component, - JAXXCompiler compiler) { -// if (fields.containsKey(id)) { - if (containsFieldPropertyName(id)) { - compiler.reportError( - "duplicate field '" + id + "' for validator " + this); - } else { - if (log.isDebugEnabled()) { - log.debug("add field <" + id + ":" + component + ">"); - } -// fields.put(id, component); - addField(id, component); - - } - } - - public void registerExcludeField(String id, - String component, - JAXXCompiler compiler) { -// if (excludeFields.containsKey(id)) { - if (containsExcludeFieldPropertyName(id)) { - compiler.reportError( - "duplicate field '" + id + "' for validator " + this); - } else { - if (log.isDebugEnabled()) { - log.debug("add excludeField <" + id + ":" + component + ">"); - } -// excludeFields.put(id, component); - addExcludeField(id, component); - } - } - - public boolean checkBeanProperty(JAXXCompiler compiler, - String propertyName) { - - for (JAXXPropertyDescriptor beanProperty : - getBeanDescriptor(compiler).getJAXXPropertyDescriptors()) { - if (beanProperty.getName().equals(propertyName)) { - if (beanProperty.getWriteMethodDescriptor() == null) { - // read-onlyproperty - compiler.reportError( - "could not bind the readonly property '" + - propertyName + "' on bean [" + getBean() + "] "); - return false; - } - return true; - } - } - compiler.reportError( - "could not find the property '" + propertyName + - "' on bean [" + getBean() + "] "); - return false; - } - } - - /** - * Test if a given bean is attached to a validator. - * - * @param compiler current compiler to use - * @param beanId the bean to test - * @return <code>true</code> if the given bean is attached to a validator, - * <code>false</code> otherwise - */ - public static boolean isBeanUsedByValidator(JAXXCompiler compiler, - String beanId) { - List<CompiledBeanValidator> beanValidatorList = validators.get(compiler); - if (beanValidatorList != null) { - for (CompiledBeanValidator validator : beanValidatorList) { - if (beanId.equals(validator.getBean())) { - return true; - } - } - } - return false; - } - - /** - * @param compiler compiler to use - * @return <code>true</code> if some validators were detected, - * <code>false</code> otherwise - */ - public static boolean hasValidator(JAXXCompiler compiler) { - List<CompiledBeanValidator> beanValidatorList = - validators.get(compiler); - return beanValidatorList != null && !beanValidatorList.isEmpty(); - } - - /** - * Test if a given CompiledObject is attached to a validator. - * - * @param compiler compiler to use - * @param componentId the compiled object to test - * @return <code>true</code> if the given compiled object is attached to - * a validator, <code>false</code> otherwise - */ - public static boolean isComponentUsedByValidator(JAXXCompiler compiler, - String componentId) { - List<String> ids = validatedComponents.get(compiler); - return ids != null && ids.contains(componentId); - } - - public static List<CompiledBeanValidator> getValidators(JAXXCompiler compiler) { - return validators.get(compiler); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/ExcludeFieldValidatorHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/ExcludeFieldValidatorHandler.java deleted file mode 100644 index 83117e2..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/ExcludeFieldValidatorHandler.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.validator; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.TagHandler; -import jaxx.compiler.tags.validator.BeanValidatorHandler.CompiledBeanValidator; -import jaxx.runtime.validator.swing.SwingValidator; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Element; - -import java.io.IOException; - -public class ExcludeFieldValidatorHandler implements TagHandler { - - public static final String TAG = "excludeField"; - - public static final String NAME_ATTRIBUTE = "name"; - - public static final String COMPONENT_ATTRIBUTE = "component"; - - /** Logger */ - static private Log log = LogFactory.getLog(ExcludeFieldValidatorHandler.class); - - @Override - public void compileFirstPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - if (compiler.getConfiguration().isVerbose()) { - log.info(tag); - } - //todo check there is no child - } - - @Override - public void compileSecondPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - if (compiler.getConfiguration().isVerbose()) { - log.debug(tag); - } - - ClassDescriptor descriptor = - ClassDescriptorHelper.getClassDescriptor(SwingValidator.class); - if (!descriptor.isAssignableFrom( - compiler.getOpenComponent().getObjectClass())) { - compiler.reportError(TAG + " tag may only appear within " + - BeanValidatorHandler.TAG + " tag but was " + - tag); - return; - } - - CompiledBeanValidator info = - (CompiledBeanValidator) compiler.getOpenComponent(); - if (!info.getAutoField()) { - compiler.reportError(TAG + " tag can not be used without an " + - "'autoField' validator : " + tag); - return; - } - String name = tag.getAttribute(NAME_ATTRIBUTE); - String component = tag.getAttribute(COMPONENT_ATTRIBUTE); - if (name == null || name.trim().isEmpty()) { - compiler.reportError(TAG + " tag requires a " + NAME_ATTRIBUTE + - " attribute"); - return; - } - name = name.trim(); - if (component == null || component.trim().isEmpty()) { - // try to use the name as component - if (!compiler.checkReference(tag, name, false, name)) { - compiler.reportError(TAG + " tag requires a " + - COMPONENT_ATTRIBUTE + " attribute, try " + - "to use the name attribute [" + name + - "] for the component, but no such " + - "component found"); - return; - } - component = name; - } - component = component.trim(); - - // check component is not already used by this compiled object -// if (info.getFields().containsValue(component)) { - if (info.containsFieldEditor(component)) { - compiler.reportError(TAG + " tag found a attribute " + - COMPONENT_ATTRIBUTE + " [" + component + - "] already used in this validator"); - return; - } -// if (info.getExcludeFields().containsValue(component)) { - if (info.containsExcludeFieldEditor(component)) { - compiler.reportError(TAG + " tag found a attribute " + - COMPONENT_ATTRIBUTE + " [" + component + - "] already used in this validator"); - return; - } - // check component exist (again perharps, but let the error knows exactly which tag failed...) - if (compiler.checkReference(tag, component, true, COMPONENT_ATTRIBUTE)) { - // add a field - info.registerField(name, component, compiler); - } - - - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/FieldValidatorHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/FieldValidatorHandler.java deleted file mode 100644 index f639841..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/FieldValidatorHandler.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags.validator; - -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.binding.DataBindingHelper; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tags.TagHandler; -import jaxx.compiler.tags.validator.BeanValidatorHandler.CompiledBeanValidator; -import jaxx.runtime.validator.swing.SwingValidator; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Element; - -import java.io.IOException; - -public class FieldValidatorHandler implements TagHandler { - - public static final String TAG = "field"; - - public static final String NAME_ATTRIBUTE = "name"; - - public static final String COMPONENT_ATTRIBUTE = "component"; - - /** Logger */ - static private Log log = LogFactory.getLog(FieldValidatorHandler.class); - - public void compileFirstPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - if (compiler.getConfiguration().isVerbose()) { - log.debug(tag); - } - //todo check there is no child - } - - @Override - public void compileSecondPass(Element tag, - JAXXCompiler compiler) throws CompilerException, IOException { - if (compiler.getConfiguration().isVerbose()) { - log.debug(tag); - } - - ClassDescriptor descriptor = - ClassDescriptorHelper.getClassDescriptor(SwingValidator.class); - if (!descriptor.isAssignableFrom( - compiler.getOpenComponent().getObjectClass())) { - compiler.reportError( - TAG + " tag may only appear within " + - BeanValidatorHandler.TAG + " tag but was " + tag); - return; - } - - CompiledBeanValidator info = - (CompiledBeanValidator) compiler.getOpenComponent(); - - String name = tag.getAttribute(NAME_ATTRIBUTE); - if (StringUtils.isEmpty(name)) { - compiler.reportError(TAG + " tag requires a " + NAME_ATTRIBUTE + - " attribute"); - return; - } - name = name.trim(); - - String component = tag.getAttribute(COMPONENT_ATTRIBUTE); - if (StringUtils.isEmpty(component)) { - // try to use the name as component - if (!compiler.checkReference(tag, name, false, name)) { - compiler.reportError( - TAG + " tag requires a " + COMPONENT_ATTRIBUTE + - " attribute, try to use the name attribute [" + name + - "] for the component, but no such component found"); - return; - } - component = name; - } - component = component.trim(); - - boolean complexType = false; - if (component.startsWith("{") && component.endsWith("}")) { - - complexType = true; - - // means a complex reference (says a java Code in facts) - component = compiler.preprocessScript( - component.substring(1, component.length() - 1)); - } - - if (log.isDebugEnabled()) { - log.debug("Check '" + component + "' reference"); - } - - // check component is not already used by this compiled object -// if (info.getFields().containsValue(component)) { -// if (info.containsFieldEditor(component)) { -// compiler.reportError( -// TAG + " tag found a attribute " + COMPONENT_ATTRIBUTE + -// " [" + component + "] already used in this validator"); -// return; -// } - - if (complexType) { - String binding = DataBindingHelper.processDataBindings(component); - boolean withBinding = binding != null; - - if (log.isDebugEnabled()) { - log.debug("apply data binding on [" + component + "] : " + withBinding); - } - - // this means reference is ok, can safely add field - - // add a field - info.registerField(name, component, compiler); - return; - } - - // simple reference, check it directly on compiler - - // check component exist (again perharps, but let the error knows - // exactly which tag failed...) - if (compiler.checkReference(tag, - component, - true, - COMPONENT_ATTRIBUTE)) { - // add a field - info.registerField(name, component, compiler); - } - - - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileFirstPassTask.java b/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileFirstPassTask.java deleted file mode 100644 index a16a91b..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileFirstPassTask.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.tasks; - -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXCompilerFile; -import jaxx.compiler.JAXXEngine; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.File; - -/** - * First compile pass task to validate jaxx files and look after dependencies. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class CompileFirstPassTask extends JAXXEngineTask { - - /** Logger */ - private static final Log log = LogFactory.getLog(CompileFirstPassTask.class); - - /** Task name */ - public static final String TASK_NAME = "CompileFirstPass"; - - public CompileFirstPassTask() { - super(TASK_NAME); - } - - @Override - public boolean perform(JAXXEngine engine) throws Exception { - boolean success = true; - - JAXXCompilerFile[] undone = engine.getFilesToCompile(); - - while (undone.length > 0) { - - // start a new round of compilation - - for (JAXXCompilerFile jaxxFile : undone) { - - boolean successForFile = treatFile(engine, jaxxFile); - - if (!successForFile) { - - // something is wrong... - success = false; - } - } - - // prepare next round - undone = engine.getFilesToCompile(); - } - return success; - } - - protected boolean treatFile(JAXXEngine engine, - JAXXCompilerFile jaxxFile) throws Exception { - - boolean isVerbose = engine.isVerbose(); - - if (isVerbose) { - log.info("start " + jaxxFile.getClassName()); - } - - boolean success = true; - - JAXXCompiler compiler = engine.newCompiler(jaxxFile); - addStartProfileTime(engine, compiler); - - compiler.compileFirstPass(); - - if (!compiler.isIdentCssFound()) { - - // check if we can add ident css file - - File cssFile = jaxxFile.getCssFile(); - - if (log.isDebugEnabled()) { - log.debug("test ident css file " + cssFile + " : " + isVerbose); - } - if (cssFile.exists()) { - - if (isVerbose) { - log.info("Auto import of css " + cssFile); - } - // ok add it - compiler.registerStyleSheetFile(cssFile, false); - } - } - - File commonCss = engine.getConfiguration().getCommonCss(); - if (commonCss != null) { - if (isVerbose) { - log.info("Import global css: " + commonCss); - } - compiler.registerStyleSheetFile(commonCss, false); - } - - addEndProfileTime(engine, compiler); - - if (compiler.isFailed()) { - success = false; - } - return success; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileSecondPassTask.java b/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileSecondPassTask.java deleted file mode 100644 index 5730d3d..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileSecondPassTask.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.tasks; - -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXCompilerFile; -import jaxx.compiler.JAXXEngine; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Task to execute the Second round of compile. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class CompileSecondPassTask extends JAXXEngineTask { - - /** Logger */ - private static final Log log = - LogFactory.getLog(CompileSecondPassTask.class); - - /** Task name */ - public static final String TASK_NAME = "CompileSecondPass"; - - public CompileSecondPassTask() { - super(TASK_NAME); - } - - @Override - public boolean perform(JAXXEngine engine) throws Exception { - boolean success = true; - boolean isVerbose = engine.isVerbose(); - - // check all files are attached to a compiler - checkAllFilesCompiled(engine); - - JAXXCompilerFile[] files = engine.getCompiledFiles(); - - for (JAXXCompilerFile jaxxFile : files) { - - String className = jaxxFile.getClassName(); - if (isVerbose) { - log.info("start " + className); - } - - JAXXCompiler compiler = jaxxFile.getCompiler(); - - addStartProfileTime(engine, compiler); - if (log.isDebugEnabled()) { - log.debug("runInitializers for " + className); - } - if (!compiler.isFailed()) { - compiler.runInitializers(); - } - if (log.isDebugEnabled()) { - log.debug("compile second pass for " + className); - } - compiler.compileSecondPass(); - addEndProfileTime(engine, compiler); - if (log.isDebugEnabled()) { - log.debug("done with result [" + !compiler.isFailed() + - "] for " + className); - } - if (compiler.isFailed()) { - success = false; - } - } - - return success; - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/FinalizeTask.java b/jaxx-compiler/src/main/java/jaxx/compiler/tasks/FinalizeTask.java deleted file mode 100644 index a36fe42..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/FinalizeTask.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.tasks; - -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXCompilerFile; -import jaxx.compiler.JAXXEngine; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Task to execute after stylesheet tasks and juste before generation task. - * - * This task will finialize all compilers. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class FinalizeTask extends JAXXEngineTask { - - /** Logger */ - private static final Log log = LogFactory.getLog(FinalizeTask.class); - - /** Task name */ - public static final String TASK_NAME = "Finalize"; - - public FinalizeTask() { - super(TASK_NAME); - } - - @Override - public boolean perform(JAXXEngine engine) throws Exception { - boolean success = true; - boolean isVerbose = engine.getConfiguration().isVerbose(); - - // check all files are attached to a compiler - checkAllFilesCompiled(engine); - - JAXXCompilerFile[] files = engine.getCompiledFiles(); - - for (JAXXCompilerFile jaxxFile : files) { - - if (isVerbose) { - log.info("start " + jaxxFile.getClassName()); - } - JAXXCompiler compiler = jaxxFile.getCompiler(); - addStartProfileTime(engine, compiler); - compiler.finalizeCompiler(); - addEndProfileTime(engine, compiler); - if (compiler.isFailed()) { - success = false; - } - } - return success; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateConstructorsTask.java b/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateConstructorsTask.java deleted file mode 100644 index 56fbdd5..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateConstructorsTask.java +++ /dev/null @@ -1,508 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.tasks; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXCompilerFile; -import jaxx.compiler.JAXXEngine; -import jaxx.compiler.finalizers.DefaultFinalizer; -import jaxx.compiler.java.JavaArgument; -import jaxx.compiler.java.JavaConstructor; -import jaxx.compiler.java.JavaElementFactory; -import jaxx.compiler.java.JavaFile; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.reflect.MethodDescriptor; -import jaxx.compiler.tags.TagManager; -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import static java.lang.reflect.Modifier.PUBLIC; - -/** - * Task to execute just after finalize task to create all constructors for any - * compiler. - * - * In fact, we can not compute constructor in one time since some compiler may - * need of the constructors of previous compiler... - * - * This task will compute all constructors to generate. - * - * @author Tony Chemit - chemit@codelutin.com - * @see JavaConstructor - * @since 2.4 - */ -public class GenerateConstructorsTask extends JAXXEngineTask { - - /** Logger */ - private static final Log log = LogFactory.getLog(GenerateConstructorsTask.class); - - /** Task name */ - public static final String TASK_NAME = "PostFinalize"; - - private static final String PARAMETER_NAME_PARENT_CONTEXT = "parentContext"; - - public GenerateConstructorsTask() { - super(TASK_NAME); - } - - @Override - public boolean perform(JAXXEngine engine) throws Exception { - boolean success = true; - boolean isVerbose = engine.getConfiguration().isVerbose(); - - JAXXCompilerFile[] files = engine.getCompiledFiles(); - - // to contains all compilers - List<JAXXCompiler> compilers = new ArrayList<>(); - for (JAXXCompilerFile jaxxFile : files) { - compilers.add(jaxxFile.getCompiler()); - } - - int round = 0; - - while (!compilers.isEmpty()) { - - if (isVerbose) { - log.info("Round " + round++ + ", still " + - compilers.size() + " compilers to treat."); - } - - // launch a round since there is still some compiler to treat - Iterator<JAXXCompiler> itr = compilers.iterator(); - while (itr.hasNext()) { - JAXXCompiler compiler = itr.next(); - JavaFile javaFile = compiler.getJavaFile(); - - boolean isJAXXObject = javaFile.isSuperclassIsJAXXObject(); - if (!isJAXXObject) { - - // can directly compute constructors - - if (log.isDebugEnabled()) { - log.debug("Compute constructor from non super " + - "jaxx object file " + javaFile.getName()); - } - - // get the constructors of the parent class - - addConstructorsForNoneSuperClassJaxx(engine, compiler); - itr.remove(); - continue; - } - - // compiler inheritate from a jaxx object - CompiledObject rootObject = compiler.getRootObject(); - ClassDescriptor parentClassDescriptor = rootObject.getObjectClass(); - - if (parentClassDescriptor.getResolverType() - != ClassDescriptorHelper.ResolverType.JAXX_FILE) { - - // the parent was not generated by this engine; we can safely - // use it - - if (log.isDebugEnabled()) { - log.debug("Compute constructor from outside super " + - "jaxx object file " + javaFile.getName()); - } - addConstructorsForSuperClassJaxx(engine, compiler, null); - itr.remove(); - continue; - - } - - JAXXCompiler parentCompiler = engine.getJAXXCompiler( - JAXXCompiler.getCanonicalName(parentClassDescriptor)); - - - if (!compilers.contains(parentCompiler)) { - - // parent was generated by this engine and was laready - // treated, can now safely deal this the given compiler - - if (log.isDebugEnabled()) { - log.debug("Compute constructor from inside super " + - "jaxx object file " + javaFile.getName()); - } - - addConstructorsForSuperClassJaxx(engine, compiler, parentCompiler); - itr.remove(); - continue; - } - - // can not treate at the moment... - if (log.isDebugEnabled()) { - log.debug("Can not compute constructors for " + - compiler.getRootObject().getId() + - " waits fro his parent to be treated..."); - } - } - } - return success; - } - - /** - * To add constructor on the given {@code compiler}, knowing that the super - * class of it is not a jaxx class. - * - * In this mode, we takes all the constructors of the parent (if parent has - * some!) and for each of them add the simple one and another one with - * first parameter a {@link JAXXContext}. - * - * @param engine the current engine which compiled compiler - * @param compiler the current compiler to treat - * @throws ClassNotFoundException if a class could not be found (when wanted to have extact type for constructor parameters) - * @throws IllegalStateException if given {@code compiler has a super JAXX class}. - */ - protected void addConstructorsForNoneSuperClassJaxx(JAXXEngine engine, - JAXXCompiler compiler) throws ClassNotFoundException, IllegalStateException { - - JavaFile javaFile = compiler.getJavaFile(); - - if (javaFile.isSuperclassIsJAXXObject()) { - throw new IllegalStateException( - "This method does not accept compiler that " + - "inheritates from a jaxx file."); - } - - String className = javaFile.getSimpleName(); - - if (engine.isVerbose()) { - log.info("start " + javaFile.getName()); - } - - addStartProfileTime(engine, compiler); - - // get already registred constructors : need to keep the list of parameters - // not to generate a constructor with same prototype twice. - List<List<String>> prototypes = getDeclaredConstructorPrototypes(compiler, javaFile); - - MethodDescriptor[] constructorDescriptors = - compiler.getRootObject().getObjectClass().getConstructorDescriptors(); - - List<String> constructorTypes; - boolean canAddConstructor; - - if (constructorDescriptors == null || constructorDescriptors.length == 0) { - - // no constructors (use only a default constructor) - - constructorTypes = getConstructorTypes(); - canAddConstructor = canAddConstructor(prototypes, constructorTypes); - if (canAddConstructor) { - addConstructor(compiler, className, constructorTypes); - } - - constructorTypes.add(0, JAXXCompiler.getCanonicalName(JAXXContext.class)); - canAddConstructor = canAddConstructor(prototypes, constructorTypes); - if (canAddConstructor) { - addConstructorWithInitialContext(compiler, className, constructorTypes, false); - } - } else { - for (MethodDescriptor constructorDescriptor : constructorDescriptors) { - - constructorTypes = getConstructorTypes(constructorDescriptor.getParameterTypes()); - canAddConstructor = canAddConstructor(prototypes, constructorTypes); - if (canAddConstructor) { - addConstructor(compiler, className, constructorTypes); - } - - constructorTypes.add(0, JAXXCompiler.getCanonicalName(JAXXContext.class)); - canAddConstructor = canAddConstructor(prototypes, constructorTypes); - if (canAddConstructor) { - addConstructorWithInitialContext(compiler, className, constructorTypes, false); - } - } - } - - addEndProfileTime(engine, compiler); - } - - /** - * To add constructor on the given {@code compiler}, knowing that the super - * class of it is a jaxx class. - * - * In this mode, we takes all the constructors of the parent (if parent has - * some!) and for each of them add the simple one and another one with - * first parameter a {@link JAXXContext}. - * - * @param engine the current engine which compiled compiler - * @param compiler the current compiler to treat - * @param parentCompiler the compiler of the super class (can be - * {@code null} if super class was not generated by - * the given engine). - * @throws ClassNotFoundException if a class could not be found (when wanted to have extact type for constructor parameters) - * @throws IllegalStateException if given {@code compiler has not a super JAXX class}. - */ - protected void addConstructorsForSuperClassJaxx(JAXXEngine engine, - JAXXCompiler compiler, - JAXXCompiler parentCompiler) throws ClassNotFoundException, IllegalStateException { - - JavaFile javaFile = compiler.getJavaFile(); - - if (!javaFile.isSuperclassIsJAXXObject()) { - throw new IllegalStateException( - "This method does not accept compiler that " + - "inheritates not from a jaxx file."); - } - - String className = javaFile.getSimpleName(); - - if (engine.isVerbose()) { - log.info("start " + javaFile.getName()); - } - - addStartProfileTime(engine, compiler); - - // get already registred constructors : need to keep the list of parameters - // not to generate a constructor with same prototype twice. - List<List<String>> prototypes = getDeclaredConstructorPrototypes(compiler, javaFile); - - MethodDescriptor[] constructorDescriptors; - - if (parentCompiler == null) { - - // the parent was not generated by this engine, this means that is - // class descriptor can be used to obtain constructors - constructorDescriptors = compiler.getRootObject().getObjectClass().getConstructorDescriptors(); - } else { - - // the parent was generated by this engine, can not trust the class - // descriptor at the moment, so just seek in his java file for - // already generated constructor - List<JavaConstructor> constructors = parentCompiler.getJavaFile().getConstructors(); - constructorDescriptors = new MethodDescriptor[constructors.size()]; - - int i = 0; - for (JavaConstructor constructor : constructors) { - String[] parameters = new String[constructor.getArguments().length]; - int j = 0; - for (JavaArgument argument : constructor.getArguments()) { - String type = argument.getType(); - parameters[j++] = type; - } - constructorDescriptors[i++] = new MethodDescriptor( - null, - constructor.getModifiers(), - null, - parameters, - compiler.getClassLoader() - ); - } - } - - // dealing with a jsuper class JAXX we are sure to have at least two constructors : - // a default one + one with just a JAXXContext parameter - - List<String> constructorTypes; - boolean canAddConstructor; - - for (MethodDescriptor constructorDescriptor : constructorDescriptors) { - - ClassDescriptor[] parameterTypes = constructorDescriptor.getParameterTypes(); - - if (parentCompiler == null) { - - // we already have the good type ??? this is dangerous - // because we could miss an import ? must be improved - constructorTypes = new ArrayList<>(parameterTypes.length); - - for (ClassDescriptor parameterType : parameterTypes) { - constructorTypes.add(parameterType.getName()); - } - } else { - - - constructorTypes = getConstructorTypes(parameterTypes); - } - canAddConstructor = canAddConstructor(prototypes, constructorTypes); - if (canAddConstructor) { - addConstructor(compiler, className, constructorTypes); - } - -// constructorTypes.add(0, JAXXCompiler.getCanonicalName(JAXXContext.class)); -// canAddConstructor = canAddConstructor(prototypes, constructorTypes); -// if (canAddConstructor) { -// addConstructorWithInitialContext(compiler, className, constructorTypes, true); -// } - } - - - addEndProfileTime(engine, compiler); - } - - protected List<List<String>> getDeclaredConstructorPrototypes(JAXXCompiler compiler, - JavaFile javaFile) throws ClassNotFoundException { - List<JavaConstructor> constructors = javaFile.getConstructors(); - List<List<String>> prototypes = new ArrayList<>(constructors.size()); - for (JavaConstructor constructor : constructors) { - List<String> prototype = new ArrayList<>(); - for (JavaArgument argument : constructor.getArguments()) { - String type = argument.getType(); - String fqn = TagManager.resolveClassName(type, compiler); - ClassDescriptor classDescriptor = ClassDescriptorHelper.getClassDescriptor(fqn); - String canonicalName = JAXXCompiler.getCanonicalName(classDescriptor); - prototype.add(canonicalName); - } - prototypes.add(prototype); - } - return prototypes; - } - - private boolean canAddConstructor(List<List<String>> prototypes, List<String> constructorTypes) { - return !prototypes.contains(constructorTypes); - } - - private List<String> getConstructorTypes(ClassDescriptor... descriptors) { - List<String> result = new ArrayList<>(); - // add all parameters from constructor - for (ClassDescriptor descriptor : descriptors) { - String fqn = JAXXCompiler.getCanonicalName(descriptor); - result.add(fqn); - } - return result; - } - - protected void addConstructor(JAXXCompiler compiler, - String className, - List<String> constructorTypes) throws CompilerException { - StringBuilder code = new StringBuilder(); - String eol = JAXXCompiler.getLineSeparator(); - - JavaArgument[] arguments = new JavaArgument[constructorTypes.size()]; - - if (!constructorTypes.isEmpty()) { - - // constructeur avec des paramètres - code.append(" super("); - int i = 0; - for (String constructorType : constructorTypes) { - JavaArgument argument = JavaElementFactory.newArgument( - constructorType, - "param" + i - ); - arguments[i] = argument; - if (i > 0) { - code.append(" ,"); - } - code.append(argument.getName()); - i++; - } - - code.append(");").append(eol); - } - code.append(DefaultFinalizer.METHOD_NAME_$INITIALIZE + "();"); - code.append(eol); - JavaConstructor constructor = JavaElementFactory.newConstructor(PUBLIC, - className, - code.toString(), - arguments - ); - compiler.getJavaFile().addConstructor(constructor); - } - - protected void addConstructorWithInitialContext(JAXXCompiler compiler, - String className, - List<String> constructorTypes, - boolean superclassIsJAXXObject) throws CompilerException { - StringBuilder code = new StringBuilder(); - String eol = JAXXCompiler.getLineSeparator(); - - JavaArgument firstArgument = JavaElementFactory.newArgument( - JAXXContext.class.getName(), - PARAMETER_NAME_PARENT_CONTEXT - ); - JavaArgument[] arguments = new JavaArgument[constructorTypes.size()]; - arguments[0] = firstArgument; - for (int i = 1, max = constructorTypes.size(); i < max; i++) { - String constructorType = constructorTypes.get(i); - JavaArgument argument = JavaElementFactory.newArgument( - constructorType, - "param" + i - ); - arguments[i] = argument; - } - if (superclassIsJAXXObject) { - - // we are sure to have at least the first parameter in the super code - code.append(" super("); - code.append(PARAMETER_NAME_PARENT_CONTEXT); - for (int i = 1, max = constructorTypes.size(); i < max; i++) { - String constructorType = constructorTypes.get(i); - JavaArgument argument = JavaElementFactory.newArgument( - constructorType, - "param" + i - ); - arguments[i] = argument; - code.append(" ,"); - code.append(argument.getName()); - } - code.append(");").append(eol); - } else { - - // only a super class only if more than the parentContext parameter - if (constructorTypes.size() > 1) { - - code.append(" super("); - - for (int i = 1, max = constructorTypes.size(); i < max; i++) { - String constructorType = constructorTypes.get(i); - JavaArgument argument = JavaElementFactory.newArgument( - constructorType, - "param" + i - ); - arguments[i] = argument; - if (i > 1) { - code.append(" ,"); - } - code.append(argument.getName()); - } - code.append(");").append(eol); - } - } - - if (!superclassIsJAXXObject) { - - // call explicitly the init code of the parentContext - String prefix = compiler.getImportedType(JAXXUtil.class); - code.append(prefix); - code.append(".initContext(this, " + PARAMETER_NAME_PARENT_CONTEXT + ");"); - code.append(eol); - } - code.append(DefaultFinalizer.METHOD_NAME_$INITIALIZE + "();"); - code.append(eol); - JavaConstructor constructor = JavaElementFactory.newConstructor(PUBLIC, - className, - code.toString(), - arguments - ); - compiler.getJavaFile().addConstructor(constructor); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateMissingRulesTask.java b/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateMissingRulesTask.java deleted file mode 100644 index dd28682..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateMissingRulesTask.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.tasks; - -import jaxx.compiler.CompiledObject; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXCompilerFile; -import jaxx.compiler.JAXXEngine; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.File; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Last task to generate java files. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class GenerateMissingRulesTask extends JAXXEngineTask { - - /** Logger */ - private static final Log log = LogFactory.getLog(GenerateMissingRulesTask.class); - - /** Task name */ - public static final String TASK_NAME = "GenerateMissingRules"; - - public GenerateMissingRulesTask() { - super(TASK_NAME); - } - - @Override - public boolean perform(JAXXEngine engine) throws Exception { - boolean success = true; - boolean isVerbose = engine.getConfiguration().isVerbose(); - - JAXXCompilerFile[] files = engine.getCompiledFiles(); - - for (JAXXCompilerFile jaxxFile : files) { - String className = jaxxFile.getClassName(); - if (isVerbose) { - log.info("start " + className); - } - - JAXXCompiler compiler = jaxxFile.getCompiler(); - addStartProfileTime(engine, compiler); - - if (compiler.isIdentCssFound()) { - - File cssFile = jaxxFile.getCssFile(); - - String cssContent = FileUtils.readFileToString(cssFile); - - Map<String, CompiledObject> objects = compiler.getObjects(); - - Set<String> cssRulesToAdd = new LinkedHashSet<>(); - - for (String id : objects.keySet()) { - - CompiledObject object = objects.get(id); - String styleClass = object.getStyleClass(); - - if (isVerbose) { - log.info("id : " + id + ", styleClass : " + styleClass); - } - - if (!id.startsWith("$")) { - Pattern idPattern = Pattern.compile("#" + id + "\\s*\\{.*\\}", Pattern.DOTALL); - Matcher idMatcher = idPattern.matcher(cssContent); - - if (!idMatcher.find()) { - if (log.isInfoEnabled()) { - log.info("add css rule for #" + id + " in " + cssFile.getName()); - } - cssRulesToAdd.add( "\n\n/* #" + id + " {} */"); - } - } - - if (styleClass != null) { - Pattern classPattern = Pattern.compile("\\." + styleClass + "\\s*\\{.*\\}", Pattern.DOTALL); - Matcher classMatcher = classPattern.matcher(cssContent); - - if (!classMatcher.find()) { - if (log.isInfoEnabled()) { - log.info("add css rule for ." + styleClass + " in " + cssFile.getName()); - } - cssRulesToAdd.add( "\n\n/* ." + styleClass + " {} */"); - } - } - - } - - FileUtils.write(cssFile, StringUtils.join(cssRulesToAdd, ""), true); - } - - addEndProfileTime(engine, compiler); - - if (compiler.isFailed()) { - success = false; - } - } - return success; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateTask.java b/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateTask.java deleted file mode 100644 index a9d7d6f..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateTask.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.tasks; - -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXCompilerFile; -import jaxx.compiler.JAXXEngine; -import jaxx.compiler.java.JavaArgument; -import jaxx.compiler.java.JavaConstructor; -import jaxx.compiler.java.JavaFile; -import jaxx.compiler.java.JavaFileGenerator; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.eugene.java.extension.ImportsManager; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * Last task to generate java files. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class GenerateTask extends JAXXEngineTask { - - /** Logger */ - private static final Log log = LogFactory.getLog(GenerateTask.class); - - /** Task name */ - public static final String TASK_NAME = "Generate"; - - public GenerateTask() { - super(TASK_NAME); - } - - @Override - public boolean perform(JAXXEngine engine) throws Exception { - - // check all files are attached to a compiler - checkAllFilesCompiled(engine); - - boolean success = true; - - boolean verbose = engine.isVerbose(); - - JavaFileGenerator generator = - new JavaFileGenerator(JAXXCompiler.getLineSeparator(), verbose); - - JAXXCompilerFile[] files = engine.getCompiledFiles(); - - for (JAXXCompilerFile jaxxFile : files) { - if (verbose) { - log.info("start " + jaxxFile.getClassName()); - } - - JAXXCompiler compiler = jaxxFile.getCompiler(); - - addStartProfileTime(engine, compiler); - - try { - consumeCompiler(compiler, generator); - } finally { - compiler.getJavaFile().clear(); - } - addEndProfileTime(engine, compiler); - if (compiler.isFailed()) { - success = false; - } - } - return success; - } - - public void consumeCompiler(JAXXCompiler compiler, - JavaFileGenerator generator) throws IOException { - - JavaFile javaFile = compiler.getJavaFile(); - - String packageName = javaFile.getPackageName(); - - // optimize imports - List<String> imports = optimizeImports(javaFile, packageName); - - String packageToExclude = packageName + ".*"; - - // push back previous imports - for (String importFQN : javaFile.getImports()) { - if (!packageToExclude.equals(importFQN) && - !imports.contains(importFQN)) { - imports.add(importFQN); - } - } - - // set them to the file to generate - javaFile.setImports(imports); - - - // generate java file - compiler.generate(generator); - } - - public List<String> optimizeImports(JavaFile f, - String packageName) { - - ImportsManager importsManager = f.getImportManager(); - - List<String> result; - - for (String importFQN : f.getImports()) { - if (log.isDebugEnabled()) { - log.debug("Add import : " + importFQN); - } - importsManager.addImport(importFQN); - } - - if (f.getSuperClass() != null) { - String superClass = f.getSuperClass(); - try { - String type = importsManager.getType(superClass); - f.setSuperClass(type); - } catch (Exception e) { - log.error("file [" + f.getName() + - "] Could not determine simple name of super class " + - superClass); - } - } - - List<String> interfaces = f.getInterfaces(); - List<String> interfaces2 = new ArrayList<>(interfaces.size()); - for (String anInterface : interfaces) { - try { - String newInterface = importsManager.getType(anInterface); - interfaces2.add(newInterface); - } catch (Exception e) { - log.error("file [" + f.getName() + - "] Could not get interface " + anInterface + " :: " + - e.getMessage()); - interfaces2.add(anInterface); - } - } - f.setInterfaces(interfaces2); - - // optimize constructors parameters - optimizeConstructorParameters(f, importsManager); -// importsManager.addImport(JAXXUtil.class); -// if (!f.isSuperclassIsJAXXObject() || needSwingUtil) { -// -// // while implementing JAXXObject contract we sure need the -// // SwingUtil class -// importsManager.addImport(SwingUtil.class); -// } - result = importsManager.getImports(packageName); - result.remove(packageName + ".*"); - if (log.isDebugEnabled()) { - log.debug("[" + f.getName() + "] Detect " + result.size() + - " imports to add."); - for (String s : result) { - log.debug(" " + s); - } - } - - return result; - } - - protected void optimizeConstructorParameters(JavaFile f, - ImportsManager importsManager) { - - List<JavaConstructor> constructors = f.getConstructors(); - for (JavaConstructor constructor : constructors) { - JavaArgument[] arguments = constructor.getArguments(); - for (JavaArgument argument : arguments) { - String type = argument.getType(); - try { - String simpleType = importsManager.getType(type); - argument.setType(simpleType); - } catch (Exception e) { - log.error("file [" + f.getName() + - "] Could not get simple type of constructor paramter " + type + " :: " + - e.getMessage()); - } - - } - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/InitTask.java b/jaxx-compiler/src/main/java/jaxx/compiler/tasks/InitTask.java deleted file mode 100644 index 4970b3b..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/InitTask.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.tasks; - -import jaxx.compiler.CompilerConfiguration; -import jaxx.compiler.JAXXEngine; -import jaxx.compiler.JAXXFactory; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * The init task to be launched first. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class InitTask extends JAXXEngineTask { - - /** Logger */ - private static final Log log = LogFactory.getLog(InitTask.class); - - /** Task name */ - public static final String TASK_NAME = "Init"; - - public InitTask() { - super(TASK_NAME); - } - - @Override - public boolean perform(JAXXEngine engine) throws Exception { - boolean success = true; - - CompilerConfiguration configuration = engine.getConfiguration(); - - // check initializers - if (configuration.getInitializers() == null) { - throw new NullPointerException( - "no initializers found in configuration."); - } - - // check decorators - if (configuration.getDecorators() == null) { - - throw new NullPointerException( - "no decorators found in configuration."); - } - - // check finalizers - if (configuration.getFinalizers() == null) { - - throw new NullPointerException( - "no finalizers found in configuration."); - } - - if (configuration.isVerbose()) { - log.info("Will init " + JAXXFactory.class.getName()); - } - JAXXFactory.initFactory(); - - engine.clearReports(); - - return success; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/JAXXEngineTask.java b/jaxx-compiler/src/main/java/jaxx/compiler/tasks/JAXXEngineTask.java deleted file mode 100644 index a8a486a..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/JAXXEngineTask.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.tasks; - -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXCompilerFile; -import jaxx.compiler.JAXXEngine; - -/** - * Base class to implement a task to be launched by a {@link JAXXEngine}. - * - * The {@link #perform(JAXXEngine)} method contains the logic of the task. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public abstract class JAXXEngineTask { - - /** Task name */ - private final String name; - - public JAXXEngineTask(String name) { - this.name = name; - } - - /** - * Performs the task on the given {@code engine}. - * - * @param engine the engine to use - * @return {@code false} if task failed (with no exception), {@code true} otherwise. - * @throws Exception if any error - */ - public abstract boolean perform(JAXXEngine engine) throws Exception; - - public String getName() { - return name; - } - - /** - * Checks the engine does not have any more files to discover. - * - * @param engine the engine to test - * @throws IllegalStateException if there is still some files to discover. - */ - protected void checkAllFilesCompiled(JAXXEngine engine) throws IllegalStateException { - JAXXCompilerFile[] undone = engine.getFilesToCompile(); - - if (undone.length > 0) { - - throw new IllegalStateException("Can not start '" + getName() + "', there is still files to process in '" + CompileFirstPassTask.TASK_NAME); - } - } - - protected void addStartProfileTime(JAXXEngine engine, - JAXXCompiler compiler) { - engine.addProfileTime(compiler, name + "_start"); - } - - - protected void addEndProfileTime(JAXXEngine engine, - JAXXCompiler compiler) { - engine.addProfileTime(compiler, name + "_end"); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/ProfileTask.java b/jaxx-compiler/src/main/java/jaxx/compiler/tasks/ProfileTask.java deleted file mode 100644 index 112b4b5..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/ProfileTask.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.tasks; - -import jaxx.compiler.JAXXEngine; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * A task to display result of profile mode - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class ProfileTask extends JAXXEngineTask { - - /** Logger */ - private static final Log log = LogFactory.getLog(ProfileTask.class); - - /** Task name */ - public static final String TASK_NAME = "Profile"; - - public ProfileTask() { - super(TASK_NAME); - } - - @Override - public boolean perform(JAXXEngine engine) throws Exception { - boolean success = true; - StringBuilder buffer = engine.getProfiler().computeProfileReport(); - log.info(buffer.toString()); - return success; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/StyleSheetTask.java b/jaxx-compiler/src/main/java/jaxx/compiler/tasks/StyleSheetTask.java deleted file mode 100644 index b5e500f..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tasks/StyleSheetTask.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.tasks; - -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXCompilerFile; -import jaxx.compiler.JAXXEngine; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Task to apply css stylesheet on objects after second round of compilation. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class StyleSheetTask extends JAXXEngineTask { - - /** Logger */ - private static final Log log = LogFactory.getLog(StyleSheetTask.class); - - /** Task name */ - public static final String TASK_NAME = "StyleSheet"; - - public StyleSheetTask() { - super(TASK_NAME); - } - - @Override - public boolean perform(JAXXEngine engine) throws Exception { - - // check all files are attached to a compiler - checkAllFilesCompiled(engine); - - boolean success = true; - boolean isVerbose = engine.getConfiguration().isVerbose(); - - JAXXCompilerFile[] files = engine.getCompiledFiles(); - - for (JAXXCompilerFile jaxxFile : files) { - String className = jaxxFile.getClassName(); - if (isVerbose) { - log.info("start " + className); - } - - JAXXCompiler compiler = jaxxFile.getCompiler(); - addStartProfileTime(engine, compiler); - compiler.applyStylesheets(); - addEndProfileTime(engine, compiler); - - if (compiler.isFailed()) { - success = false; - } - } - return success; - } - -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tools/PrintTagInfo.java b/jaxx-compiler/src/main/java/jaxx/compiler/tools/PrintTagInfo.java deleted file mode 100644 index 48870bf..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tools/PrintTagInfo.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tools; - -import jaxx.compiler.DefaultCompilerConfiguration; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXFactory; -import jaxx.compiler.beans.JAXXPropertyDescriptor; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.reflect.MethodDescriptor; -import jaxx.compiler.tags.DefaultObjectHandler; -import jaxx.compiler.tags.TagManager; -import org.apache.commons.lang3.StringUtils; - -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.io.IOException; -import java.io.OutputStreamWriter; - -/** Generates information about a tag for use on the jaxxframework.org web site. */ -public class PrintTagInfo { - /** - * Displays information about the class name in arg[0]. - * - * @param arg command-line arguments - * @throws Exception if an error occurs - */ - public static void main(String[] arg) throws Exception { - if (arg.length < 1) { - throw new IllegalArgumentException("programm needs at least two parameters : the file where to put the result, and at least one fqn class to treate"); - } - String firstarg = arg[0]; - boolean toFile = false; - BufferedWriter w; - if (firstarg.startsWith("file:")) { - w = new BufferedWriter(new FileWriter(firstarg.substring(5))); - toFile = true; - } else { - w = new BufferedWriter(new OutputStreamWriter(System.out)); - } - - try { - JAXXFactory.setConfiguration(new DefaultCompilerConfiguration()); - JAXXFactory.initFactory(); - for (int i = toFile ? 1 : 0; i < arg.length; i++) { - String className = arg[i]; - treateClass(w, className); - } - } finally { - w.flush(); - w.close(); - } - - } - - protected static void treateClass(BufferedWriter w, String className) throws ClassNotFoundException, IOException { - - ClassDescriptor beanClass = ClassDescriptorHelper.getClassDescriptor(className); - DefaultObjectHandler handler = TagManager.getTagHandler(beanClass); - - DefaultObjectHandler superHandler = TagManager.getTagHandler(beanClass.getSuperclass()); - - // dump all bean properties - w.append("Properties in ").append(String.valueOf(beanClass)); - w.newLine(); - JAXXPropertyDescriptor[] properties = handler.getJAXXBeanInfo().getJAXXPropertyDescriptors(); - JAXXPropertyDescriptor[] superProperties = superHandler.getJAXXBeanInfo().getJAXXPropertyDescriptors(); - for (JAXXPropertyDescriptor property : properties) { - if (property.getWriteMethodDescriptor() == null) { - continue; - } - - boolean found = false; - String name = property.getName(); - for (JAXXPropertyDescriptor superProperty : superProperties) { - if (superProperty.getName().equals(name)) { - found = true; - break; - } - } - if (!found) { - if (property.getPropertyType() == null) { - System.err.println(name + " has null type"); - } else { - w.append("{{EquivalentAttribute|"); - w.append(name); - w.append("|"); - w.append(className.replace('.', '/')); - w.append("|set"); - w.append(StringUtils.capitalize(name)); - w.append("|"); - w.append(JAXXCompiler.getCanonicalName(property.getPropertyType())); - w.append("}}"); - w.append("|-"); - w.newLine(); - } - } - } - - w.newLine(); - w.newLine(); - - // dump all bound methods - dumpMethods(w, beanClass, handler); - } - - protected static void dumpMethods(BufferedWriter w, ClassDescriptor beanClass, DefaultObjectHandler handler) throws IOException { - MethodDescriptor[] methods = beanClass.getMethodDescriptors(); - w.append("Bound methods in ").append(String.valueOf(beanClass)); - w.newLine(); - for (MethodDescriptor method : methods) { - try { - if (handler.isMemberBound(method.getName())) { - w.append("* <tt>").append(method.getName()).append("()</tt>"); - w.newLine(); - } - } catch (Throwable e) { - // ignore ? - } - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/AbstractContextNode.java b/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/AbstractContextNode.java deleted file mode 100644 index feedd6c..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/AbstractContextNode.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tools.jaxxcapture; - -import java.util.ArrayList; -import java.util.List; - -public abstract class AbstractContextNode implements ContextNode { - private List<ContextNode> arguments = new ArrayList<>(); - - - @Override - public void addArgument(ContextNode node) { - arguments.add(node); - } - - @Override - public ContextNode[] getArguments() { - return arguments.toArray(new ContextNode[arguments.size()]); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/CapturedObject.java b/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/CapturedObject.java deleted file mode 100644 index cafb7a9..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/CapturedObject.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tools.jaxxcapture; - -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.tools.jaxxcapture.handlers.ObjectHandler; - -import java.awt.Component; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; - -public class CapturedObject extends AbstractContextNode { - private String className; - - private ObjectHandler handler; - - /** Maps children to their constraints. */ - private Map<CapturedObject, ContextNode> children = new LinkedHashMap<>(); - - private CapturedObject parent; - - private Map<String, String> properties = new LinkedHashMap<>(); - - private Map<String, Object> additionalData = new HashMap<>(); - - private StringBuilder innerXML = new StringBuilder(); - - private StringBuilder script = new StringBuilder(); - - private boolean inlineable = true; - - private JAXXCapture capture; - - public CapturedObject(ObjectHandler handler, String className, JAXXCapture capture) { - this.handler = handler; - this.className = className; - this.capture = capture; - } - - - public ObjectHandler getObjectHandler() { - return handler; - } - - - public void addChild(CapturedObject child, ContextNode constraints) { - children.put(child, constraints); - child.setParent(this); - } - - - public CapturedObject[] getChildren() { - return children.keySet().toArray(new CapturedObject[children.size()]); - } - - - public CapturedObject getParent() { - return parent; - } - - - public void setParent(CapturedObject parent) { - this.parent = parent; - } - - - public ContextNode getConstraints(CapturedObject child) { - return children.get(child); - } - - - public String getClassName() { - return className; - } - - - public String getProperty(String key) { - return properties.get(key); - } - - - public void setProperty(String key, String value) { - properties.put(key, value); - } - - - public Map<String, String> getProperties() { - return properties; - } - - - public Object getAdditionalData(String key) { - return additionalData.get(key); - } - - - public void setAdditionalData(String key, Object value) { - additionalData.put(key, value); - } - - - public Map<String, Object> getAdditionalData() { - return additionalData; - } - - - public void setInlineable(boolean inlineable) { - this.inlineable = inlineable; - } - - - public boolean isInlineable() { - try { - return script.length() == 0 && !Component.class.isAssignableFrom(Class.forName(className, true, capture.getClassLoader())) && inlineable; - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - - public void appendInnerXML(String xml) { - if (this.innerXML.length() > 0) { - this.innerXML.append(JAXXCompiler.getLineSeparator()); - } - this.innerXML.append(xml); - } - - - public String getInnerXML() { - return innerXML.toString(); - } - - - public void appendScriptCode(String script) { - if (this.script.length() > 0) { - this.script.append(JAXXCompiler.getLineSeparator()); - } - this.script.append(script); - } - - - public String getScriptCode() { - return script.toString(); - } - - - public String getXML(JAXXCapture capture) { - return getObjectHandler().getXML(this, capture); - } - - @Override - public String toString() { - return "CapturedObject[" + getProperty("id") + ", " + className + "]"; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/ContextNode.java b/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/ContextNode.java deleted file mode 100644 index cd2d039..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/ContextNode.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tools.jaxxcapture; - -public interface ContextNode { - - void addArgument(ContextNode node); - - ContextNode[] getArguments(); -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/JAXXCapture.java b/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/JAXXCapture.java deleted file mode 100644 index 4aeeb12..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/JAXXCapture.java +++ /dev/null @@ -1,405 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tools.jaxxcapture; - -import jaxx.compiler.ClassMap; -import jaxx.compiler.CompiledObject; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.tools.jaxxcapture.handlers.JTabbedPaneHandler; -import jaxx.compiler.tools.jaxxcapture.handlers.ObjectHandler; -import jaxx.compiler.tools.jaxxcapture.handlers.TableHandler; -import jaxx.compiler.types.TypeManager; -import org.apache.commons.lang3.StringUtils; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; -import org.xml.sax.SAXException; - -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JTabbedPane; -import javax.swing.JWindow; -import javax.swing.SwingUtilities; -import java.awt.AWTEvent; -import java.awt.Component; -import java.awt.Container; -import java.awt.EventQueue; -import java.awt.Toolkit; -import java.awt.Window; -import java.awt.event.MouseEvent; -import java.beans.XMLEncoder; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Stack; -import java.util.jar.Attributes; -import java.util.jar.JarFile; -import java.util.jar.Manifest; - -public class JAXXCapture { - - private static ClassMap<Object> objectHandlers = new ClassMap<>(); - - static { - //TODO make a serviceLoader mecanism to allow inter-module loading - objectHandlers.put(ClassDescriptorHelper.getClassDescriptor(Object.class), new ObjectHandler()); - objectHandlers.put(ClassDescriptorHelper.getClassDescriptor(JTabbedPane.class), new JTabbedPaneHandler()); - try { - objectHandlers.put(ClassDescriptorHelper.getClassDescriptor("jaxx.runtime.swing.Table"), new TableHandler()); - } catch (ClassNotFoundException e) { - System.err.println(e); - } - } - - private Map<String, Object> sourceObjects = new HashMap<>(); - - private Map<String, CapturedObject> capturedObjects = new HashMap<>(); - - private ClassLoader classLoader; - - private int count; - - private static class CaptureEventQueue extends EventQueue { - - private ClassLoader classLoader; - - private CaptureEventQueue(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - @Override - public void dispatchEvent(AWTEvent event) { - if (event.getID() == MouseEvent.MOUSE_PRESSED && ((MouseEvent) event).isControlDown()) { - Component target = ((MouseEvent) event).getComponent(); - if (!(target instanceof Window)) { - target = SwingUtilities.getWindowAncestor(target); - } - if (target instanceof JFrame) { - target = ((JFrame) target).getContentPane(); - } else if (target instanceof JDialog) { - target = ((JDialog) target).getContentPane(); - } - if (target instanceof JWindow) { - target = ((JWindow) target).getContentPane(); - } - if (target != null) { - Thread.currentThread().setContextClassLoader(classLoader); - JAXXCapture capture = new JAXXCapture(classLoader); - capture.applyNames(target); - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - XMLEncoder encoder = new XMLEncoder(buffer); - encoder.writeObject(target); - encoder.close(); - try { - System.err.println(new String(buffer.toByteArray())); - System.out.println(capture.convertToJAXX(new ByteArrayInputStream(buffer.toByteArray()))); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } - super.dispatchEvent(event); - } - } - - private JAXXCapture(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - public ClassLoader getClassLoader() { - return classLoader; - } - - public Map<String, CapturedObject> getCapturedObjects() { - return capturedObjects; - } - - private void applyNames(Component target) { - String name = target.getName(); - if (name == null || sourceObjects.containsKey(name) || !CompiledObject.isValidID(name)) { - do { - name = "Object" + ++count; - } while (sourceObjects.containsKey(name)); - } - target.setName(name); - assert !sourceObjects.containsKey(name) : "ID " + name + " is already registered"; - sourceObjects.put(name, target); - - if (target instanceof Container) { - Container container = (Container) target; - for (int i = 0; i < container.getComponentCount(); i++) { - applyNames(container.getComponent(i)); - } - } - } - - public static String getText(Element tag) { // NOT a safe general-purpose implementation! - return ((Text) tag.getChildNodes().item(0)).getData(); - } - - private String getArgumentsCode(ContextNode[] arguments) { - StringBuilder result = new StringBuilder(); - result.append('('); - for (int i = 0; i < arguments.length; i++) { - if (i != 0) { - result.append(", "); - } - result.append(getJavaCode(arguments[i])); - } - result.append(')'); - return result.toString(); - } - - public String getJavaCode(ContextNode node) { - StringBuilder result = new StringBuilder(); - if (node instanceof PropertyNode) { - ContextNode[] arguments = node.getArguments(); - result.append(arguments.length == 0 ? "get" : "set"); - result.append(StringUtils.capitalize(((PropertyNode) node).getProperty())); - result.append(getArgumentsCode(arguments)); - } else if (node instanceof MethodNode) { - result.append((((MethodNode) node).getMethodName())); - result.append(getArgumentsCode(node.getArguments())); - } else if (node instanceof CapturedObject) { - CapturedObject object = (CapturedObject) node; - if (object.isInlineable()) { - result.append("new "); - result.append(object.getClassName()); - result.append(getArgumentsCode(node.getArguments())); - } else { - String id = object.getProperty("id"); - assert id != null; - result.append(id); - } - } else if (node instanceof ValueNode) { - result.append(TypeManager.getJavaCode(((ValueNode) node).getValue())); - } else if (node instanceof LiteralNode) { - result.append(((LiteralNode) node).getJavaCode()); - } else { - throw new IllegalArgumentException("unrecognized node type: " + node); - } - return result.toString(); - } - - // returns the best matching method for the specified argument types - private static Method getMethod(Class<?> target, String methodName, Class<?>[] arguments) { - try { - // use the package-private class java.beans.ReflectionUtils to resolve the method. This isn't 100% safe, but it's better than - // having to rewrite the resolution myself. - Class<?> reflectionUtils = Class.forName("java.beans.ReflectionUtils"); - Method getMethod = reflectionUtils.getDeclaredMethod("getMethod", new Class<?>[]{Class.class, String.class, Class[].class}); - getMethod.setAccessible(true); - return (Method) getMethod.invoke(null, target, methodName, arguments); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - // returns the best matching constructor for the specified argument types - private static Constructor<?> getConstructor(Class<?> target, Class<?>[] arguments) { - try { - // use the package-private class java.beans.ReflectionUtils to resolve the constructor. This isn't 100% safe, but it's better than - // having to rewrite the resolution myself. - Class<?> reflectionUtils = Class.forName("java.beans.ReflectionUtils"); - Method getConstructor = reflectionUtils.getDeclaredMethod("getConstructor", new Class<?>[]{Class.class, Class[].class}); - getConstructor.setAccessible(true); - return (Constructor<?>) getConstructor.invoke(null, target, arguments); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private Object createInstance(CapturedObject object) { - try { - ContextNode[] argumentNodes = object.getArguments(); - Object[] arguments = new Object[argumentNodes.length]; - Class<?>[] argumentTypes = new Class<?>[argumentNodes.length]; - for (int j = 0; j < argumentNodes.length; j++) { - if (argumentNodes[j] instanceof ValueNode) { - arguments[j] = ((ValueNode) argumentNodes[j]).getValue(); - argumentTypes[j] = arguments[j] != null ? arguments[j].getClass() : null; - } else if (argumentNodes[j] instanceof CapturedObject) { - arguments[j] = createInstance((CapturedObject) argumentNodes[j]); - argumentTypes[j] = arguments[j] != null ? arguments[j].getClass() : null; - } - } - Constructor<?> constructor = getConstructor(Class.forName(object.getClassName(), true, classLoader), argumentTypes); - return constructor.newInstance(arguments); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public String getJavaCode(Stack/*<ContextNode>*/ context) { - CapturedObject contextCapturedObject = (CapturedObject) context.get(0); - StringBuilder result = new StringBuilder(); - int start = 1; - for (int i = context.size() - 1; i > 1; i--) { - if (context.get(i) instanceof CapturedObject) { - start = i; - contextCapturedObject = (CapturedObject) context.get(i); - break; - } - } - Object contextObject = sourceObjects.get(contextCapturedObject.getProperty("id")); - Class<?> contextClass = contextObject != null ? contextObject.getClass() : null; - - for (int i = start; i < context.size(); i++) { - ContextNode node = (ContextNode) context.get(i); - if (contextObject != null && (node instanceof MethodNode || node instanceof PropertyNode)) { - // need to follow the call chain so we can insert typecasts as necessary - try { - String methodName; - ContextNode[] argumentNodes = node.getArguments(); - if (node instanceof MethodNode) { - methodName = ((MethodNode) node).getMethodName(); - } else { - methodName = (argumentNodes.length == 0 ? "get" : "set") + StringUtils.capitalize(((PropertyNode) node).getProperty()); - } - Object[] arguments = new Object[argumentNodes.length]; - Class<?>[] argumentTypes = new Class<?>[argumentNodes.length]; - for (int j = 0; j < argumentNodes.length; j++) { - if (argumentNodes[j] instanceof ValueNode) { - arguments[j] = ((ValueNode) argumentNodes[j]).getValue(); - argumentTypes[j] = arguments[j] != null ? arguments[j].getClass() : null; - } else if (argumentNodes[j] instanceof CapturedObject) { - arguments[j] = createInstance((CapturedObject) argumentNodes[j]); - argumentTypes[j] = arguments[j].getClass(); - } else if (argumentNodes[j] instanceof LiteralNode) { - arguments[j] = ((LiteralNode) argumentNodes[j]).getValue(); - argumentTypes[j] = arguments[j].getClass(); - } else { - throw new IllegalArgumentException("unsupported argument type: " + argumentNodes[j]); - } - } - - Method method = getMethod(contextClass, methodName, argumentTypes); - if (method == null) { - // could not find method in contextClass, must be defined in a subclass -- insert a typecast - result.insert(0, "((" + getOutputName(contextObject.getClass()) + ") "); - result.append(')'); - method = getMethod(contextObject.getClass(), methodName, argumentTypes); - } - if (method == null) { - throw new RuntimeException("could not find method " + methodName + Arrays.asList(argumentTypes) + " in " + contextObject.getClass() + " (context: " + context + ")"); - } - contextObject = method.invoke(contextObject, arguments); - contextClass = method.getReturnType(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - if (i > start) { - result.append('.'); - } - - result.append(getJavaCode(node)); - } - return result + ";"; - } - - private String getOutputName(Class<?> c) { - return c.getName(); - } - - public CapturedObject processObject(Element objectTag, Stack<ContextNode> context) { - String className = objectTag.getAttribute("class"); - ObjectHandler handler; - if (className.length() > 0) { - try { - ClassDescriptor descriptor = ClassDescriptorHelper.getClassDescriptor(className, classLoader); - handler = (ObjectHandler) objectHandlers.get(descriptor); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } else { - handler = (ObjectHandler) objectHandlers.get(ClassDescriptorHelper.getClassDescriptor(Object.class)); - } - - return handler.processObject(objectTag, context, this); - } - - private synchronized String convertToJAXX(InputStream beansXML) throws IOException { - try { - Document document = JAXXCompiler.parseDocument(beansXML); - Element rootElement = document.getDocumentElement(); - NodeList nodes = rootElement.getChildNodes(); - Stack<ContextNode> context = new Stack<>(); - for (int i = 0; i < nodes.getLength(); i++) { - Node child = nodes.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - Element element = (Element) child; - if (!element.getTagName().equals("object")) { - throw new Error("expected tag 'object', found '" + element.getTagName() + "'"); - } - CapturedObject root = processObject(element, context); - for (CapturedObject object : capturedObjects.values()) { // add all orphan objects to the root, so any non-inlineable ones have their XML created - if (object.getParent() == null && object != root) { - root.addChild(object, null); - } - } - return root.getXML(this); - } - } - return null; - } catch (SAXException e) { - throw new RuntimeException(e); - } finally { - reset(); - } - } - - private void reset() { - sourceObjects.clear(); - capturedObjects.clear(); - count = 0; - } - - public static void main(String[] arg) throws Exception { - File file = new File(arg[0]); - JarFile jarFile = new JarFile(file); - ClassLoader classLoader = new URLClassLoader(new URL[]{file.toURI().toURL()}); - Thread.currentThread().setContextClassLoader(classLoader); - EventQueue systemQueue = Toolkit.getDefaultToolkit().getSystemEventQueue(); - systemQueue.push(new CaptureEventQueue(classLoader)); - Manifest mf = jarFile.getManifest(); - String mainClassName = mf.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS); - Class<?> mainClass = Class.forName(mainClassName, true, classLoader); - Method main = mainClass.getMethod("main", String[].class); - main.invoke(null, new Object[]{new String[0]}); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/LiteralNode.java b/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/LiteralNode.java deleted file mode 100644 index da582c6..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/LiteralNode.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tools.jaxxcapture; - -public class LiteralNode extends AbstractContextNode { - private String javaCode; - - private Object value; - - public LiteralNode(String javaCode, Object value) { - this.javaCode = javaCode; - this.value = value; - } - - - public String getJavaCode() { - return javaCode; - } - - public Object getValue() { - return value; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/MethodNode.java b/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/MethodNode.java deleted file mode 100644 index d9173cf..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/MethodNode.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tools.jaxxcapture; - -public class MethodNode extends AbstractContextNode { - private String methodName; - - public MethodNode(String methodName) { - this.methodName = methodName; - } - - - public String getMethodName() { - return methodName; - } - - @Override - public String toString() { - return "Method[" + methodName + ", " + java.util.Arrays.asList(getArguments()) + "]"; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/PropertyNode.java b/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/PropertyNode.java deleted file mode 100644 index 2ac611a..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/PropertyNode.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tools.jaxxcapture; - -public class PropertyNode extends AbstractContextNode { - private String property; - - public PropertyNode(String property) { - this.property = property; - } - - - public String getProperty() { - return property; - } - - - public String toString() { - return "Property[" + property + ", " + java.util.Arrays.asList(getArguments()) + "]"; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/ValueNode.java b/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/ValueNode.java deleted file mode 100644 index eaeee35..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/ValueNode.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tools.jaxxcapture; - -public class ValueNode extends AbstractContextNode { - private Object value; - - public ValueNode(Object value) { - this.value = value; - } - - - public Object getValue() { - return value; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/JTabbedPaneHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/JTabbedPaneHandler.java deleted file mode 100644 index 1181737..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/JTabbedPaneHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tools.jaxxcapture.handlers; - -import jaxx.compiler.tools.jaxxcapture.ContextNode; -import jaxx.compiler.tools.jaxxcapture.JAXXCapture; -import jaxx.compiler.tools.jaxxcapture.MethodNode; -import org.w3c.dom.Element; - -import java.util.Arrays; -import java.util.Stack; - -public class JTabbedPaneHandler extends ObjectHandler { - - @Override - protected void evaluateMethod(Element tag, Stack<ContextNode> context, JAXXCapture capture) { - String methodName = tag.getAttribute("method"); - if (methodName.equals("addTab")) { - MethodNode addTab = new MethodNode(methodName); - context.push(addTab); - processChildren(tag, context, capture); - context.pop(); - System.err.println(Arrays.asList(addTab.getArguments())); - } else { - super.evaluateMethod(tag, context, capture); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/ObjectHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/ObjectHandler.java deleted file mode 100644 index 4569c9b..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/ObjectHandler.java +++ /dev/null @@ -1,346 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tools.jaxxcapture.handlers; - -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.finalizers.JAXXCompilerFinalizer; -import jaxx.compiler.java.JavaFileGenerator; -import jaxx.compiler.tools.jaxxcapture.CapturedObject; -import jaxx.compiler.tools.jaxxcapture.ContextNode; -import jaxx.compiler.tools.jaxxcapture.JAXXCapture; -import jaxx.compiler.tools.jaxxcapture.LiteralNode; -import jaxx.compiler.tools.jaxxcapture.MethodNode; -import jaxx.compiler.tools.jaxxcapture.PropertyNode; -import jaxx.compiler.tools.jaxxcapture.ValueNode; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.awt.Container; -import java.lang.reflect.Field; -import java.util.Map; -import java.util.Stack; - -public class ObjectHandler { - private static int count; - - public static final String ATTRIBUTE_PROPERTY = "property"; - - protected CapturedObject createCapturedObject(String className, JAXXCapture capture) { - return new CapturedObject(this, className, capture); - } - - - // returns true if the tag has any "void" children - protected boolean processChildren(Element tag, Stack<ContextNode> context, JAXXCapture capture) { - boolean result = false; - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - Element innerTag = (Element) child; - if (innerTag.getTagName().equals(JAXXCompilerFinalizer.TYPE_VOID)) { - result = true; - } - evaluate(innerTag, context, capture); - } - } - return result; - } - - - protected void evaluateProperty(Element tag, Stack<ContextNode> context, JAXXCapture capture) { - // determine containing object - CapturedObject contextObject = null; - for (int i = context.size() - 1; i >= 0; i--) { - if (context.get(i) instanceof CapturedObject) { - contextObject = (CapturedObject) context.get(i); - break; - } - } - assert contextObject != null; - - String property = tag.getAttribute(ATTRIBUTE_PROPERTY); - if (!property.equals("actionCommand")) { // filter out actionCommand due to screwiness in XMLEncoder's handling of it - Object current = context.peek(); - PropertyNode newContext = new PropertyNode(property); - context.push(newContext); - boolean voidChildren = processChildren(tag, context, capture); - - ContextNode[] arguments = newContext.getArguments(); - if (arguments.length == 1) { - if (current instanceof CapturedObject && arguments[0] instanceof ValueNode) // simple property assignment - { - ((CapturedObject) current).setProperty(property, dataBindingEncode(String.valueOf(((ValueNode) arguments[0]).getValue()))); - } else if (current instanceof CapturedObject && arguments[0] instanceof CapturedObject && ((CapturedObject) arguments[0]).isInlineable()) // simple data binding - { - ((CapturedObject) current).setProperty(property, "{" + capture.getJavaCode(arguments[0]) + "}"); - } else { - contextObject.setInlineable(false); - contextObject.appendScriptCode(capture.getJavaCode(context)); - } - } else if (!voidChildren) { - contextObject.setInlineable(false); - contextObject.appendScriptCode(capture.getJavaCode(context)); - } - - assert context.peek() == newContext; - context.pop(); - } - } - - - protected void evaluateAdd(CapturedObject contextObject, CapturedObject child, ContextNode constraints) { - contextObject.addChild(child, constraints); - } - - - protected void evaluateMethod(Element tag, Stack<ContextNode> context, JAXXCapture capture) { - // determine containing object - CapturedObject contextObject = null; - for (int i = context.size() - 1; i >= 0; i--) { - if (context.get(i) instanceof CapturedObject) { - contextObject = (CapturedObject) context.get(i); - break; - } - } - assert contextObject != null; - - try { - String methodName = tag.getAttribute("method"); - MethodNode newContext = new MethodNode(methodName); - context.push(newContext); - boolean voidChildren = processChildren(tag, context, capture); - boolean add = false; - - ContextNode[] arguments = newContext.getArguments(); - if (methodName.equals("add") && arguments.length >= 1 && arguments[0] instanceof CapturedObject) { - Class<?> contextClass = Class.forName(contextObject.getClassName(), true, capture.getClassLoader()); - if (Container.class.isAssignableFrom(contextClass)) { - add = true; - evaluateAdd(contextObject, (CapturedObject) arguments[0], null); - } - } - - if (!voidChildren && !add) { - contextObject.appendScriptCode(capture.getJavaCode(context)); - } - - assert context.peek() == newContext; - context.pop(); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - - protected void evaluate(Element tag, Stack<ContextNode> context, JAXXCapture capture) { - String tagName = tag.getTagName(); - if (tagName.equals("object")) { - String fieldName = tag.getAttribute("field"); - ContextNode currentNode = context.peek(); - if (fieldName.length() > 0) { - try { - String className = tag.getAttribute("class"); - Field field = Class.forName(className, true, capture.getClassLoader()).getField(fieldName); - Object value = field.get(null); - currentNode.addArgument(new LiteralNode(className + "." + fieldName, value)); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else { - currentNode.addArgument(capture.processObject(tag, context)); - } - } else if (tagName.equals(JAXXCompilerFinalizer.TYPE_VOID)) { - String property = tag.getAttribute(ATTRIBUTE_PROPERTY); - if (property.length() > 0) { - evaluateProperty(tag, context, capture); - } else { - evaluateMethod(tag, context, capture); - } - } else if (tagName.equals("string")) { - context.peek().addArgument(new ValueNode(JAXXCapture.getText(tag))); - } else if (tagName.equals("boolean")) { - context.peek().addArgument(new ValueNode(Boolean.valueOf(JAXXCapture.getText(tag)))); - } else if (tagName.equals("char")) { - context.peek().addArgument(new ValueNode(JAXXCapture.getText(tag).charAt(0))); - } else if (tagName.equals("short")) { - context.peek().addArgument(new ValueNode(Short.valueOf(JAXXCapture.getText(tag)))); - } else if (tagName.equals("int")) { - context.peek().addArgument(new ValueNode(Integer.valueOf(JAXXCapture.getText(tag)))); - } else if (tagName.equals("long")) { - context.peek().addArgument(new ValueNode(Long.valueOf(JAXXCapture.getText(tag)))); - } else if (tagName.equals("float")) { - context.peek().addArgument(new ValueNode(Float.valueOf(JAXXCapture.getText(tag)))); - } else if (tagName.equals("double")) { - context.peek().addArgument(new ValueNode(Double.valueOf(JAXXCapture.getText(tag)))); - } else if (tagName.equals("null")) { - context.peek().addArgument(new ValueNode(null)); - } else { - System.err.println("unsupported tag: " + tag.getTagName()); - } - } - - - private static String dataBindingEncode(String value) { - return value.replaceAll("\\{", "\\\\{").replaceAll("\\}", "\\\\}"); - } - - - public CapturedObject processObject(Element objectTag, Stack<ContextNode> context, JAXXCapture capture) { - String className = objectTag.getAttribute("class"); - if (className.length() > 0) { - CapturedObject capturedObject = createCapturedObject(className, capture); - context.push(capturedObject); - NodeList children = objectTag.getChildNodes(); - String id = objectTag.getAttribute("id"); - if (id.length() == 0 || capture.getCapturedObjects().containsKey(id)) { - id = "Auto" + ++count; - } - assert !capture.getCapturedObjects().containsKey(id); - capture.getCapturedObjects().put(id, capturedObject); - capturedObject.setProperty("id", id); - // process object's name before anything else - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - Element element = (Element) child; - if (element.getTagName().equals(JAXXCompilerFinalizer.TYPE_VOID) && element.getAttribute(ATTRIBUTE_PROPERTY).equals("name")) { - evaluate(element, context, capture); - String name = capturedObject.getProperty("name"); - if (name != null && !capture.getCapturedObjects().containsKey(name)) { - capture.getCapturedObjects().put(name, capturedObject); - capturedObject.setProperty("id", name); - capturedObject.getProperties().remove("name"); - } - } - } - } - // process remaining children - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - Element element = (Element) child; - if (!JAXXCompilerFinalizer.TYPE_VOID.equals(element.getTagName()) || !element.getAttribute(ATTRIBUTE_PROPERTY).equals("name")) { - evaluate(element, context, capture); - } - } - } - assert context.peek() == capturedObject; - context.pop(); - - return capturedObject; - } else { - CapturedObject result = capture.getCapturedObjects().get(objectTag.getAttribute("idref")); - if (result == null) { - throw new RuntimeException("Internal error: could not find tag with id " + objectTag.getAttribute("idref")); - } - result.setInlineable(false); // we have at least two references to it, and so can't inline it - return result; - } - } - - - private static String xmlEncode(String src) { - return src.replaceAll("'", "&").replaceAll("<", "<"); - } - - - public String getXML(CapturedObject object, JAXXCapture capture) { - StringBuilder result = new StringBuilder(); - result.append('<'); - String className = object.getClassName(); - if (className.startsWith("javax.swing.")) { - className = className.substring("javax.swing.".length()); - } - result.append(className); - Map<String, String> properties = object.getProperties(); - for (Map.Entry<String, String> e : properties.entrySet()) { - result.append(' '); - result.append(e.getKey()); - result.append("='"); - result.append(xmlEncode(e.getValue())); - result.append('\''); - } - ContextNode[] arguments = object.getArguments(); - if (arguments != null && arguments.length > 0) { - result.append(" constructorParams='"); - for (int j = 0; j < arguments.length; j++) { - if (j != 0) { - result.append(", "); - } - result.append(capture.getJavaCode(arguments[j])); - } - result.append('\''); - } - boolean tagClosed = false; - - String children = getChildXML(object, capture); - String lineSeparator = JAXXCompiler.getLineSeparator(); - if (children != null && children.length() > 0) { - if (!tagClosed) { - tagClosed = true; - result.append('>'); - result.append(lineSeparator); - } - result.append(children); - } - - String script = object.getScriptCode(); - if (script != null && script.length() > 0) { - if (!tagClosed) { - tagClosed = true; - result.append('>'); - result.append(lineSeparator); - } - result.append(" <script>"); - result.append(lineSeparator); - result.append(JavaFileGenerator.indent(script, 4, false, lineSeparator)); - result.append(lineSeparator); - result.append(" </script>"); - result.append(lineSeparator); - } - if (tagClosed) { - result.append("</"); - result.append(className); - result.append('>'); - } else { - result.append("/>"); - } - return result.toString(); - } - - - protected String getChildXML(CapturedObject object, JAXXCapture capture) { - StringBuilder result = new StringBuilder(); - CapturedObject[] children = object.getChildren(); - String lineSeparator = JAXXCompiler.getLineSeparator(); - for (CapturedObject aChildren : children) { - if (!aChildren.isInlineable()) { - result.append(JavaFileGenerator.indent(aChildren.getXML(capture), 2, false, lineSeparator)); - result.append(lineSeparator); - } - } - return result.toString(); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/TableHandler.java b/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/TableHandler.java deleted file mode 100644 index a66f8be..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/TableHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tools.jaxxcapture.handlers; - -import jaxx.compiler.tools.jaxxcapture.CapturedObject; -import jaxx.compiler.tools.jaxxcapture.JAXXCapture; - -public class TableHandler extends ObjectHandler { - - @Override - protected CapturedObject createCapturedObject(String className, JAXXCapture capture) { - CapturedObject result = new CapturedObject(this, "javax.swing.JPanel", capture); - result.setProperty("layout", "{new GridBagLayout()}"); - return result; - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/types/ColorConverter.java b/jaxx-compiler/src/main/java/jaxx/compiler/types/ColorConverter.java deleted file mode 100644 index ad1d8c6..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/types/ColorConverter.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.types; - -import java.awt.Color; -import java.lang.reflect.Field; - -public class ColorConverter implements TypeConverter { - - @Override - public Class<?>[] getSupportedTypes() { - return new Class<?>[]{ - Color.class - }; - } - - @Override - public String getJavaCode(Object object) { - Color color = (Color) object; - return "new Color(" + color.getRed() + ", " + color.getGreen() + ", " + color.getBlue() + ")"; - } - - @Override - public Object convertFromString(String string, Class<?> type) { - if (!Color.class.equals(type)) { - throw new IllegalArgumentException("unsupported type: " + type); - } - if (string.length() == 7 && string.charAt(0) == '#') { - return new Color(Integer.parseInt(string.substring(1), 16)); - } - try { - Field color = Color.class.getField(string); - return color.get(null); - } catch (NoSuchFieldException e) { - throw new IllegalArgumentException("colors must be of the form #xxxxxx ('#' followed by six hexadecimal digits), or the name of a constant field in java.awt.Color (found: '" + string + "')"); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/types/GridBagConstraintsConverter.java b/jaxx-compiler/src/main/java/jaxx/compiler/types/GridBagConstraintsConverter.java deleted file mode 100644 index 69d6d94..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/types/GridBagConstraintsConverter.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.types; - -import java.awt.GridBagConstraints; - -public class GridBagConstraintsConverter implements TypeConverter { - - @Override - public Class<?>[] getSupportedTypes() { - return new Class<?>[]{ - GridBagConstraints.class - }; - } - - @Override - public String getJavaCode(Object object) { - GridBagConstraints g = (GridBagConstraints) object; - return "new GridBagConstraints(" + g.gridx + ", " + g.gridy + ", " + g.gridwidth + ", " + g.gridheight + ", " + - g.weightx + ", " + g.weighty + ", " + g.anchor + ", " + g.fill + ", " + - TypeManager.getJavaCode(g.insets) + ", " + g.ipadx + ", " + g.ipady + ")"; - } - - @Override - public Object convertFromString(String string, Class<?> type) { - throw new UnsupportedOperationException("GridBagConstraints must be represented using Java code"); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/types/InsetsConverter.java b/jaxx-compiler/src/main/java/jaxx/compiler/types/InsetsConverter.java deleted file mode 100644 index b7120bc..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/types/InsetsConverter.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.types; - -import java.awt.Insets; -import java.util.StringTokenizer; - -public class InsetsConverter implements TypeConverter { - - @Override - public Class<?>[] getSupportedTypes() { - return new Class<?>[]{Insets.class}; - } - - @Override - public String getJavaCode(Object object) { - Insets insets = (Insets) object; - return "new Insets(" + insets.top + ", " + insets.left + ", " + insets.bottom + ", " + insets.right + ")"; - } - - @Override - public Object convertFromString(String string, Class<?> type) { - if (!Insets.class.equals(type)) { - throw new IllegalArgumentException("unsupported type: " + type); - } - StringTokenizer tokenizer = new StringTokenizer(string, ","); - int count = tokenizer.countTokens(); - if (count == 1) { - int i = Integer.parseInt(tokenizer.nextToken().trim()); - return new Insets(i, i, i, i); - } - if (count == 4) { - int[] insets = new int[count]; - for (int i = 0; tokenizer.hasMoreTokens(); i++) { - insets[i] = Integer.parseInt(tokenizer.nextToken().trim()); - } - return new Insets(insets[0], insets[1], insets[2], insets[3]); - } - throw new IllegalArgumentException("unable to convert string '" + string + "' to Insets"); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/types/KeyStrokeConverter.java b/jaxx-compiler/src/main/java/jaxx/compiler/types/KeyStrokeConverter.java deleted file mode 100644 index 704db81..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/types/KeyStrokeConverter.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.types; - -import javax.swing.KeyStroke; - -public class KeyStrokeConverter implements TypeConverter { - - @Override - public Class<?>[] getSupportedTypes() { - return new Class<?>[]{KeyStroke.class}; - } - - @Override - public String getJavaCode(Object object) { - return "KeyStroke.getKeyStroke(\"" + object.toString() + "\")"; - } - - @Override - public Object convertFromString(String string, Class<?> type) { - if (!KeyStroke.class.equals(type)) { - throw new IllegalArgumentException("unsupported type: " + type); - } - return KeyStroke.getKeyStroke(string); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/types/PrimitiveConverter.java b/jaxx-compiler/src/main/java/jaxx/compiler/types/PrimitiveConverter.java deleted file mode 100644 index e550058..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/types/PrimitiveConverter.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.types; - -import jaxx.compiler.JAXXCompiler; - -public class PrimitiveConverter implements TypeConverter { - - @Override - public Class<?>[] getSupportedTypes() { - - return new Class<?>[]{ - boolean.class, - Boolean.class, - byte.class, - Byte.class, - short.class, - Short.class, - int.class, - Integer.class, - long.class, - Long.class, - float.class, - Float.class, - double.class, - Double.class, - char.class, - Character.class, - String.class - }; - } - - @Override - public String getJavaCode(Object object) { - if (object instanceof Boolean) { - return String.valueOf(((Boolean) object).booleanValue()); - } - if (object instanceof Byte) { - return String.valueOf(((Byte) object).byteValue()); - } - if (object instanceof Short) { - return String.valueOf(((Short) object).shortValue()); - } - if (object instanceof Integer) { - return String.valueOf(((Integer) object).intValue()); - } - if (object instanceof Long) { - return String.valueOf(((Long) object).longValue()) + "L"; - } - if (object instanceof Float) { - return String.valueOf(((Float) object).floatValue()) + "F"; - } - if (object instanceof Double) { - return String.valueOf(((Double) object).doubleValue()); - } - if (object instanceof String) { - return '"' + JAXXCompiler.escapeJavaString((String) object) + '"'; - } - throw new IllegalArgumentException("unsupported object: " + object); - } - - @Override - public Object convertFromString(String string, Class<?> type) { - if (String.class.equals(type) || Object.class.equals(type) || type == null) { - return string; - } - if (int.class.equals(type) || Integer.class.equals(type)) { - return Integer.valueOf(string); - } - if (boolean.class.equals(type) || Boolean.class.equals(type)) { - if (string.toLowerCase().equals("true")) { - return Boolean.TRUE; - } - if (string.toLowerCase().equals("false")) { - return Boolean.FALSE; - } - throw new IllegalArgumentException("expected 'true' or 'false', found '" + string + "'"); - } - if (byte.class.equals(type) || Byte.class.equals(type)) { - return Byte.valueOf(string); - } - if (short.class.equals(type) || Short.class.equals(type)) { - return Short.valueOf(string); - } - if (long.class.equals(type) || Long.class.equals(type)) { - return Long.valueOf(string); - } - if (float.class.equals(type) || Float.class.equals(type)) { - return Float.valueOf(string); - } - if (double.class.equals(type) || Double.class.equals(type)) { - return Double.valueOf(string); - } - if (char.class.equals(type) || Character.class.equals(type)) { - if (string.length() == 1) { - return string.charAt(0); - } - throw new IllegalArgumentException("expected a single character, found '" + string + "'"); - } - throw new IllegalArgumentException("unsupported type: " + type); - } -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/types/TypeConverter.java b/jaxx-compiler/src/main/java/jaxx/compiler/types/TypeConverter.java deleted file mode 100644 index 92c6a94..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/types/TypeConverter.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.types; - -public interface TypeConverter { - - Class<?>[] getSupportedTypes(); - - String getJavaCode(Object object); - - Object convertFromString(String string, Class<?> type); -} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/types/TypeManager.java b/jaxx-compiler/src/main/java/jaxx/compiler/types/TypeManager.java deleted file mode 100644 index 88e889c..0000000 --- a/jaxx-compiler/src/main/java/jaxx/compiler/types/TypeManager.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.types; - -import java.util.HashMap; -import java.util.Map; -import java.util.ServiceLoader; - -public class TypeManager { - - /** - * Dictionnary of converters loaded by the {@link ServiceLoader} mecanism - */ - private static Map<Class<?>, TypeConverter> converters; - - /** - * @return dictionnary of known converters - */ - public static Map<Class<?>, TypeConverter> getConverters() { - if (converters == null) { - converters = new HashMap<>(); - // load converters - ServiceLoader<TypeConverter> loader = - ServiceLoader.load(TypeConverter.class); - for (TypeConverter c : loader) { - // for each supported type, register the converter - for (Class<?> type : c.getSupportedTypes()) { - converters.put(type, c); - } - } - } - return converters; - } - - private TypeManager() { /* not instantiable */ } - - public static TypeConverter getTypeConverter(Class<?> type) { - return getConverters().get(type); - } - - public static String getJavaCode(Object object) { - if (object == null) { - return "null"; - } - TypeConverter converter = getTypeConverter(object.getClass()); - if (converter == null) { - throw new IllegalArgumentException("unsupported type: " + object.getClass()); - } - return converter.getJavaCode(object); - } - - public static Object convertFromString(String string, Class<?> type) { - TypeConverter converter = getTypeConverter(type); - if (converter == null) { - throw new IllegalArgumentException("unsupported type: " + type); - } - return converter.convertFromString(string, type); - } - - /** - * Convertit un nom de variable en nom de constante. - * - * @param variableName le nom de variable a convertir - * @return le nom de la constante à partir du nom de la variable - */ - public static String convertVariableNameToConstantName(String variableName) { - StringBuilder buffer = new StringBuilder(); - boolean lastCarIsUp = false; - char lastChar = '$'; - for (int i = 0, j = variableName.length(); i < j; i++) { - char c = variableName.charAt(i); - boolean carIsUp; - if (c == '!') { - buffer.append("NOT_"); - lastChar = '_'; - lastCarIsUp = true; - continue; - } - if (Character.isLetterOrDigit(c)) { - carIsUp = Character.isUpperCase(c); - } else { - carIsUp = false; - if (c != '$') { - // on remplace tous les caractères non standard par un _ - if (lastChar == '_' && c != '_') { - continue; - } - c = '_'; - } - } - - if (i > 0 && !lastCarIsUp && carIsUp) { - // ajout d'un _ - buffer.append('_'); - } - if (carIsUp) { - buffer.append(c); - } else { - buffer.append(Character.toUpperCase(c)); - } - lastCarIsUp = carIsUp || c == '$' || c == '_'; - lastChar = c; - } - return buffer.toString(); - } -} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/ClassMap.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/ClassMap.java new file mode 100644 index 0000000..7ddbb43 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/ClassMap.java @@ -0,0 +1,117 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +/** + * A Map implementation which uses Classes as keys. <code>ClassMap</code> differs from typical maps + * in that it takes subclasses into account; mapping a class to a value also maps all subclasses of + * that class to the value. + * + * A <code>get</code> operation will return the value associated with the class itself, or failing + * that, with its nearest ancestor for which there exists a mapping. + * + * @param <T> type of the class + */ +public class ClassMap<T> extends HashMap<ClassDescriptor, T> { + + private static final long serialVersionUID = 5149779660675529037L; + + /** + * Logger + */ + protected static final Log log = LogFactory.getLog(ClassMap.class); + + /** + * Keeps track of automatically-added Classes so we can distinguish them from user-added + * Classes. Unknown Classes are automatically added to the map during <code>get</code> + * calls to speed up subsequent requests, but they must be updated when the mappings + * for their superclasses are modified. + */ + private List<ClassDescriptor> autoKeys = new ArrayList<>(); + + /** + * Returns the value associated with the key <code>Class</code>. If the class itself does not have + * a mapping, its superclass will be checked, and so on until an ancestor class with a mapping is + * located. If none of the class' ancestors have a mapping, <code>null</code> is returned. + * + * @param key the class to check + * @return the mapping for the class + */ + @Override + public T get(Object key) { + T result = null; + ClassDescriptor c = (ClassDescriptor) key; + while (c != null) { + result = super.get(c); + if (result != null) { + break; + } + c = c.getSuperclass(); + } + + if (result == null && ((ClassDescriptor) key).isInterface()) { + result = get(ClassDescriptorHelper.getClassDescriptor(Object.class)); + } + + if (c != key && result != null) { // no mapping for the class itself, but found one for a superclass + put((ClassDescriptor) key, result); + autoKeys.add((ClassDescriptor) key); + } + return result; + } + + /** + * Associates a value with a class and all of its descendents. + * + * @param key the class to map + * @param value the value to map to the class + * @return the old value associated with the class + */ + @Override + public T put(ClassDescriptor key, T value) { + //if (!(key instanceof ClassDescriptor)) { + // throw new IllegalArgumentException("expected ClassDescriptor, got " + key); + //} + if (autoKeys.size() > 0) { // remove all automatic keys which descend from the class being modified + Iterator<ClassDescriptor> i = autoKeys.iterator(); + while (i.hasNext()) { + ClassDescriptor auto = i.next(); + if (key.isAssignableFrom(auto)) { + i.remove(); + remove(auto); + } + } + } + return super.put(key, value); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/CompiledObject.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/CompiledObject.java new file mode 100644 index 0000000..3d95e23 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/CompiledObject.java @@ -0,0 +1,791 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.nuiton.jaxx.compiler.tags.TagHandler; +import org.nuiton.jaxx.compiler.tags.TagManager; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Container; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Represents an object in the <code>.java</code> file being generated during compilation. There is + * a <code>CompiledObject</code> for each class tag encountered, and certain tags may generate + * additional objects for various reasons. + */ +public class CompiledObject { + + /** The object's id. */ + private String id; + + /** Java code referring to the object. */ + private String javaCode; + + /** The object's class. */ + private ClassDescriptor objectClass; + + /** The style class. */ + private String styleClass; + + /** The container containing this CompiledObject. */ + private CompiledObject parent; + + /** + * true if this object overrides an object of the same id in a superclass + * of the object being compiled + */ + private boolean override; + + /** + * The type of the object without fqn if possible. + * + * This is used when casting on an overridden object and only available if + * {@link #override} is set to {@code true}. + */ + private String simpleType; + + /** + * Comma-separated Java code snippets representing the parameters that + * should be passed to the object's constructor. + */ + private String constructorParams; + + /** + * Java code snippet which performs basic initialization of the object (after it has already been constructed). + * Because CompiledObject initialization order cannot be guaranteed, it is not safe to refer to other + * CompiledObjects from initializationCode -- you must refer to them from additionCode instead. + */ + private StringBuilder initializationCode = new StringBuilder(); + + /** + * Java code snippet which completes setup by adding any child objects, or otherwise manipulates any refererenced + * objects. Because CompiledObject initialization order cannot be guaranteed, it is not safe to refer to other + * CompiledObjects from initializationCode -- you must refer to them from additionCode instead. + */ + private StringBuilder additionCode = new StringBuilder(); + + /** List of all registered event handlers. */ + private List<EventHandler> eventHandlers = new ArrayList<>(); + + /** All properties that have been applied to this CompiledObject. */ + private Map<String, String> properties = new HashMap<>(); + + /** generic types of the compiled object */ + private String[] genericTypes; + + /** + * a flag to indicate if javaBean full support must be support for this + * object by root object + */ + private boolean javaBean; + + /** code to initialize the bean (can be null) */ + private String javaBeanInitCode; + + /** the type of the override object (can be null if no overide) */ + private ClassDescriptor overrideType; + + /** the decorator */ + private CompiledObjectDecorator decorator; + + /** client properties */ + private Map<String, String> clientProperties; + + /** initializer of the object */ + private String initializer; + + public String getSimpleType() { + return simpleType; + } + + public class ChildRef { + + CompiledObject child; + + String constraints; + + String childJavaCode; + + private String delegateCode; + + public ChildRef(CompiledObject child, + String constraints, + String childJavaCode, + String delegateCode) { + this.child = child; + this.constraints = constraints; + this.childJavaCode = childJavaCode; + this.delegateCode = delegateCode; + } + + + public String getConstraints() { + return constraints; + } + + public String getDelegateCode() { + return delegateCode; + } + + public CompiledObject getChild() { + return child; + } + + public String getChildJavaCode() { + return childJavaCode; + } + + public void setChildJavaCode(String childJavaCode) { + this.childJavaCode = childJavaCode; + } + + public void addToAdditionCode(StringBuilder buffer, + boolean isRootObject) { + //TC-20091026 do not prefix if on root object + String prefix; + if (isRootObject) { + prefix = ""; + } else { + prefix = javaCode + delegateCode + "."; + } + if (constraints != null) { + buffer.append(prefix); + buffer.append("add("); + buffer.append(childJavaCode); + buffer.append(", "); + buffer.append(constraints); + buffer.append(");"); + } else { + buffer.append(prefix); + buffer.append("add("); + buffer.append(childJavaCode); + buffer.append(");"); + } + buffer.append(JAXXCompiler.getLineSeparator()); + } + } + + private List<ChildRef> childs; + + /** + * Creates a new <code>CompiledObject</code>. + * + * To be useful, the object should be registered with a + * <code>JAXXCompiler</code> using + * {@link JAXXCompiler#registerCompiledObject(CompiledObject)} . + * + * @param id the object's id + * @param objectClass the object's class + * @param compiler the current <code>JAXXCompiler</code> + * @throws NullPointerException if id or class is null + */ + public CompiledObject(String id, + ClassDescriptor objectClass, + JAXXCompiler compiler) { + this(id, objectClass, compiler, false); + } + + /** + * Creates a new <code>CompiledObject</code>. To be useful, the object should be registered with a + * <code>JAXXCompiler</code> using {@link JAXXCompiler#registerCompiledObject(CompiledObject)} . + * + * @param id the object's id + * @param objectClass the object's class + * @param compiler the current <code>JAXXCompiler</code> + * @param force <code>true</code> to force acceptance of invalid ids + * @throws NullPointerException if id or class is null + */ + public CompiledObject(String id, + ClassDescriptor objectClass, + JAXXCompiler compiler, + boolean force) { + this(id, id, objectClass, compiler, force); + } + + /** + * Creates a new <code>CompiledObject</code>. To be useful, the object should be registered with a + * <code>JAXXCompiler</code> using {@link JAXXCompiler#registerCompiledObject(CompiledObject)} . + * + * @param id the object's id + * @param javaCode Java code referring to the object + * @param objectClass the object's class + * @param force <code>true</code> to force acceptance of invalid ids + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if the id is not a valid Java identifier + * @throws NullPointerException if id or class is null + */ + public CompiledObject(String id, + String javaCode, + ClassDescriptor objectClass, + JAXXCompiler compiler, + boolean force) throws CompilerException { + if (!force) { + if (!isValidID(id)) { + compiler.reportError( + "the id '" + id + "' is not a valid Java identifier"); + } + } + this.id = id; + this.javaCode = javaCode; + + if (objectClass == null) { + throw new NullPointerException(); + } + this.objectClass = objectClass; + childs = new ArrayList<>(); + } + + public static boolean isValidID(String id) { + boolean valid = true; + if (id.length() == 0) { + valid = false; + } + if (valid) { + if (!Character.isJavaIdentifierStart(id.charAt(0))) { + valid = false; + } + if (valid) { + for (int i = 1; i < id.length(); i++) { + if (!Character.isJavaIdentifierPart(id.charAt(i))) { + valid = false; + break; + } + } + } + } + return valid; + } + + /** + * True if this object overrides an object in the superclass of the class + * being compiled. For this to be true, the class currently being compiled + * must be a subclass of another <code>JAXXObject</code> which has an + * identically-named object. + * + * @return <code>true</code> if this object is an override + * @see #setOverride(boolean) + */ + public boolean isOverride() { + return override; + } + + /** + * {@code true} when overrides an object in the superclass of the class + * being compiled AND type is also override. + * + * @return {@code true} if this object is an override AND override type + */ + public boolean isOverrideType() { + return isOverride() && !getObjectClass().equals(getOverrideType()); + } + + /** + * Sets whether this class overrides an identically-named object in the + * parent class. + * + * @param override <code>true</code> if this object is an override + * @see #isOverride + */ + public void setOverride(boolean override) { + this.override = override; + } + + /** + * Sets the simple type of the object. + * + * Used when castin an overridden object. + * + * @param simpleType the simple type to use (or the fqn if there is a + * conflict with already imported types of the compiler). + * @since 2.4 + */ + public void setSimpleType(String simpleType) { + this.simpleType = simpleType; + } + + /** + * Returns this object's CSS style class. + * + * @return the value of the <code>styleClass</code> attribute + */ + public String getStyleClass() { + return styleClass; + } + + /** + * Sets this object's CSS style class. + * + * @param styleClass the new style class + */ + public void setStyleClass(String styleClass) { + this.styleClass = styleClass; + } + + /** + * Returns this object's parent container. Non-visual components (and + * the root container) return <code>null</code>. + * + * @return the object's parent container + */ + public CompiledObject getParent() { + return parent; + } + + /** + * Sets this object's parent container. + * + * @param parent the parent container + * @throws IllegalArgumentException if parent is not a {@link Container} + */ + public void setParent(CompiledObject parent) throws IllegalArgumentException { + if (!ClassDescriptorHelper.getClassDescriptor(Container.class).isAssignableFrom(parent.getObjectClass())) { + throw new IllegalArgumentException("parent must descend from java.awt.Container"); + } + this.parent = parent; + } + + /** + * Returns the name of the method that should be generated in the compiled + * <code>.java</code> file + * in order to create this object. This is just a suggestion and may be + * ignored. + * + * @return the suggested name of the method which initializes this object + */ + public String getCreationMethodName() { + return "create" + StringUtils.capitalize(getId()); + } + + /** + * Returns the name of the method that should be generated in the compiled + * <code>.java</code> file in order to add children to this object. This + * is just a suggestion and may be ignored. + * + * @return the suggested name of the method which completes this object's setup + */ + public String getAdditionMethodName() { + return "addChildrenTo" + StringUtils.capitalize(getId()); + } + + /** + * Returns the type of this object. + * + * @return the class this <code>CompiledObject</code> represents + */ + public ClassDescriptor getObjectClass() { + return objectClass; + } + + /** + * Returns this object's id. Generally, a field with this name will be + * created in the compiled <code>.java</code> + * file in order to represent this object. + * + * @return the id used to refer to this object + */ + public String getId() { + return id; + } + + /** + * Returns Java code used to refer to this object in the compiled Java file. + * This is usually the same as its id. + * + * @return the Java code for this object + */ + public String getJavaCode() { + String result = javaCode; + if (isOverride()) { + // handle cases where object is overridden to be a different class + if (simpleType == null) { + + // means overridden but stil on the same type + result = javaCode; + } else { + result = "((" + simpleType + ") " + javaCode + ")"; +// result = "((" + JAXXCompiler.getCanonicalName(this) + ") " + javaCode + ")"; + } + } + return result; + } + + public String getJavaCodeForProperty(String property) { + if (!isOverride() || simpleType == null) { + return javaCode; + } + String result = "((" + simpleType + ") " + javaCode + ")"; +// String result = "((" + JAXXCompiler.getCanonicalName(this) + ") " + javaCode + ")"; +// String result = "((" + JAXXCompiler.getCanonicalName(getObjectClass()) + ") " + javaCode + ")"; + + String methodName = StringUtils.capitalize(property); + try { + MethodDescriptor methodDescriptor = overrideType.getMethodDescriptor("get" + methodName); + if (methodDescriptor != null) { + if (overrideType.getMethodDescriptor("set" + methodName, methodDescriptor.getReturnType()) != null) { + // handle cases where object is overridden to be a different class + result = javaCode; + } + } + } catch (NoSuchMethodException e) { + // lazy error, do nothing + } + return result; + } + + /** + * Returns a list of comma-separated Java code snippets that represent the + * parameters to pass to this object's constructor. + * + * @return the raw constructor params + * @see #setConstructorParams(String) + */ + public String getConstructorParams() { + return constructorParams; + } + + /** + * Sets the parameters to pass to this object's constructor. + * + * @param constructorParams comma-separated Java code snippets representing + * constructor params + * @see #getConstructorParams + */ + public void setConstructorParams(String constructorParams) { + this.constructorParams = constructorParams; + } + + public String getInitializer() { + return initializer; + } + + public void setInitializer(String initializer) { + this.initializer = initializer; + } + + /** + * Returns the code that performs basic initialization of this object, + * after it has already been constructed. + * This basic code should not reference any other + * <code>CompiledObjects</code> as they may not have been created yet. + * + * @param compiler compiler to use + * @return the code which initializes this object + */ + public String getInitializationCode(JAXXCompiler compiler) { + StringBuilder result = new StringBuilder(initializationCode.toString()); + for (Object eventHandler : eventHandlers) { + EventHandler handler = (EventHandler) eventHandler; + result.append(getInitializationCode(handler, compiler)); + } + return result.toString(); + } + + protected String getInitializationCode(EventHandler handler, JAXXCompiler compiler) { + MethodDescriptor addMethod = handler.getAddMethod(); + ClassDescriptor listenerClass = addMethod.getParameterTypes()[0]; + String type = compiler.getImportedType(listenerClass.getName()); + String prefix = compiler.getImportedType(JAXXUtil.class); + + //TC-20091026 use 'this' instead of root object javaCode + //TC-20091105 JAXXUtil.getEventListener is generic, no more need cast and use simple name + return getJavaCode() + '.' + addMethod.getName() + "(" + prefix + ".getEventListener(" + type + ".class, " + + TypeManager.getJavaCode(handler.getListenerMethod().getName()) + ", this, " + + TypeManager.getJavaCode(compiler.getEventHandlerMethodName(handler)) + "));" + JAXXCompiler.getLineSeparator(); + } + + /** + * Returns Java code to complete final setup on this object. This code may + * reference other <code>CompiledObjects</code>, as they are guaranteed to + * have all been created by this point. + * + * @return code which adds children and performs final setup + */ + public String getAdditionCode() { + return additionCode.toString(); + } + + /** + * Appends code to the initialization code block. A line separator is + * automatically appended to the end. + * + * @param code the code to add to the initialization block + * @see #getInitializationCode(JAXXCompiler) + */ + public void appendInitializationCode(String code) { + if (!code.isEmpty()) { + initializationCode.append(code); + initializationCode.append(JAXXCompiler.getLineSeparator()); + } + } + + /** + * Appends code to the addition code block. A line separator is + * automatically appended to the end. + * + * @param code the code to add to the addition block + * @see #getAdditionCode + */ + public void appendAdditionCode(String code) { + if (!code.isEmpty()) { + additionCode.append(code); + additionCode.append(JAXXCompiler.getLineSeparator()); + } + } + + /** + * Stores a property for this object. The only effect of calling this + * method is that the property will be returned by {@code getProperties()}. + * + * @param property the name of the property + * @param value the property's value + * @see #getProperties() + */ + public void addProperty(String property, String value) { + properties.put(property, value); + } + + public boolean hasClientProperties() { + return clientProperties != null && !clientProperties.isEmpty(); + } + + public void addClientProperty(String property, String value) { + getClientProperties().put(property, value); + } + + public String getClientProperty(String key) { + if (!hasClientProperties()) { + return null; + } + return clientProperties.get(key); + } + + public Map<String, String> getClientProperties() { + if (clientProperties == null) { + clientProperties = new HashMap<>(); + } + return clientProperties; + } + + /** + * Returns all properties which have been set for this object. + * + * @return a <code>Map</code> containing all properties defined for this object + * @see #addProperty(String, String) + */ + public Map<?, ?>/*<String, String>*/ getProperties() { + return properties; + } + + /** + * Adds an event listener to this object. The generated code will appear + * in the initialization block. + * + * @param eventId unique (per CompiledObject) identifier for the event handler + * @param addMethod the method which adds the event listener + * @param listenerMethod the method (in the listener class) which is called when the event is fired + * @param code the Java code for the listenerMethod's body + * @param compiler the current <code>JAXXCompiler</code> + * @see #getInitializationCode(EventHandler, JAXXCompiler) + */ + public void addEventHandler(String eventId, + MethodDescriptor addMethod, + MethodDescriptor listenerMethod, + String code, + JAXXCompiler compiler) { + EventHandler handler = new EventHandler( + getId() + "." + eventId, + getJavaCode(), + addMethod, + addMethod.getParameterTypes()[0], + listenerMethod, + code + ); + compiler.registerEventHandler(handler); + eventHandlers.add(handler); + + if (getJavaCode().contains(".")) { + // object lives in another JAXX file and consequently its initialization code won't be output + compiler.appendInitializerCode( + getInitializationCode(handler, compiler)); + } + } + + /** + * Adds a child component to this container. The child is added without + * layout constraints. + * + * @param child the component to add + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if this object is not a container + * @see #addChild(CompiledObject, String, JAXXCompiler) + */ + public void addChild(CompiledObject child, + JAXXCompiler compiler) throws CompilerException { + addChild(child, null, compiler); + } + + /** + * Adds a child component to this container. This variant allows the Java + * code for a layout constraints object to be specified. + * + * @param child the component to add + * @param constraints Java code for the layout constraints object + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if this object is not a container + * @see #addChild(CompiledObject, JAXXCompiler) + */ + public void addChild(CompiledObject child, + String constraints, + JAXXCompiler compiler) throws CompilerException { + try { + if (constraints != null) { + constraints = compiler.checkJavaCode(constraints); + } + } catch (CompilerException e) { + compiler.reportError( + "While parsing 'constraints' attribute: " + e.getMessage()); + } + + if (!child.isOverride()) { + TagHandler tagHandler = TagManager.getTagHandler(getObjectClass()); + if (tagHandler instanceof DefaultComponentHandler && + !((DefaultComponentHandler) tagHandler).isContainer()) { + compiler.reportError("component " + this + " may not have children"); + } + + String containerDelegate = ((DefaultComponentHandler) tagHandler).getContainerDelegate(); + String delegateCode = containerDelegate != null ? + "." + containerDelegate + "()" : + ""; + + child.setParent(this); + + ChildRef ref = newChildRef(child, constraints, delegateCode); + childs.add(ref); + } + } + + protected ChildRef newChildRef(CompiledObject child, String constraints, String delegateCode) { + return new ChildRef(child, + constraints, + child.getJavaCode(), + delegateCode + ); + } + + @Override + public String toString() { + return getObjectClass().getName() + "[id='" + id + "']"; + } + + public String getGenericTypes() { + if (getGenericTypesLength() == 0) { + // not using it + return ""; + } + String result = ""; + for (int i = 0, j = getGenericTypesLength(); i < j; i++) { + result += ", " + genericTypes[i]; + } + return "< " + result.substring(2) + " >"; + } + + public void setGenericTypes(String... genericTypes) { + if (genericTypes == null) { + this.genericTypes = null; + return; + } + this.genericTypes = new String[genericTypes.length]; + for (int i = 0, j = genericTypes.length; i < j; i++) { + this.genericTypes[i] = genericTypes[i].trim(); + } + } + + public boolean isJavaBean() { + return javaBean; + } + + public void setJavaBean(boolean javaBean) { + this.javaBean = javaBean; + } + + public ClassDescriptor getOverrideType() { + return overrideType; + } + + public void setOverrideType(ClassDescriptor overrideType) { + this.overrideType = overrideType; + } + + public String getJavaBeanInitCode() { + return javaBeanInitCode; + } + + public void setJavaBeanInitCode(String javaBeanInitCode) { + this.javaBeanInitCode = javaBeanInitCode; + } + + public List<ChildRef> getChilds() { + return childs; + } + + public CompiledObjectDecorator getDecorator() { + return decorator; + } + + public void setDecorator(CompiledObjectDecorator decorator) { + this.decorator = decorator; + } + + public void finalizeCompiler(JAXXCompiler compiler) { + + List<ChildRef> refList = getChilds(); + if (refList != null && !refList.isEmpty()) { + // compute additionCode for all childs + StringBuilder buffer = new StringBuilder(); + for (ChildRef childRef : refList) { + childRef.addToAdditionCode(buffer, + equals(compiler.getRootObject())); + } + additionCode = buffer.append(additionCode); + } + } + + public int getGenericTypesLength() { + return genericTypes == null ? 0 : genericTypes.length; + } + + public String getGetterName() { + return "get" + StringUtils.capitalize(id); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/CompiledObjectDecorator.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/CompiledObjectDecorator.java new file mode 100644 index 0000000..c41f81f --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/CompiledObjectDecorator.java @@ -0,0 +1,105 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler; + +import org.nuiton.jaxx.compiler.java.JavaFile; + +/** + * Contract of compiled object decorator at generation time. + * + * Note : The implementation of this class must be stateless. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.2 + */ +public interface CompiledObjectDecorator { + + /** + * @return the name of the decorator (match the content of a decorator + * attribute value in a JAXX file) + */ + String getName(); + + /** + * Obtain the setup code of the given {@code object} from the + * {@code compiler} to be inject in the generated method + * {@code $completeSetup}. + * + * @param compiler the compiler to use + * @param object the compiled object to treate + * @param javaFile the file to treate + * @return the code to inject in $completeSetup method in file + */ + String createCompleteSetupMethod(JAXXCompiler compiler, + CompiledObject object, + JavaFile javaFile); + + /** + * Create the initializer code for the given compiled {@code object} and + * inject it in the {@code code}. + * + * @param compiler the compiler to use + * @param root the root compiled object of the jaxx file + * @param object the compiled object to treate + * @param code where to store code to inject + * @param lastWasMethodCall {@code true} if last instruction call was a method call + * @return {@code true} if the last instruction was a method call + */ + boolean createInitializer(JAXXCompiler compiler, + CompiledObject root, + CompiledObject object, + StringBuilder code, + boolean lastWasMethodCall); + + /** + * Finalize the given compiled object before any generation in the {@code file}. + * + * @param compiler the compiler to use + * @param root the root compiled object of the jaxx file + * @param object the compiled object to treate + * @param javaFile the file to treate + * @param packageName the package name + * @param className the (simple ?) class name + * @param fullClassName the fully class name + * @throws ClassNotFoundException if a class is not found + */ + void finalizeCompiler(JAXXCompiler compiler, + CompiledObject root, + CompiledObject object, + JavaFile javaFile, + String packageName, + String className, + String fullClassName) throws ClassNotFoundException; + + /** + * Obtain the creation code of the given {@code object} from the {@code compiler} to inject in generate method + * {@code $initialize} or {@code createXXX} in not inline. + * + * @param compiler the compiler to use + * @param object the compiled object to treate + * @return the code to inject in $initialize (or in the createXXX in not inline) method to create the given object + * @throws CompilerException if any pb + */ + String getCreationCode(JAXXCompiler compiler, + CompiledObject object) throws CompilerException; +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/CompilerConfiguration.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/CompilerConfiguration.java new file mode 100644 index 0000000..0d16881 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/CompilerConfiguration.java @@ -0,0 +1,179 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler; + +import org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import org.nuiton.jaxx.compiler.spi.Initializer; +import org.nuiton.jaxx.runtime.JAXXContext; +import org.nuiton.jaxx.runtime.spi.UIHandler; + +import java.io.File; +import java.util.Map; + +/** + * Configuration of a compiler task. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.0 + */ +public interface CompilerConfiguration { + + /** + * Default css file extension. + * + * @since 2.28 + */ + String DEFAULT_CSS_EXTENSION = "css"; + + /** @return the class loader used by compilers */ + ClassLoader getClassLoader(); + + /** @return the type of compiler to use */ + Class<? extends JAXXCompiler> getCompilerClass(); + + /** @return the type of default decorator to use if none specified */ + Class<? extends CompiledObjectDecorator> getDefaultDecoratorClass(); + + /** @return the type of the default error UI to use for validation */ + Class<?> getDefaultErrorUI(); + + /** @return extra imports to add on all generated jaxx object */ + String[] getExtraImports(); + + /** + * @return the FQN of the help broker (can not directly a type since + * the help broker should (may?) be inside the sources. + */ + String getHelpBrokerFQN(); + + /** + * @return the FQN of the validator factory used to instanciate new validators. + * @since 2.6 + */ + String getValidatorFactoryFQN(); + + + /** @return the type of context to use in each generated jaxx object */ + Class<? extends JAXXContext> getJaxxContextClass(); + + /** + * Returns whether or not optimization should be performed. + * + * @return whether or not optimizations should be performed + */ + boolean getOptimize(); + + /** + * Returns whether or not should recurse in css for existing JAXX Object. + * + * <b>Note:</b> This functionnality was here at the beginning of the project + * but offers nothing very usefull, will be remove probably in JAXX 3.0. + * + * @return {@code true} if a css file with same name as jaxx file should + * be included in jaxx file if found. + * @since 2.0.2 + */ + boolean isAutoRecurseInCss(); + + /** + * Returns the target directory. + * + * @return the target directory + */ + File getTargetDirectory(); + + /** @return {@code true} if a logger must add on each generated jaxx object */ + boolean isAddLogger(); + + /** @return {@code true} if we are generating help */ + boolean isGenerateHelp(); + + /** @return {@code true} if we use the i18n system */ + boolean isI18nable(); + + /** @return {@code true} to generate optimized code */ + boolean isOptimize(); + + /** @return {@code true} if a profile pass must be done */ + boolean isProfile(); + + /** @return {@code true} if states must be reset after the compilation */ + boolean isResetAfterCompile(); + + /** @return {@code true} if UIManager is used to retrieve icons */ + boolean isUseUIManagerForIcon(); + + /** @return {@code true} if compiler is verbose */ + boolean isVerbose(); + + /** + * @return {@code true} to trace the Class descriptor loading. + * @since 2.4 + */ + boolean isShowClassDescriptorLoading(); + + /** + * @return {@code true} to detect and add {@link UIHandler} if found in class-path. + * @since 2.6 + */ + boolean isAddAutoHandlerUI(); + + /** + * @param addAutoHandlerUI new value of the state + * @since 2.6 + */ + void setAddAutoHandlerUI(boolean addAutoHandlerUI); + + /** + * @return {@code true} to generate missing ids and style classes in the CSS files + * @since 2.29 + */ + boolean isGenerateMissingIdsAndStyleClassesInCss(); + + /** + * @param generateMissingIdsAndStyleClassesInCss new value of the state + * @since 2.29 + */ + void setGenerateMissingIdsAndStyleClassesInCss(boolean generateMissingIdsAndStyleClassesInCss); + + /** @return the encoding to use to write files */ + String getEncoding(); + + Map<String, CompiledObjectDecorator> getDecorators(); + + Map<String, JAXXCompilerFinalizer> getFinalizers(); + + Map<String, Initializer> getInitializers(); + + /** + * @return the optional common css to inject in all JaxxCompiler. + * @since 2.13 + */ + File getCommonCss(); + + /** + * @return the extension of css files (by default use {@link #DEFAULT_CSS_EXTENSION} as before). + * @since 2.28 + */ + String getCssExtension(); +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/CompilerException.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/CompilerException.java new file mode 100644 index 0000000..a06af1f --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/CompilerException.java @@ -0,0 +1,68 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler; + +/** Thrown by the compiler when an error occurs. */ +public class CompilerException extends RuntimeException { + + private static final long serialVersionUID = -9099889519671482440L; + + /** Creates a new <code>ParseException</code>. */ + public CompilerException() { + } + + /** + * Creates a new <code>ParseException</code> with the specified detail message. + * + * @param msg the exception's detail message + */ + public CompilerException(String msg) { + super(msg); + } + + /** + * Creates a new <code>ParseException</code> with the specified cause. + * + * @param initCause the exception's initCause + */ + public CompilerException(Throwable initCause) { + super(initCause); + } + + /** + * Creates a new <code>ParseException</code> with the specified detail message and cause. + * + * @param msg the exception's detail message + * @param initCause the exception's initCause + */ + public CompilerException(String msg, Throwable initCause) { + super(msg, initCause); + } + +// @Override +// public void printStackTrace() { +// super.printStackTrace(); +// System.err.println("CompilerException printed from:"); +// Thread.dumpStack(); +// } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/DefaultCompilerConfiguration.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/DefaultCompilerConfiguration.java new file mode 100644 index 0000000..c426dc9 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/DefaultCompilerConfiguration.java @@ -0,0 +1,373 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler; + +import org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import org.nuiton.jaxx.compiler.spi.Initializer; +import org.nuiton.jaxx.runtime.JAXXContext; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.UIManager; +import java.io.File; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.TreeMap; + +/** Options of the {@link JAXXCompiler} and {@link JAXXEngine}. */ +public class DefaultCompilerConfiguration implements CompilerConfiguration { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(DefaultCompilerConfiguration.class); + + /** where to generate */ + private File targetDirectory; + + /** flag to optimize generated code */ + private boolean optimize; + + /** verbose flag */ + private boolean verbose; + + /** to do a profile pass after generation */ + private boolean profile; + + /** a flag to enable or disable i18n generation */ + private boolean i18nable; + + /** a flag to add or not logger on generated jaxx files */ + private boolean addLogger; + + /** a flag to not reset compiler after a compile */ + private boolean resetAfterCompile; + + /** + * the name of implementation of {@link JAXXContext} + * to be used on {@link JAXXObject}. + */ + protected Class<? extends JAXXContext> jaxxContextClass; + + /** list of fqn of class to import for all generated jaxx files */ + protected String[] extraImports; + + /** default error ui */ + private Class<?> defaultErrorUI; + + /** class loader to use in compiler */ + private ClassLoader classLoader = getClass().getClassLoader(); + + /** the compiler class to use */ + private Class<? extends JAXXCompiler> compilerClass; + + /** + * the default compiled object decorator to use if none specifed via + * decorator attribute + */ + private Class<? extends CompiledObjectDecorator> defaultDecoratorClass; + + /** a flag to use {@link UIManager} to retreave icons. */ + private boolean useUIManagerForIcon; + + /** a flag to generate javax help for any */ + private boolean generateHelp; + + /** + * Fully qualified name of help broker, can not use a class here + * since this class should be in sources (so not yet compiled) + */ + private String helpBrokerFQN; + + /** + * Fully qualified name of validator factory. + * + * @since 2.6 + */ + private String validatorFactoryFQN; + + /** Encoding to use to write files */ + private String encoding; + + private boolean autoRecurseInCss; + + /** decorators available in engine */ + protected Map<String, CompiledObjectDecorator> decorators; + + /** finalizers available in engine */ + protected Map<String, JAXXCompilerFinalizer> finalizers; + + /** initializes availables */ + protected Map<String, Initializer> initializers; + + /** + * To trace class descriptor loading. + * + * @since 2.4 + */ + private boolean showClassDescriptorLoading; + + /** + * To detect {@link UIHandler} if found. + * + * @since 2.6 + */ + private boolean addAutoHandlerUI; + + /** + * To generate missing ids and style classes in the CSS files + * + * @since 2.29 + */ + private boolean generateMissingIdsAndStyleClassesInCss; + + /** + * Optional common css. + * + * @since 2.13 + */ + private File commonCss; + + @Override + public File getTargetDirectory() { + return targetDirectory; + } + + @Override + public boolean getOptimize() { + return optimize; + } + + @Override + public boolean isVerbose() { + return verbose; + } + + @Override + public boolean isShowClassDescriptorLoading() { + return showClassDescriptorLoading; + } + + @Override + public boolean isAddAutoHandlerUI() { + return addAutoHandlerUI; + } + + @Override + public void setAddAutoHandlerUI(boolean addAutoHandlerUI) { + this.addAutoHandlerUI = addAutoHandlerUI; + } + + @Override + public boolean isGenerateMissingIdsAndStyleClassesInCss() { + return generateMissingIdsAndStyleClassesInCss; + } + + @Override + public void setGenerateMissingIdsAndStyleClassesInCss(boolean generateMissingIdsAndStyleClassesInCss) { + this.generateMissingIdsAndStyleClassesInCss = generateMissingIdsAndStyleClassesInCss; + } + + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + @Override + public boolean isI18nable() { + return i18nable; + } + + @Override + public boolean isUseUIManagerForIcon() { + return useUIManagerForIcon; + } + + @Override + public boolean isAddLogger() { + return addLogger; + } + + @Override + public Class<? extends JAXXContext> getJaxxContextClass() { + return jaxxContextClass; + } + + @Override + public String[] getExtraImports() { + return extraImports; + } + + @Override + public boolean isResetAfterCompile() { + return resetAfterCompile; + } + + @Override + public boolean isOptimize() { + return optimize; + } + + @Override + public Class<?> getDefaultErrorUI() { + return defaultErrorUI; + } + + @Override + public ClassLoader getClassLoader() { + return classLoader; + } + + @Override + public Class<? extends JAXXCompiler> getCompilerClass() { + return compilerClass; + } + + @Override + public Class<? extends CompiledObjectDecorator> getDefaultDecoratorClass() { + return defaultDecoratorClass; + } + + @Override + public boolean isProfile() { + return profile; + } + + @Override + public boolean isGenerateHelp() { + return generateHelp; + } + + @Override + public String getHelpBrokerFQN() { + return helpBrokerFQN; + } + + @Override + public String getValidatorFactoryFQN() { + return validatorFactoryFQN; + } + + @Override + public String getEncoding() { + return encoding; + } + + @Override + public Map<String, CompiledObjectDecorator> getDecorators() { + if (decorators == null) { + decorators = new TreeMap<>(); + ClassLoader classloader = + Thread.currentThread().getContextClassLoader(); + if (log.isInfoEnabled()) { + log.info("with cl " + classloader); + } + + // load decorators + ServiceLoader<CompiledObjectDecorator> services = + ServiceLoader.load(CompiledObjectDecorator.class, + classloader); + for (CompiledObjectDecorator decorator : services) { + if (log.isInfoEnabled()) { + log.info("detected " + decorator); + } + decorators.put(decorator.getName(), decorator); + } + } + return decorators; + } + + @Override + public Map<String, JAXXCompilerFinalizer> getFinalizers() { + if (finalizers == null) { + finalizers = new TreeMap<>(); + + ClassLoader classloader = + Thread.currentThread().getContextClassLoader(); + if (log.isInfoEnabled()) { + log.info("with cl " + classloader); + } + + ServiceLoader<JAXXCompilerFinalizer> services = + ServiceLoader.load(JAXXCompilerFinalizer.class, + classloader); + for (JAXXCompilerFinalizer finalizer : services) { + if (log.isInfoEnabled()) { + log.info("detected " + finalizer); + } + finalizers.put(finalizer.getClass().getName(), finalizer); + } + } + return finalizers; + } + + @Override + public Map<String, Initializer> getInitializers() { + if (initializers == null) { + initializers = new TreeMap<>(); + ClassLoader classloader = + Thread.currentThread().getContextClassLoader(); + if (log.isInfoEnabled()) { + log.info("with cl " + classloader); + } + + ServiceLoader<Initializer> loader = + ServiceLoader.load(Initializer.class, classloader); + + for (Initializer initializer : loader) { + if (log.isInfoEnabled()) { + log.info("detected " + initializer); + } + initializers.put(initializer.getClass().getName(), initializer); + } + } + return initializers; + } + + @Override + public File getCommonCss() { + return commonCss; + } + + @Override + public String getCssExtension() { + return DEFAULT_CSS_EXTENSION; + } + + public void setCommonCss(File commonCss) { + this.commonCss = commonCss; + } + + @Override + public boolean isAutoRecurseInCss() { + return autoRecurseInCss; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString( + this, ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/EventHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/EventHandler.java new file mode 100644 index 0000000..9ae8cd1 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/EventHandler.java @@ -0,0 +1,86 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; + +public class EventHandler { + + private String eventId; + + private String objectCode; + + private ClassDescriptor listenerClass; + + private MethodDescriptor addMethod; + + private MethodDescriptor listenerMethod; + + private String javaCode; + + public EventHandler(String eventId, + String objectCode, + MethodDescriptor addMethod, + ClassDescriptor listenerClass, + MethodDescriptor listenerMethod, + String javaCode) { + this.eventId = eventId; + this.objectCode = objectCode; + this.addMethod = addMethod; + this.listenerClass = listenerClass; + this.listenerMethod = listenerMethod; + this.javaCode = javaCode; + } + + public String getEventId() { + return eventId; + } + + public String getObjectCode() { + return objectCode; + } + + public MethodDescriptor getAddMethod() { + return addMethod; + } + + public ClassDescriptor getListenerClass() { + return listenerClass; + } + + public MethodDescriptor getListenerMethod() { + return listenerMethod; + } + + public String getJavaCode() { + return javaCode; + } + + @Override + public String toString() { + return "EventHandler[" + eventId + ", " + + listenerClass.getName() + ", " + + objectCode + ", " + javaCode + "]"; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/I18nHelper.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/I18nHelper.java new file mode 100644 index 0000000..41253b8 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/I18nHelper.java @@ -0,0 +1,144 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler; + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.apache.commons.lang3.CharUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.i18n.I18n; + +import java.util.Arrays; +import java.util.List; + +/** + * I18n methods to add {@link I18n#t(String, Object...)} method on some attributes. + * + * Make sure to set an i18nable compiler to have his {@link CompilerConfiguration#isI18nable()} returning true. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class I18nHelper { + + protected static final Log log = LogFactory.getLog(I18nHelper.class); + + public static final List<String> I18N_ATTRIBUTES = Arrays.asList("text", "title", "toolTipText"); + + /** + * Test if we have an active i18n attribute (says an i18n attribute on a i18neable compiler). + * + * @param attributeName name of attribute to test + * @param compiler current used compiler (contains options) + * @return <code>true</code> if wa have an active i18n attribute, <code>false</code> otherwise. + */ + public static boolean isI18nableAttribute(String attributeName, JAXXCompiler compiler) { + return compiler.getConfiguration().isI18nable() && isI18nAttribute(attributeName); + } + + /** + * Test if we have an i18n attribute. + * + * @param attributeName name of attribute to test + * @return <code>true</code> if wa have an active i18n attribute, <code>false</code> otherwise. + */ + public static boolean isI18nAttribute(String attributeName) { + return I18N_ATTRIBUTES.contains(attributeName); + } + + /** + * Add the i18n on a attribute. + * + * Note: <b>Be ware : </b> no test is done here to ensure we are on a i18neable attribute for an i18nable compiler. + * + * Make sure with the method {@link I18nHelper#isI18nableAttribute(String, JAXXCompiler)} returns + * <code>true</code> before using this method. + * + * @param widgetId the id of the widget + * @param attributeName the name of the attribute + * @param attributeValueCode the value code of the attribute value + * @param compiler the current used compile + * @return the surrender i18n call if attribute name is match the + * attributeValueCode otherwise + */ + public static String addI18nInvocation(String widgetId, String attributeName, String attributeValueCode, JAXXCompiler compiler) { + + if (log.isDebugEnabled()) { + log.debug(" try i18n support for [" + widgetId + ":" + attributeName + "] : " + attributeValueCode); + } + boolean doWarn = false; + int indexOf = attributeValueCode.indexOf("t("); + if (indexOf > -1 && !attributeValueCode.contains(",")) { + if (indexOf == 0) { + doWarn = true; + } else { + + // make sure that the previous character is not alphabetical (means yet another method than t()) + char charBefore = attributeValueCode.charAt(indexOf - 1); + if (CharUtils.isAsciiAlphanumeric(charBefore)) { + + doWarn = false; + } else { + + //TODO tchemit-2014-08-24 Maybe could we do better ? + doWarn = true; + } + } + } + if (doWarn) { + compiler.reportWarning("\n\tjaxx supports i18n, no need to add explicit call to I18n.t for attribute '" + attributeName + "' in component '" + widgetId + "' : [" + attributeValueCode + "]"); + } else { + compiler.addImport("static " + I18n.class.getName() + ".t"); + attributeValueCode = "t(" + attributeValueCode + ")"; + } + + return attributeValueCode; + } + + /** + * Box a i18n key with code to be used as a i18n mnemonic. + * + * Note: <b>Be ware : </b> no test is done here to ensure we are on a + * i18neable attribute for an i18nable compiler. + * + * @param object the object to use + * @param attributeName the name of the attribute + * @param attributeValueCode the value code of the attribute value + * @param compiler the current used compile + * @return the surrender i18n call if attribute name is match the + * attributeValueCode otherwise + * @since 2.6.11 + */ + public static String addI18nMnemonicInvocation(CompiledObject object, + String attributeName, + String attributeValueCode, + JAXXCompiler compiler) { + String stringValue = I18nHelper.addI18nInvocation( + object.getId(), + attributeName, + attributeValueCode, + compiler); + compiler.addImport(SwingUtil.class.getName()); + return "{" + SwingUtil.class.getSimpleName() + + ".getFirstCharAt(" + stringValue + ",'Z')}"; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/IDHelper.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/IDHelper.java new file mode 100644 index 0000000..4730858 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/IDHelper.java @@ -0,0 +1,117 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +/** + * A usefull class to generate Ids. + * + * Created: 27 nov. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + */ +public class IDHelper { + /** + * Logger + */ + protected static final Log log = LogFactory.getLog(IDHelper.class); + + /** + * Counter by type + */ + protected final Map<String, Integer> autoGenIds = new TreeMap<>(); + + /** + * Maps of uniqued id for objects used in compiler + */ + protected final Map<Object, String> uniqueIds = new HashMap<>(); + + /** + * Optimized Counter + */ + protected int optimizedAutogenId = 0; + + /** + * Flag to use optimized id + */ + protected final boolean optimize; + + public IDHelper(boolean optimize) { + this.optimize = optimize; + } + + public String nextId(String name) { + + if (optimize) { + return "$" + Integer.toString(optimizedAutogenId++, 36); + } + + Integer integer = autoGenIds.get(name); + + if (integer == null) { + integer = 0; + } + name = name.substring(name.lastIndexOf(".") + 1); + String result = "$" + name + integer; + autoGenIds.put(name, ++integer); + if (log.isTraceEnabled()) { + log.trace("new id = " + result); + } + return result; + } + + public void revertId(String name) { + if (optimize) { + optimizedAutogenId--; + } else { + name = name.substring(name.lastIndexOf(".") + 1); + Integer integer = autoGenIds.get(name); + if (integer != null) { + autoGenIds.put(name, --integer); + } + } + } + + public String getUniqueId(Object object) { + String result = uniqueIds.get(object); + if (result == null) { + result = "$u" + uniqueIds.size(); + uniqueIds.put(object, result); + } + if (log.isTraceEnabled()) { + log.trace("new uniqueid = " + result); + } + return result; + } + + public void clear() { + autoGenIds.clear(); + uniqueIds.clear(); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXCompiler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXCompiler.java new file mode 100644 index 0000000..efbdc5b --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXCompiler.java @@ -0,0 +1,2139 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler; + +import org.nuiton.jaxx.compiler.binding.DataBindingHelper; +import org.nuiton.jaxx.compiler.css.StylesheetHelper; +import org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import org.nuiton.jaxx.compiler.java.JavaElementFactory; +import org.nuiton.jaxx.compiler.java.JavaField; +import org.nuiton.jaxx.compiler.java.JavaFile; +import org.nuiton.jaxx.compiler.java.JavaFileGenerator; +import org.nuiton.jaxx.compiler.java.JavaMethod; +import org.nuiton.jaxx.compiler.java.parser.ParseException; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.reflect.FieldDescriptor; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; +import org.nuiton.jaxx.compiler.script.ScriptManager; +import org.nuiton.jaxx.compiler.tags.DefaultObjectHandler; +import org.nuiton.jaxx.compiler.tags.TagHandler; +import org.nuiton.jaxx.compiler.tags.TagManager; +import org.nuiton.jaxx.runtime.ComponentDescriptor; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.JAXXObjectDescriptor; +import org.nuiton.jaxx.runtime.css.Rule; +import org.nuiton.jaxx.runtime.css.Stylesheet; +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.eugene.java.JavaGeneratorUtil; +import org.nuiton.eugene.java.extension.ImportsManager; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.AttributesImpl; +import org.xml.sax.helpers.XMLFilterImpl; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.ErrorListener; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXSource; +import java.awt.BorderLayout; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +/** + * Compiles a given {@link #jaxxFile} into a {@link #javaFile}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.0.0 + */ +public class JAXXCompiler { + + /** Logger */ + protected static final Log log = LogFactory.getLog(JAXXCompiler.class); + + /** + * True to throw exceptions when we encounter unresolvable classes, + * false to ignore. + * + * This is currently set to false until JAXX has full support for + * inner classes (including enumerations), because currently they don't + * always resolve (but will generally run without error anyway). + */ + public static boolean STRICT_CHECKS; + + + public static final String JAXX_NAMESPACE = + "http://www.jaxxframework.org/"; + + public static final String JAXX_INTERNAL_NAMESPACE = + "http://www.jaxxframework.org/internal"; + + /** Maximum length of an inlinable creation method. */ + public static final int INLINE_THRESHOLD = 300; + + /** Line separator cached value */ + protected static String lineSeparator = + System.getProperty("line.separator", "\n"); + + public static final String BORDER_LAYOUT_PREFIX = BorderLayout.class.getSimpleName() + "."; + + /** The unique object handler used in first pass */ + protected final DefaultObjectHandler firstPassClassTagHandler; + + /*------------------------------------------------------------------------*/ + /*-- compiler fields -----------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + /** flag to detect if an error occurs while compiling jaxx file */ + protected boolean failed; + + /** Object corresponding to the root tag in the document. */ + protected CompiledObject root; + + /** Contains strings of the form "javax.swing." */ + protected Set<String> importedPackages; + + /** Contains strings of the form "javax.swing.Timer" */ + protected Set<String> importedClasses; + + /** Keeps track of open components (components still having children added). */ + protected Stack<CompiledObject> openComponents; + + /** to generate ids */ + protected final IDHelper idHelper; + + /** Binding Util */ + protected final DataBindingHelper bindingHelper; + + /** table of symbols for this compiler */ + protected SymbolTable symbolTable; + + /** + * Base directory used for path resolution (normally the directory in + * which the .jaxx file resides). + */ + protected File baseDir; + + /** jaxx file being compiled. */ + protected File src; + + /** Parsed XML of src file. */ + protected Document document; + + /** Name of class being compiled. */ + protected String outputClassName; + + /** script manager */ + protected ScriptManager scriptManager; + + /** + * Combination of all stylesheets registered using + * {@link #registerStylesheet(Stylesheet)}. + */ + protected Stylesheet stylesheet; + + /** Contains all attributes defined inline on class tags. */ + protected List<Rule> inlineStyles; + + /** + * Maps objects (expressed in Java code) to event listener classes + * (e.g. MouseListener) to Lists of EventHandlers. The final list + * contains all event handlers of a particular type attached to a + * particular object (again, as represented by a Java expression). + */ + protected Map<String, Map<ClassDescriptor, List<EventHandler>>> eventHandlers; + + /** Map of event handler method names used in compiler */ + protected Map<EventHandler, String> eventHandlerMethodNames; + + /** + * ClassLoader which searches the user-specified class path in + * addition to the normal class path + */ + protected ClassLoader classLoader; + + /** + * A list of Runnables which will be run after the first compilation pass. + * + * This is primarily used to trigger the creation of CompiledObjects, + * which cannot be created during the first pass and must be created + * in document order. + */ + protected List<Runnable> initializers; + + /** + * extra interfaces which can by passed to root object via the + * 'implements' attribute + */ + private String[] extraInterfaces; + + /** a flag to generate a abstract class */ + private boolean abstractClass; + + /** the possible generic type of the class */ + private String genericType; + + /** the possible generic type of the super class */ + private String superGenericType; + + /** Extra code to be added to the instance initializer. */ + protected StringBuilder initializer; + + /** Extra code to be added at the end of the instance initializer. */ + protected StringBuilder lateInitializer; + + /** Extra code to be added to the class body. */ + protected StringBuilder bodyCode; + + /** true if a main() method has been declared in a script */ + protected boolean mainDeclared; + + /** the file to be generated */ + protected JavaFile javaFile; + + /** Used for error reporting purposes, so we can report the right line number. */ + protected Stack<Element> tagsBeingCompiled; + + /** Used for error reporting purposes, so we can report the right source file. */ + protected Stack<File> sourceFiles; + + /** + * Maps object ID strings to the objects themselves. + * + * These are created during the second compilation pass. + */ + protected Map<String, CompiledObject> objects; + + /** + * Maps objects to their ID strings. + * + * These are created during the second compilation pass. + */ + protected Map<CompiledObject, String> ids; + + /** default decodator to use if none specified */ + protected CompiledObjectDecorator defaultDecorator; + + /** + * engine which references this compiler + * (can be null if compiler is standalone) + */ + protected final JAXXEngine engine; + + protected final CompilerConfiguration defaultConfiguration = + new DefaultCompilerConfiguration(); + + protected final JAXXCompilerFile jaxxFile; + + /** + * Flag to know if jaxx file ident css was found, otherwise add it + * at the end of the second compile pass. + * + * @since 2.0.2 + */ + protected boolean identCssFound; + + /** + * A flag to know if SwingUtil msut be imported. + * + * @since 2.4 + * @deprecated since 2.4.1, will be removed in version 3.0, it is not a good + * idea to do special treatment for a particular class, to use SwingUtil, + * do like for other class : import it! + */ + @Deprecated + protected boolean needSwingUtil; + + public static final String[] EMPTY_STRING_ARRAY = new String[0]; + + public JAXXCompiler() { + this(null, null, null); + } + + /** + * Creates a new JAXXCompiler. + * + * @param engine engine which use the compiler (could be null if not attach to any engine) + * @param jaxxFile the file to compile + * @param defaultImports list of default imports to add to java files + */ + public JAXXCompiler(JAXXEngine engine, + JAXXCompilerFile jaxxFile, + List<String> defaultImports) { + this.engine = engine; + this.jaxxFile = jaxxFile; + + ids = new LinkedHashMap<>(); + objects = new LinkedHashMap<>(); + bodyCode = new StringBuilder(); + lateInitializer = new StringBuilder(); + initializer = new StringBuilder(); + tagsBeingCompiled = new Stack<>(); + initializers = new ArrayList<>(); + eventHandlerMethodNames = new HashMap<>(); + eventHandlers = + new HashMap<>(); + inlineStyles = new ArrayList<>(); + scriptManager = new ScriptManager(this); + symbolTable = new SymbolTable(); + openComponents = new Stack<>(); + importedPackages = new HashSet<>(); + importedClasses = new HashSet<>(); + sourceFiles = new Stack<>(); + if (jaxxFile == null) { + src = null; + baseDir = null; + outputClassName = null; + } else { + src = jaxxFile.getJaxxFile(); + baseDir = src.getParentFile(); + outputClassName = jaxxFile.getClassName(); + sourceFiles.push(src); + addImport(outputClassName.substring( + 0, outputClassName.lastIndexOf(".") + 1) + "*"); + } + + firstPassClassTagHandler = new DefaultObjectHandler( + ClassDescriptorHelper.getClassDescriptor(Object.class) + ); + bindingHelper = new DataBindingHelper(this); + + if (defaultImports != null) { + for (String defaultImport : defaultImports) { + addDefaultImport(defaultImport); + } + } + + if (engine != null) { + CompilerConfiguration configuration = engine.getConfiguration(); + // add extra imports from configuration + if (configuration.getExtraImports() != null) { + for (String extraImport : configuration.getExtraImports()) { + addImport(extraImport); + } + } + defaultDecorator = engine.getDecorator( + configuration.getDefaultDecoratorClass()); + if (defaultDecorator == null) { + throw new IllegalArgumentException( + "could not find default decorator : " + + configuration.getDefaultDecoratorClass() + ); + } + idHelper = new IDHelper(configuration.isOptimize()); + } else { + idHelper = new IDHelper(false); + } + } + + /*------------------------------------------------------------------------*/ + /*-- Initializer methods -------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public void runInitializers() { + for (Runnable runnable : initializers) { + if (log.isDebugEnabled()) { + log.debug(runnable); + } + try { + runnable.run(); + } catch (Exception e) { + //TC - 20081018 report error and quit + reportError(e.getMessage()); + return; + } + } + initializers.clear(); + } + + /** + * Registers a <code>Runnable</code> which will be executed after the first + * compilation pass is complete. + * + * @param r runnable to register + */ + public void registerInitializer(Runnable r) { + initializers.add(r); + } + + /*------------------------------------------------------------------------*/ + /*-- Compile methods -----------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public void compileFirstPass(final Element tag) throws IOException { + tagsBeingCompiled.push(tag); + + String namespace = tag.getNamespaceURI(); + String fullClassName; + String localName = tag.getLocalName(); + boolean namespacePrefix = tag.getPrefix() != null; + // resolve class tags into fully-qualified class name + if (namespace != null && namespace.endsWith("*")) { + String packageName = namespace.substring(0, namespace.length() - 1); + if (localName.startsWith(packageName)) { + // class name is fully-qualified already + fullClassName = TagManager.resolveClassName(localName, this); + } else { + // namespace not included in class name, probably need the + // namespace to resolve + fullClassName = TagManager.resolveClassName( + packageName + localName, this); + if (fullClassName == null && !namespacePrefix) { + // it was just a default namespace, try again without + // using the namespace + fullClassName = TagManager.resolveClassName(localName, this); + } + } + } else { + fullClassName = TagManager.resolveClassName(localName, this); + } + + if (fullClassName != null) { + // we are definitely dealing with a class tag + addDependencyClass(fullClassName); + namespace = fullClassName.substring( + 0, fullClassName.lastIndexOf(".") + 1) + "*"; + if (symbolTable.getSuperclassName() == null) { + symbolTable.setSuperclassName(fullClassName); + } + String id = tag.getAttribute(DefaultObjectHandler.ID_ATTRIBUTE); + MethodDescriptor methodDescriptor; + if (!id.isEmpty()) { + symbolTable.getClassTagIds().put(id, fullClassName); + if (tag.getAttributeNode(DefaultObjectHandler.JAVA_BEAN_ATTRIBUTE) != null) { + // add java bean support for this property + String capitalizeName = StringUtils.capitalize(id); + // add method + + methodDescriptor = new MethodDescriptor( + "get" + capitalizeName, + Modifier.PUBLIC, + fullClassName, + EMPTY_STRING_ARRAY, + getClassLoader() + ); + symbolTable.getScriptMethods().add(methodDescriptor); + if (Boolean.class.getName().equals(fullClassName)) { + methodDescriptor = new MethodDescriptor( + "is" + capitalizeName, + Modifier.PUBLIC, + fullClassName, + EMPTY_STRING_ARRAY, + getClassLoader() + ); + symbolTable.getScriptMethods().add(methodDescriptor); + } + methodDescriptor = new MethodDescriptor( + "set" + capitalizeName, + Modifier.PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + new String[]{fullClassName}, + getClassLoader() + ); + symbolTable.getScriptMethods().add(methodDescriptor); + } else { + // add simple get support + String capitalizeName = StringUtils.capitalize(id); + // add method + methodDescriptor = new MethodDescriptor( + "get" + capitalizeName, + Modifier.PUBLIC, + fullClassName, + EMPTY_STRING_ARRAY, + getClassLoader() + ); + symbolTable.getScriptMethods().add(methodDescriptor); + } + } + String interfacesStr = + tag.getAttribute(DefaultObjectHandler.IMPLEMENTS_ATTRIBUTE); + if (!interfacesStr.isEmpty()) { + // there is some interfaces to deal with + + + try { + String[] interfaces = + JavaGeneratorUtil.splitFqnList(interfacesStr, ','); + if (log.isDebugEnabled()) { + log.debug("detect interfaces : " + + Arrays.toString(interfaces)); + } + symbolTable.setInterfaces(interfaces); + } catch (Exception e) { + // the syntax is not valid (missed one >) + throw new CompilerException( + "Syntax error of interfaces " + + interfacesStr); + } +// StringTokenizer stk = new StringTokenizer(interfacesStr, ","); +// List<String> tmp = new ArrayList<String>(); +// while (stk.hasMoreTokens()) { +// String c = stk.nextToken(); +// if (c.contains("<") && !c.contains(">")) { +// // deal with a generic interface with more than one +// // parameter +// boolean done = false; +// while (stk.hasMoreTokens()) { +// +// String next = stk.nextToken(); +// if (!next.contains(">")) { +// // still a parameter of the generic type +// continue; +// } +// // ok find the ending token +// done = true; +// break; +// } +// if (!done) { +// // the syntax is not valid (missed one >) +// throw new CompilerException( +// "Syntax error of interfaces " + +// interfacesStr); +// } +// //c = c.substring(0, c.indexOf("<")); +// } +// tmp.add(c.trim()); +// } +// String[] interfaces = tmp.toArray(new String[tmp.size()]); +// if (log.isDebugEnabled()) { +// log.debug("detect interfaces : " + +// Arrays.toString(interfaces)); +// } +// symbolTable.setInterfaces(interfaces); + } + + } + // during the first pass, we can't create ClassDescriptors for JAXX + // files because they may not have been processed yet (and we can't + // wait until they have been processed because of circular + // dependencies). + // So we don't do any processing during the first pass which requires + // having a ClassDescriptor; here we determine whether we have a class + // tag or not (class tag namespaces end in "*") and use a generic + // handler if so. + // The real handler is used during the second pass. + TagHandler handler = namespace != null && namespace.endsWith("*") ? + firstPassClassTagHandler : + TagManager.getTagHandler(tag.getNamespaceURI(), + localName, + namespacePrefix, + this + ); + if (!firstPassClassTagHandler.equals(handler) && + handler instanceof DefaultObjectHandler) { + fullClassName = + ((DefaultObjectHandler) handler).getBeanClass().getName(); + handler = firstPassClassTagHandler; + } + if (firstPassClassTagHandler.equals(handler)) { + final String finalClassName = fullClassName; + + // register an initializer which will create the + // CompiledObject after pass 1 + + registerInitializer(new Runnable() { + + @Override + public void run() { + DefaultObjectHandler handler = + (DefaultObjectHandler) TagManager.getTagHandler( + null, + finalClassName, + JAXXCompiler.this + ); + if (handler == null) { + throw new CompilerException( + "Internal error: missing TagHandler for '" + + finalClassName + "'"); + } + handler.registerCompiledObject(tag, JAXXCompiler.this); + } + }); + } + if (handler == null) { + reportError("Could not find a Java class corresponding to: <" + + tag.getTagName() + ">"); + failed = true; + } else { + try { + handler.compileFirstPass(tag, this); + } catch (CompilerException e) { + reportError(e); + } + } + + Element finished = tagsBeingCompiled.pop(); + if (finished != tag) { + throw new IllegalStateException( + "internal error: just finished compiling " + tag + + ", but top of tagsBeingCompiled stack is " + finished); + } + } + + public void compileSecondPass(Element tag) throws IOException { + tagsBeingCompiled.push(tag); + + TagHandler handler = TagManager.getTagHandler( + tag.getNamespaceURI(), + tag.getLocalName(), + tag.getPrefix() != null, + this + ); + + if (handler == null) { + reportError("Could not find a Java class corresponding to: <" + + tag.getTagName() + ">"); + failed = true; + } else { + handler.compileSecondPass(tag, this); + } + + Element finished = tagsBeingCompiled.pop(); + if (!tag.equals(finished)) { + throw new RuntimeException( + "internal error: just finished compiling " + tag + + ", but top of tagsBeingCompiled stack is " + finished); + } + } + + public void compileFirstPass() throws IOException { + InputStream in = new FileInputStream(src); + try { + document = parseDocument(in); + + Element documentElement = document.getDocumentElement(); + + boolean addAutoHandlerUI = + getEngine().getConfiguration().isAddAutoHandlerUI(); + + String uiHandlerFullClassName; + + if (addAutoHandlerUI) { + + // try to find the + + uiHandlerFullClassName = getOutputClassName() + "Handler"; + ClassDescriptor uiHandlerClass = null; + try { + uiHandlerClass = ClassDescriptorHelper.getClassDescriptor(uiHandlerFullClassName, getClassLoader()); + if (uiHandlerClass != null && !ClassDescriptorHelper.isAssignableFrom(uiHandlerClass, UIHandler.class)) { + String isAbstractValue = documentElement.getAttribute("abstract"); + boolean isAbstract = isAbstractValue != null && "true".equals(isAbstractValue); + if (!isAbstract) { + reportWarning( + "Found a handler " + uiHandlerFullClassName + + " which does not implements " + UIHandler.class.getName()); + } + uiHandlerClass = null; + } + + } catch (ClassNotFoundException e) { + // not found + } + + if (uiHandlerClass == null) { + uiHandlerFullClassName = null; + } + } else { + + uiHandlerFullClassName = documentElement.getAttribute( + DefaultObjectHandler.HANDLER_ATTRIBUTE); + if (StringUtils.isNotBlank(uiHandlerFullClassName)) { + + // get his class descriptor + ClassDescriptor uiHandlerClass = null; + try { + uiHandlerClass = ClassDescriptorHelper.getClassDescriptor(uiHandlerFullClassName, getClassLoader()); + + // check if implements UIHandler + if (uiHandlerClass != null && !ClassDescriptorHelper.isAssignableFrom(uiHandlerClass, UIHandler.class)) { + reportError( + "Found a handler " + uiHandlerFullClassName + + " which does not implements " + UIHandler.class.getName()); + uiHandlerClass = null; + } + } catch (ClassNotFoundException e) { + reportError("Could not find type " + uiHandlerFullClassName); + } + if (uiHandlerClass == null) { + uiHandlerFullClassName = null; + } + } + } + + if (uiHandlerFullClassName != null) { + + setUiHandler(uiHandlerFullClassName); + } + + compileFirstPass(documentElement); + } catch (SAXParseException e) { + reportError(e.getLineNumber(), "Invalid XML: " + e.getMessage()); + } catch (SAXException e) { + reportError(null, "Error parsing XML document: " + e); + } finally { + in.close(); + } + } + + public void compileSecondPass() throws IOException { + if (!tagsBeingCompiled.isEmpty()) { + throw new RuntimeException( + "Internal error: starting pass two, but tagsBeingCompiled" + + " is not empty: " + tagsBeingCompiled); + } + + if (isUseHandler()) { + + String handler = getUiHandler(); + + boolean addField = true; + try { + + boolean superclassIsJAXXObject = isSuperClassAware(JAXXObject.class); + + if (superclassIsJAXXObject) { + + CompiledObject rootObject = getRootObject(); + ClassDescriptor rootObjectClass = rootObject.getObjectClass(); + // test if there is a super handler + try { + rootObjectClass.getDeclaredFieldDescriptor("handler"); + addField = false; + } catch (NoSuchFieldException e) { + + // no field handler found + } + } + + } catch (ClassNotFoundException e) { + throw new RuntimeException("Coul not find class ",e); + } + + JavaField field = JavaElementFactory.newField( + Modifier.PROTECTED, + handler, + DefaultObjectHandler.HANDLER_ATTRIBUTE, + !addField, + null); + + if (addField) { + + javaFile.addField(field, false); + + } else { + + // override getter + javaFile.addOverrideGetterMethod(field.getName(), + Modifier.PUBLIC, + field.getType(), + true); + } + + } + compileSecondPass(document.getDocumentElement()); + } + + /*------------------------------------------------------------------------*/ + /*-- CompiledObject methods ----------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public void openComponent(CompiledObject component) throws CompilerException { + openComponent(component, null); + } + + public void openComponent(CompiledObject component, + String constraints) throws CompilerException { + if (constraints != null) { + + // try to add the constraints class in imports + if (constraints.startsWith(BORDER_LAYOUT_PREFIX)) { + addImport(BorderLayout.class.getName()); + } + } + CompiledObject parent = getOpenComponent(); + openInvisibleComponent(component); + if (parent != null && !component.isOverride()) { + parent.addChild(component, constraints, this); + } + } + + public void openInvisibleComponent(CompiledObject component) { + if (!ids.containsKey(component)) { + registerCompiledObject(component); + } + openComponents.push(component); + } + + public CompiledObject getOpenComponent() { + if (openComponents.isEmpty()) { + return null; + } + return openComponents.peek(); + } + + public void closeComponent(CompiledObject component) { + if (component == null) { + throw new NullPointerException("can not close a null component"); + } + if (!component.equals(openComponents.pop())) { + throw new IllegalArgumentException( + "can only close the topmost open object"); + } + } + + public void registerCompiledObject(CompiledObject object) { +// assert engine.symbolTables.values().contains(symbolTable) : +// "attempting to register CompiledObject before pass 1 is complete"; + if (root == null) { + root = object; + } + + String id = object.getId(); + if (ids.containsKey(object)) { + reportError("object '" + object + + "' is already registered with id '" + + ids.get(object) + "', cannot re-register as '" + id + + "'" + ); + } + if (objects.containsKey(id) && !(objects.get(id) instanceof Element)) { + reportError("id '" + id + "' is already registered to component " + objects.get(id)); + } + objects.put(id, object); + ids.put(object, id); + if (object.getDecorator() == null) { + // use default decorator + object.setDecorator(defaultDecorator); + } + } + + public CompiledObject getCompiledObject(String id) { + runInitializers(); +// assert engine.symbolTables.values().contains(symbolTable) : +// "attempting to retrieve CompiledObject before pass 1 is complete"; + return objects.get(id); + } + + public boolean inlineCreation(CompiledObject object) { + return object.getId().startsWith("$") && + object.getInitializationCode(this).length() < INLINE_THRESHOLD; + } + + public void checkOverride(CompiledObject object) throws CompilerException { + String fieldName = object.getId(); + if (fieldName.startsWith("$")) { + return; + } + ClassDescriptor ancestor = root.getObjectClass(); + if (object.getObjectClass().equals(ancestor)) { + return; + } + while (ancestor != null) { + try { + FieldDescriptor f = + ancestor.getDeclaredFieldDescriptor(fieldName); + if (!f.getType().isAssignableFrom(object.getObjectClass())) { + reportError( + "attempting to redefine superclass member '" + + fieldName + "' as incompatible type (was " + + f.getType() + ", redefined as " + + object.getObjectClass() + ")" + ); + } + object.setOverride(true); + object.setOverrideType(f.getType()); + if (!getCanonicalName(f.getType()).equals(getCanonicalName(object))) { + + // types are not the same + String simpleType = + getImportedType(getCanonicalName(object)); + if (log.isDebugEnabled()) { + log.debug("Simple type for " + object.getId() + + " : " + getCanonicalName(object) + + " against : " + + getCanonicalName(f.getType())); + } + object.setSimpleType(simpleType); + } + break; + } catch (NoSuchFieldException e) { + if (log.isDebugEnabled()) { + log.debug(">>>>> could not find declared field [" + fieldName + "] in " + ancestor.getName()); + } + ancestor = ancestor.getSuperclass(); + } + } + } + + /*------------------------------------------------------------------------*/ + /*-- DataBinding methods -------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public DataBindingHelper getBindingHelper() { + return bindingHelper; + } + + public void registerEventHandler(EventHandler handler) { + String objectCode = handler.getObjectCode(); + Map<ClassDescriptor, List<EventHandler>> listeners = + eventHandlers.get(objectCode); + if (listeners == null) { + listeners = new HashMap<>(); + eventHandlers.put(objectCode, listeners); + } + ClassDescriptor listenerClass = handler.getListenerClass(); + List<EventHandler> handlerList = listeners.get(listenerClass); + if (handlerList == null) { + handlerList = new ArrayList<>(); + listeners.put(listenerClass, handlerList); + } + handlerList.add(handler); + } + + public String getEventHandlerMethodName(EventHandler handler) { + String result = eventHandlerMethodNames.get(handler); + if (result == null) { + if (getConfiguration().isOptimize()) { + result = "$ev" + eventHandlerMethodNames.size(); + } else { + //TC-20090309 must get the goal property from the event id + // to make possible inheritance + String id = handler.getEventId().substring( + 0, handler.getEventId().indexOf(".")); + + result = "do" + StringUtils.capitalize(handler.getListenerMethod().getName()) + "__on__" + id; + //TC-20091105 : check the method name is available + // using css can have multi methods with result name (see priority) + if (eventHandlerMethodNames.containsValue(result)) { + int index = 0; + String result2; + do { + result2 = result + "_" + index++; + + } while (eventHandlerMethodNames.containsValue(result2)); + result = result2; + } + } + eventHandlerMethodNames.put(handler, result); + } + return result; + } + + /*------------------------------------------------------------------------*/ + /*-- Script methods ------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public void addScriptField(FieldDescriptor field) { + symbolTable.getScriptFields().add(field); + } + + public void addScriptMethod(MethodDescriptor method) { + if (method.getName().equals("main") && + method.getParameterTypes().length == 1 && + method.getParameterTypes()[0].getName().equals("[Ljava.lang.String;")) { + setMainDeclared(true); + } + symbolTable.getScriptMethods().add(method); + } + + public void registerScript(String script) throws CompilerException { + registerScript(script, null); + } + + public void registerScript(String script, + File sourceFile) throws CompilerException { + if (sourceFile != null) { + sourceFiles.push(sourceFile); + } + script = script.trim(); + if (!"".equals(script) && !script.endsWith("}") && + !script.endsWith(";")) { + script += ";"; + } + scriptManager.registerScript(script); + + if (sourceFile != null) { + File pop = sourceFiles.pop(); + if (!sourceFile.equals(pop)) { + throw new RuntimeException( + "leaving registerScript(), but " + sourceFile + + " was not the top entry on the stack (found " + pop + + " instead)"); + } + } + } + + public String preprocessScript(String script) throws CompilerException { + return scriptManager.preprocessScript(script); + } + + /*------------------------------------------------------------------------*/ + /*-- StyleSheet methods --------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public boolean isIdentCssFound() { + return identCssFound; + } + + public void registerStyleSheetFile(File styleFile, boolean warnAutoCssImport) throws IOException { + if (!identCssFound) { + + // detects if the given css file is ident to jaxx file + File identCssFile = jaxxFile.getCssFile(); + + if (styleFile.equals(identCssFile) && identCssFile.exists()) { + + // ok found ident css file + identCssFound = true; + + if (warnAutoCssImport) { + + reportWarning("The css file " + styleFile + " can be automaticly imported since it is named as his jaxx file."); + + } + + } + + } + String content = loadFile(styleFile); + getSourceFiles().push(styleFile); + try { + Stylesheet style = StylesheetHelper.processStylesheet(content); + registerStylesheet(style); + } catch (CompilerException e) { + String message= "Css file content is not valid :" + styleFile; + if (e instanceof org.nuiton.jaxx.compiler.css.parser.ParseException) { + org.nuiton.jaxx.compiler.css.parser.ParseException parseException = (org.nuiton.jaxx.compiler.css.parser.ParseException) e; + + message += " (line: " + parseException.getLine() + " - col:" + parseException.getColumn() + ") "; + } + reportError(message, e); + } finally { + + // whatever could be result, must pop this source file + getSourceFiles().pop(); + } + } + + public void applyStylesheets() { + for (Object o : new ArrayList<>(objects.values())) { + CompiledObject object = (CompiledObject) o; + DefaultObjectHandler tagHandler = + TagManager.getTagHandler(object.getObjectClass()); + if (log.isDebugEnabled()) { + log.debug("will apply css on object " + object.getId() + + " from handler " + tagHandler); + } + tagHandler.applyStylesheets(object, this); + } + } + + public void registerStylesheet(Stylesheet stylesheet) { + if (this.stylesheet == null) { + this.stylesheet = stylesheet; + } else { + this.stylesheet.add(stylesheet.getRules()); + } + } + + public void addInlineStyle(CompiledObject object, + String propertyName, + boolean dataBinding) { + Rule style = StylesheetHelper.inlineAttribute( + object, + propertyName, + dataBinding + ); + inlineStyles.add(style); + } + + /*------------------------------------------------------------------------*/ + /*-- Report methods ------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public void reportWarning(String warning) { + Element currentTag = null; + if (!tagsBeingCompiled.isEmpty()) { + currentTag = tagsBeingCompiled.peek(); + } + reportWarning(currentTag, warning, 0); + } + + public void reportWarning(Element tag, String warning, int lineOffset) { + String lineNumber = null; + if (tag != null) { + String lineAttr = + tag.getAttributeNS(JAXX_INTERNAL_NAMESPACE, "line"); + if (lineAttr.length() > 0) { + lineNumber = lineAttr; + } + } + File srcFile = sourceFiles.peek(); + try { + srcFile = srcFile.getCanonicalFile(); + } catch (IOException e) { + // ignore ? + } + StringBuilder buffer = new StringBuilder(); + buffer.append(srcFile); + if (lineNumber != null) { + buffer.append(":"); + buffer.append(sourceFiles.size() == 1 ? + Integer.parseInt(lineNumber) + lineOffset : + lineOffset + 1 + ); + } + buffer.append(getLineSeparator()).append(warning.trim()); + if (engine != null) { + engine.addWarning(buffer.toString()); + } else { + System.err.println(buffer.toString()); + } + } + + public void reportError(String error) { + Element currentTag = null; + if (!tagsBeingCompiled.isEmpty()) { + currentTag = tagsBeingCompiled.peek(); + } + reportError(currentTag, error); + } + + public void reportError(CompilerException ex) { + reportError(null, ex); + } + + public void reportError(String extraMessage, CompilerException ex) { + String message = ex.getMessage(); + if (UnsupportedAttributeException.class.equals(ex.getClass()) || + UnsupportedTagException.class.equals(ex.getClass())) { + String exceptionName = ex.getClass().getName(); + message = exceptionName.substring( + exceptionName.lastIndexOf(".") + 1) + ": " + message; + } + int lineOffset; + if (ex instanceof ParseException) { + lineOffset = Math.max(0, ((ParseException) ex).getLine() - 1); + } else { + lineOffset = 0; + } + Element currentTag = null; + if (!tagsBeingCompiled.isEmpty()) { + currentTag = tagsBeingCompiled.peek(); + } + reportError(currentTag, extraMessage != null ? + extraMessage + message : + message, lineOffset + ); + } + + public void reportError(Element tag, String error) { + reportError(tag, error, 0); + } + + public void reportError(Element tag, String error, int lineOffset) { + int lineNumber = 0; + if (tag != null) { + String lineAttr = + tag.getAttributeNS(JAXX_INTERNAL_NAMESPACE, "line"); + if (lineAttr.length() > 0) { + lineNumber = Integer.parseInt(lineAttr); + } + } + lineNumber = Math.max(lineNumber, 1) + lineOffset; + reportError(lineNumber, error); + } + + public void reportError(int lineNumber, String error) { + File errorFile = sourceFiles.isEmpty() ? null : sourceFiles.peek(); + try { + if (errorFile != null) { + errorFile = errorFile.getCanonicalFile(); + } + } catch (IOException e) { + // ignore ? + } + StringBuilder buffer = new StringBuilder(); + buffer.append(errorFile != null ? errorFile.getPath() : + "<unknown source>"); + if (lineNumber > 0) { + buffer.append(":").append(lineNumber); + } + buffer.append(getLineSeparator()).append(": ").append(error); + if (engine != null) { + engine.addError(buffer.toString()); + } else { + System.err.println(buffer.toString()); + } + failed = true; + } + + /*------------------------------------------------------------------------*/ + /*-- Getter methods ------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public Map<String, CompiledObject> getObjects() { + return objects; + } + + public Map<String, Map<ClassDescriptor, List<EventHandler>>> getEventHandlers() { + return eventHandlers; + } + + public CompilerConfiguration getConfiguration() { + JAXXEngine engine = getEngine(); + if (engine == null) { + return defaultConfiguration; + } + return engine.getConfiguration(); + } + + public String getOutputClassName() { + return outputClassName; + } + + public File getBaseDir() { + return baseDir; + } + + public Set<String> getImportedClasses() { + return importedClasses; + } + + public Set<String> getImportedPackages() { + return importedPackages; + } + + public Iterator<CompiledObject> getObjectCreationOrder() { + return objects.values().iterator(); + } + + public CompiledObject getRootObject() { + return root; + } + + public Stack<File> getSourceFiles() { + return sourceFiles; + } + + public ScriptManager getScriptManager() { + return scriptManager; + } + + public SymbolTable getSymbolTable() { + return symbolTable; + } + + public Stylesheet getStylesheet() { + Stylesheet merged = new Stylesheet(); + if (stylesheet != null) { + merged.add(stylesheet.getRules()); + } + merged.add(inlineStyles.toArray(new Rule[inlineStyles.size()])); + return merged; + } + + public FieldDescriptor[] getScriptFields() { + List<FieldDescriptor> scriptFields = symbolTable.getScriptFields(); + return scriptFields.toArray( + new FieldDescriptor[scriptFields.size()]); + } + + public FieldDescriptor getScriptField(String fieldName) { + for (FieldDescriptor f : symbolTable.getScriptFields()) { + if (fieldName.equals(f.getName())) { + return f; + } + } + return null; + } + + public MethodDescriptor[] getScriptMethods() { + List<MethodDescriptor> scriptMethods = symbolTable.getScriptMethods(); + return scriptMethods.toArray( + new MethodDescriptor[scriptMethods.size()]); + } + + public MethodDescriptor getScriptMethod(String methodName) { + for (MethodDescriptor m : symbolTable.getScriptMethods()) { + if (methodName.equals(m.getName())) { + return m; + } + } + return null; + } + + public boolean isFailed() { + return failed; + } + + public IDHelper getIdHelper() { + return idHelper; + } + + /** + * Returns a <code>ClassLoader</code> which searches the user-specified + * class path in addition to the normal system class path. + * + * @return <code>ClassLoader</code> to use while resolving class references + */ + public ClassLoader getClassLoader() { + if (classLoader == null) { + CompilerConfiguration configuration = getConfiguration(); + if (configuration.getClassLoader() != null) { + classLoader = configuration.getClassLoader(); + } else { + throw new NullPointerException( + "compiler configuration requires a classLoader! :\n" + + configuration); + } + } + + return classLoader; + } + + /** + * Checks if the super class of the mirrored javaFile is aware of the + * iven {@code type}. + * + * <strong>Note:</strong> If no super-class exist, then returns + * {@code false}. + * + * @param type the type to check against super class + * @return {@code true} if super class exists and is assignable against the + * given type, {@code false} otherwise + * @throws ClassNotFoundException if could not find class descriptor for + * super-class + */ + public boolean isSuperClassAware(Class<?> type) throws ClassNotFoundException { + ClassDescriptor superClass = root.getObjectClass(); + if (superClass == null) { + + // no super class, not awre of anything + return false; + } + + return ClassDescriptorHelper.isAssignableFrom(superClass, + type); + } + + public JAXXObjectDescriptor getJAXXObjectDescriptor() { + runInitializers(); + CompiledObject[] components = new ArrayList<>( + objects.values()).toArray(new CompiledObject[objects.size()]); + + assert initializers.isEmpty() : + "there are pending initializers remaining"; + assert root != null : "root object has not been defined"; + assert Arrays.asList(components).contains(root) : + "root object is not registered"; + ComponentDescriptor[] descriptors = + new ComponentDescriptor[components.length]; + // as we print, sort the array so that component's parents are always + // before the components themselves + for (int i = 0; i < components.length; i++) { + CompiledObject parent = components[i].getParent(); + while (parent != null) { + boolean found = false; + for (int j = i + 1; j < components.length; j++) { + // found parent after component, swap them + if (components[j] == parent) { + components[j] = components[i]; + components[i] = parent; + found = true; + break; + } + } + if (!found) { + break; + } + parent = components[i].getParent(); + } + int parentIndex = -1; + if (parent != null) { + for (int j = 0; j < i; j++) { + if (components[j].equals(parent)) { + parentIndex = j; + break; + } + } + } + descriptors[i] = new ComponentDescriptor( + components[i].getId(), + components[i] == root ? outputClassName : components[i].getObjectClass().getName(), + components[i].getStyleClass(), + parentIndex != -1 ? descriptors[parentIndex] : null); + } + + Stylesheet css = getStylesheet(); + if (css == null) { + css = new Stylesheet(); + } + + return new JAXXObjectDescriptor(descriptors, css); + } + + /*------------------------------------------------------------------------*/ + /*-- Buffer --------------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public StringBuilder getInitializer() { + return initializer; + } + + public StringBuilder getLateInitializer() { + return lateInitializer; + } + + public StringBuilder getBodyCode() { + return bodyCode; + } + + + public boolean isMainDeclared() { + return mainDeclared; + } + + public void setMainDeclared(boolean mainDeclared) { + this.mainDeclared = mainDeclared; + } + + public void appendInitializerCode(String code) { + initializer.append(code); + } + + public void appendBodyCode(String code) { + bodyCode.append(code); + } + + public void appendLateInitializer(String code) { + lateInitializer.append(code); + } + + public boolean hasMethod(String methodName) { + for (JavaMethod method : getJavaFile().getMethods()) { + if (methodName.equals(method.getName())) { + return true; + } + } + return false; + } + + /*------------------------------------------------------------------------*/ + /*-- Other methods -------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public void addImport(Class<?> clazz) { + addImport(clazz.getName()); + } + + public void addImport(String text) { + if (text.endsWith("*")) { + importedPackages.add(text.substring(0, text.length() - 1)); + } else { + importedClasses.add(text); + } + + if (!text.equals("*")) { + getJavaFile().addImport(text); + } + } + + protected void addDefaultImport(String text) { + if (text.endsWith("*")) { + importedPackages.add(text.substring(0, text.length() - 1)); + } else { + importedClasses.add(text); + } + } + + public void addDependencyClass(String className) { + + if (engine.containsJaxxFileClassName(className)) { + + // already registred in engine + return; + } + + // register the jaxx file into the engine + + URL jaxxURL = ClassDescriptorHelper.getURL(getClassLoader(), className, "jaxx"); + + if (jaxxURL == null) { + + // not a jaxx file, can quit now + return; + } + + if (!engine.isCompileFirstPassTask()) { + throw new IllegalStateException( + "Internal error: adding dependency class " + + className + " during second compilation pass"); + } + + //FIXME tchemit 20100518 Must unify this with ClassDescriptorHelper to use the less costless resource + if (jaxxURL.toString().startsWith("file:")) { + File jaxxFile = URLtoFile(jaxxURL); + try { + jaxxFile = jaxxFile.getCanonicalFile(); + } catch (IOException ex) { + // ignore ? (at least log it...) + log.error(ex); + } + String jaxxFileName = + className.substring(className.lastIndexOf(".") + 1) + + ".jaxx"; + + assert jaxxFile.getName().equalsIgnoreCase(jaxxFileName) : + "expecting file name to match " + + className + ", but found " + jaxxFile.getName(); + if (jaxxFile.getName().equals(jaxxFileName)) { + engine.addFileToCompile(jaxxFile, className); + } + } + } + + /** + * Loads the given file and returns its content. + * + * <b>Note:</b> If any errors encounters, then report an error in the + * compiler and returns an empty string. + * + * @param file the file to load + * @return the content of the file or empty string if something was wrong + */ + public String loadFile(File file) { + if (!file.exists()) { + reportError("Could not found file " + file); + return ""; + } + try { + FileReader in = new FileReader(file); + try { + StringWriter styleBuffer = new StringWriter(); + char[] readBuffer = new char[2048]; + int c; + while ((c = in.read(readBuffer)) > 0) { + styleBuffer.write(readBuffer, 0, c); + } + return styleBuffer.toString(); + } finally { + in.close(); + } + } catch (IOException e) { + reportError("Could not read file " + file + " for reason " + + e.getMessage()); + return ""; + } + } + + /** + * Verifies that a snippet of Java code parses correctly. + * + * A warning is generated if the string has enclosing curly braces. + * + * @param javaCode the Java code snippet to test + * @return a "cooked" version of the string which has enclosing curly + * braces removed. + * @throws CompilerException if the code cannot be parsed + */ + public String checkJavaCode(String javaCode) { + javaCode = scriptManager.trimScript(javaCode); + scriptManager.checkParse(javaCode); + return javaCode; + } + + /** + * Check that a reference exists in symbol table on second compil pass + * + * @param tag the current tag + * @param reference the required reference + * @param strict flag to report an error if reference was not found + * @param attribute (if not null reference the attribute where is defined + * the reference) + * @return <code>true</code> if reference was found, <code>false</code> + * otherwise and add an error in compiler + */ + public boolean checkReference(Element tag, + String reference, + boolean strict, + String attribute) { + String component = getSymbolTable().getClassTagIds().get(reference); + if (component == null) { + if (strict) { + String msg; + if (attribute != null) { + msg = "tag '" + tag.getLocalName() + + "' could not find the reference '" + reference + + "' on attribute [" + attribute + "]"; + } else { + msg = "tag '" + tag.getLocalName() + + "' could not find the reference '" + reference + "'"; + } + reportError(msg); + } + return false; + } + return true; + } + + public String getAutoId(String name) { + return idHelper.nextId(name); + } + + public String getUniqueId(Object object) { + return idHelper.getUniqueId(object); + } + + public void setExtraInterfaces(String[] extraInterfaces) { + this.extraInterfaces = extraInterfaces; + } + + public String[] getExtraInterfaces() { + return extraInterfaces; + } + + public boolean isAbstractClass() { + return abstractClass; + } + + public void setAbstractClass(boolean abstractClass) { + this.abstractClass = abstractClass; + } + + public String getGenericType() { + return genericType; + } + + public void setGenericType(String genericType) { + this.genericType = genericType; + } + + public String getSuperGenericType() { + return superGenericType; + } + + public void setSuperGenericType(String superGenericType) { + this.superGenericType = superGenericType; + } + + public void addSimpleField(JavaField javaField) { + getJavaFile().addSimpleField(javaField); + } + + public JavaFile getJavaFile() { + if (javaFile == null) { + String outputClassName = getOutputClassName(); + if (outputClassName == null) { + javaFile = JavaElementFactory.newFile(0, ""); + } else { + int dotPos = outputClassName.lastIndexOf("."); + String packageName = dotPos != -1 ? + outputClassName.substring(0, dotPos) : null; + String simpleClassName = outputClassName.substring(dotPos + 1); + + javaFile = JavaElementFactory.newFile( + Modifier.PUBLIC, + packageName + "." + simpleClassName); + } + } + return javaFile; + } + + public void preFinalizeCompiler() throws Exception { + + } + + public void finalizeCompiler() throws Exception { + + int dotPos = getOutputClassName().lastIndexOf("."); + String packageName = dotPos != -1 ? + getOutputClassName().substring(0, dotPos) : null; + String simpleClassName = getOutputClassName().substring(dotPos + 1); + CompiledObject compiledObject = getRootObject(); + + String genericType = getGenericType(); + if (StringUtils.isNotEmpty(genericType)) { + + // add the generic type to the root object + + // generictype can be on form E extends XXX + //keep only the first thing... + StringBuilder sb = new StringBuilder(); + String[] allTypes = JavaGeneratorUtil.splitFqnList(genericType, ','); + for (String type : allTypes) { + int anExtends = type.indexOf("extends"); + if (anExtends > -1) { + type = type.substring(0, anExtends - 1).trim(); + } + sb.append(", ").append(type); + } + String finalType; + if (allTypes.length > 0) { + finalType = sb.substring(2); + } else { + finalType = sb.toString(); + } + compiledObject.setGenericTypes(finalType); + } + // finalize all objects via their decorator + + for (CompiledObject object : getObjects().values()) { + CompiledObjectDecorator decorator = object.getDecorator(); + decorator.finalizeCompiler(this, + root, + object, + javaFile, + packageName, + simpleClassName, + getOutputClassName()); + } + + // obtain list of finalizers to apply + + List<JAXXCompilerFinalizer> realFinalizers = + new ArrayList<>(); + for (JAXXCompilerFinalizer finalizer : + getConfiguration().getFinalizers().values()) { + if (finalizer.accept(this)) { + realFinalizers.add(finalizer); + } + } + + // call the finalizers finalizeCompiler method + + for (JAXXCompilerFinalizer finalizer : realFinalizers) { + // check if finalizer can be apply of this compiler + if (finalizer.accept(this)) { + finalizer.finalizeCompiler(compiledObject, + this, + javaFile, + packageName, + simpleClassName + ); + } + } + + // call the compiled objects finalizeCompiler method + + for (CompiledObject object : getObjects().values()) { + object.finalizeCompiler(this); + } + + // compile bindings + + getBindingHelper().finalizeBindings(); + + // call the finalizers prepareJavaFile method + + for (JAXXCompilerFinalizer finalizer : realFinalizers) { + finalizer.prepareJavaFile(compiledObject, + this, + javaFile, + packageName, + simpleClassName + ); + } + } + + public void generate(JavaFileGenerator generator) throws IOException { + File dest; + String fqn = getOutputClassName(); + if (getConfiguration().getTargetDirectory() != null) { + dest = new File(getConfiguration().getTargetDirectory(), + fqn.replace('.', File.separatorChar) + ".java" + ); + } else { + dest = new File(getBaseDir(), + fqn.substring(fqn.lastIndexOf(".") + 1) + ".java" + ); + } + + // make sure directory exists + File parentFile = dest.getParentFile(); + if (parentFile == null) { + throw new IOException("No parent file for " + dest); + } + if (!parentFile.exists() && !parentFile.mkdirs()) { + throw new IOException("Could not create directory " + parentFile); + } + if (dest.exists() && !dest.setLastModified(System.currentTimeMillis())) { + log.warn("could not touch file " + dest); + } + PrintWriter out = new PrintWriter(new FileWriter(dest)); + try { + generator.generateFile(javaFile, out); + } finally { + out.close(); + } + } + + /** + * Returns the system line separator string. + * + * @return the string used to separate lines + */ + public static String getLineSeparator() { + return lineSeparator; + } + + // 1.5 adds getCanonicalName; unfortunately we can't depend on 1.5 features yet + + public static String getCanonicalName(Class<?> clazz) { + if (clazz.isArray()) { + String canonicalName = getCanonicalName(clazz.getComponentType()); + if (canonicalName != null) { + return canonicalName + "[]"; + } + return null; + } + return clazz.getName().replace('$', '.'); + } + + public static String getCanonicalName(ClassDescriptor clazz) { + if (clazz.isArray()) { + String canonicalName = getCanonicalName(clazz.getComponentType()); + if (canonicalName != null) { + return canonicalName + "[]"; + } + return null; + } + return clazz.getName().replace('$', '.'); + } + + public static String getCanonicalName(CompiledObject compiled) { + ClassDescriptor clazz = compiled.getObjectClass(); + if (clazz.isArray()) { + String canonicalName = getCanonicalName(clazz.getComponentType()); + if (canonicalName != null) { + if (compiled.getGenericTypesLength() > 0) { + canonicalName += compiled.getGenericTypes(); + } + return canonicalName + "[]"; + } + return null; + } + + String canonicalName = clazz.getName().replace('$', '.'); + if (compiled.getGenericTypesLength() > 0) { + canonicalName += compiled.getGenericTypes(); + } + return canonicalName; + } + + /** + * Escapes a string using standard Java escape sequences, generally in + * preparation to including it in a string literal in a compiled Java file. + * + * @param raw the raw string to be escape + * @return a string in which all 'dangerous' characters have been replaced + * by equivalent Java escape sequences + */ + public static String escapeJavaString(String raw) { + StringBuilder out = new StringBuilder(raw); + for (int i = 0; i < out.length(); i++) { + char c = out.charAt(i); + if (c == '\\' || c == '"') { + out.insert(i, '\\'); + i++; + } else if (c == '\n') { + out.replace(i, i + 1, "\\n"); + i++; + } else if (c == '\r') { + out.replace(i, i + 1, "\\r"); + i++; + } else if (c < 32 || c > 127) { + String value = Integer.toString((int) c, 16); + while (value.length() < 4) { + value = "0" + value; + } + out.replace(i, i + 1, "\\u" + value); + i += 5; + } + } + return out.toString(); + } + + public static File URLtoFile(URL url) { + return URLtoFile(url.toString()); + } + + public static File URLtoFile(String urlString) { + if (!urlString.startsWith("file:")) { + throw new IllegalArgumentException("url must start with 'file:'"); + } + urlString = urlString.substring("file:".length()); + if (urlString.startsWith("/") && + System.getProperty("os.name").startsWith("Windows")) { + urlString = urlString.substring(1); + } + try { + return new File(URLDecoder.decode( + urlString.replace('/', File.separatorChar), "utf-8")); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + public static SAXParser getSAXParser() { + try { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setNamespaceAware(true); + SAXParser parser; + parser = factory.newSAXParser(); + return parser; + } catch (SAXException e) { + throw new RuntimeException(e); + } catch (ParserConfigurationException e) { + throw new RuntimeException(e); + } + } + + public static Document parseDocument(InputStream in) throws IOException, SAXException { + try { + TransformerFactory factory = TransformerFactory.newInstance(); + Transformer transformer = factory.newTransformer(); + transformer.setErrorListener(new ErrorListener() { + + @Override + public void warning( + TransformerException ex) throws TransformerException { + throw ex; + } + + @Override + public void error( + TransformerException ex) throws TransformerException { + throw ex; + } + + @Override + public void fatalError( + TransformerException ex) throws TransformerException { + throw ex; + } + }); + + DOMResult result = new DOMResult(); + transformer.transform( + new SAXSource(new XMLFilterImpl(getSAXParser().getXMLReader()) { + + Locator locator; + + @Override + public void setDocumentLocator(Locator locator) { + this.locator = locator; + } + + @Override + public void startElement(String uri, + String localName, + String qName, + Attributes atts) throws SAXException { + AttributesImpl resultAtts = new AttributesImpl(atts); + resultAtts.addAttribute( + JAXX_INTERNAL_NAMESPACE, + "line", + "internal:line", + "CDATA", + String.valueOf(locator.getLineNumber()) + ); + getContentHandler().startElement(uri, + localName, + qName, + resultAtts + ); + } + }, new InputSource(in)), result); + return (Document) result.getNode(); + } catch (TransformerConfigurationException e) { + throw new RuntimeException(e); + } catch (TransformerException e) { + Throwable ex = e; + while (ex.getCause() != null) { + ex = ex.getCause(); + } + if (ex instanceof IOException) { + throw (IOException) ex; + } + if (ex instanceof SAXException) { + throw (SAXException) ex; + } + if (ex instanceof RuntimeException) { + throw (RuntimeException) ex; + } + throw new RuntimeException(ex); + } + } + + public JAXXEngine getEngine() { + return engine; + } + + public void clear() { + idHelper.clear(); + bindingHelper.clear(); + objects.clear(); + ids.clear(); + if (symbolTable != null) { + symbolTable.clear(); + } + } + +// public void setIdentCssFound(boolean identCssFound) { +// this.identCssFound = identCssFound; +// } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + /** + * Try to import the given type into the underlying java file of this compiler. + * + * If import can not be done, will then returns the fully qualified name of + * the type. + * + * @param type the type to simplify + * @return the simplify type or the fqn if type could not be imported for the underlying java file. + * @since 2.4.1 + */ + public String getImportedType(Class<?> type) { + return getJavaFile().getImportedType(type); + } + + /** + * Try to import the given type into the underlying java file of this compiler. + * + * If import can not be done, will then returns the fully qualified name of + * the type. + * + * @param type the fqn of the type to simplify + * @return the simplify type or the fqn if type could not be imported for the underlying java file. + * @since 2.4.1 + */ + public String getImportedType(String type) { + return getJavaFile().getImportedType(type); + } + + public String getImportedTypeForSimpleName(String type) { + String suffix = "." + type; + String result = null; + for (String importedClass : getImportedClasses()) { + if (importedClass.endsWith(suffix)) { + result = importedClass; + break; + } + } + return result; + } + + /** + * @return the javafile import manager + * @since 2.4 + * @deprecated since 2.4.1, will be removed in version 3.0 : do not want + * to expose eugene export manager in rest of api, this is purpose of + * JavaFile only + */ + @Deprecated + public ImportsManager getImportManager() { + return getJavaFile().getImportManager(); + } + + /** + * @since 2.4 + * @deprecated since 2.4.1, will be removed in version 3.0, has no effect do not use it... + */ + @Deprecated + public boolean isNeedSwingUtil() { + return needSwingUtil; + } + + /** + * @since 2.4 + * @deprecated since 2.4.1, will be removed in version 3.0, has no effect do not use it... + */ + @Deprecated + public void setNeedSwingUtil(boolean needSwingUtil) { + this.needSwingUtil = needSwingUtil; + } + + public boolean containsScriptField(String fieldName) { + FieldDescriptor[] scriptFields = getScriptFields(); + for (FieldDescriptor f : scriptFields) { + if (fieldName.equals(f.getName())) { + return true; + } + } + return false; + } + + protected String uiHandler; + + public String getUiHandler() { + return uiHandler; + } + + public void setUiHandler(String uiHandler) { + this.uiHandler = uiHandler; + } + + public boolean isUseHandler() { + return StringUtils.isNotBlank(uiHandler); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXCompilerFile.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXCompilerFile.java new file mode 100644 index 0000000..8ea5beb --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXCompilerFile.java @@ -0,0 +1,204 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.FileUtil; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; + +/** + * Represents a file to be treated by the {@link JAXXCompiler}. + * + * It contains informations about jaxx file, ident css, class name,... + * + * <b>Note:</b> This class will be more used in next version (will have the + * compiler it-self, symbols table,...). + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class JAXXCompilerFile { + + /** Logger */ + private static final Log log = LogFactory.getLog(JAXXCompilerFile.class); + + /** root directory of the source roots. */ + protected final File basedir; + + /** relative path from {@link #basedir} to {@link #jaxxFile}. */ + private final String relativePath; + + /** location of the jaxx file */ + protected File jaxxFile; + + /** location of the ident css file */ + protected File cssFile; + + /** full qualified name of the jaxx file class */ + protected String className; + + /** compiler associated to the file */ + protected JAXXCompiler compiler; + + /** + * Css file extension. + * + * @see CompilerConfiguration#getCssExtension() + */ + protected final String cssExtension; + + public JAXXCompilerFile(File basedir, File jaxxFile, String cssExtension) { + this.basedir = basedir; + this.jaxxFile = jaxxFile; + this.cssExtension = cssExtension; + String absolutePath = jaxxFile.getAbsolutePath(); + String baseAbsolutePath = basedir.getAbsolutePath(); + if (!absolutePath.startsWith(baseAbsolutePath)) { + throw new IllegalStateException( + "Jaxx file " + jaxxFile + " is not in basedir " + basedir); + } + + relativePath = absolutePath.substring(baseAbsolutePath.length() + 1); + if (log.isDebugEnabled()) { + log.debug("relativePath = " + relativePath); + } + } + + public JAXXCompilerFile(File jaxxFile, String className, String cssExtension) { + + this.jaxxFile = jaxxFile; + this.className = className; + this.cssExtension = cssExtension; + + String extension = FileUtil.extension(jaxxFile); + String[] paths = className.split("\\."); + File basedir = jaxxFile; + for (int i = paths.length - 1; i > -1; i--) { + if (basedir == null) { + throw new IllegalStateException("Could not find base dir for " + jaxxFile + " according to fqn " + className); + } + + String path = paths[i]; + if (basedir.equals(jaxxFile)) { + // first in loop + path += "." + extension; + } + + // check path = base filename + if (!path.equals(basedir.getName())) { + throw new IllegalStateException("Should have found directory " + path + ", but was " + basedir.getName()); + } + + basedir = basedir.getParentFile(); + } + + if (log.isDebugEnabled()) { + log.debug("basedir = " + basedir); + } + + // must guess the base directory and relative path + + String relativePath = jaxxFile.getAbsolutePath().substring(basedir.getAbsolutePath().length() + 1); + + if (log.isDebugEnabled()) { + log.debug("relative path = " + relativePath); + } + + this.basedir = basedir; + this.relativePath = relativePath; + } + + public File getBasedir() { + return basedir; + } + + public String getRelativePath() { + return relativePath; + } + + public JAXXCompiler getCompiler() { + return compiler; + } + +// public SymbolTable getSymbolTable() { +// return compiler==null?null:compiler.getSymbolTable(); +// } + + public File getJaxxFile() { + if (jaxxFile == null) { + jaxxFile = new File(basedir, relativePath); + } + return jaxxFile; + } + + public URL getJAXXFileURL() { + File file = getJaxxFile(); + try { + return file.toURI().toURL(); + } catch (MalformedURLException e) { + throw new IllegalStateException("Url of the jaxx file is malformed... " + file); + } + } + + public File getCssFile() { + if (cssFile == null) { + File file = getJaxxFile(); + String extension = FileUtil.extension(file); + String fileName = file.getName(); + int length = fileName.length() - extension.length(); + String identCssFilename = fileName.substring(0, length) + cssExtension; + cssFile = new File(file.getParentFile(), identCssFilename); + } + return cssFile; + } + + public String getClassName() { + if (className == null) { + + className = relativePath.substring(0, relativePath.lastIndexOf(".")); + className = className.replace(File.separatorChar, '.'); + className = className.replace('/', '.'); + className = className.replace('\\', '.'); + className = className.replace(':', '.'); + + } + return className; + } + + public void clear() { + if (compiler != null) { + compiler.clear(); + } + } + +// public void setSymbolTable(SymbolTable symbolTable) { +// this.symbolTable = symbolTable; +// } + + public void setCompiler(JAXXCompiler compiler) { + this.compiler = compiler; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXEngine.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXEngine.java new file mode 100644 index 0000000..ed141ab --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXEngine.java @@ -0,0 +1,484 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tasks.CompileFirstPassTask; +import org.nuiton.jaxx.compiler.tasks.CompileSecondPassTask; +import org.nuiton.jaxx.compiler.tasks.FinalizeTask; +import org.nuiton.jaxx.compiler.tasks.GenerateConstructorsTask; +import org.nuiton.jaxx.compiler.tasks.GenerateMissingRulesTask; +import org.nuiton.jaxx.compiler.tasks.GenerateTask; +import org.nuiton.jaxx.compiler.tasks.InitTask; +import org.nuiton.jaxx.compiler.tasks.JAXXEngineTask; +import org.nuiton.jaxx.compiler.tasks.ProfileTask; +import org.nuiton.jaxx.compiler.tasks.StyleSheetTask; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.StringUtil; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * The engine to compile jaxx files. + * + * The method {@link #run()} launch the compilation of files. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.0 was previously JAXXCompilerLaunchor + */ +public class JAXXEngine { + + /** Logger */ + private static final Log log = LogFactory.getLog(JAXXEngine.class); + + /** configuration of the launchor and underlines compilers */ + protected final CompilerConfiguration configuration; + + /** original list of files to compile (says the detected modfied files) */ + protected final JAXXCompilerFile[] incomingFiles; + + /** Files to compile */ + protected final List<JAXXCompilerFile> compilingFiles; + + /** Warnings detected while running. */ + protected final List<String> warnings; + + /** Errors detected while running. */ + protected final List<String> errors; + + /** tasks to launch */ + protected JAXXEngineTask[] tasks; + + /** current pass of the engine */ + protected JAXXEngineTask currentTask; + + /** profile attached to the engine (can be null) */ + protected JAXXProfile profiler; + + protected JAXXEngine(CompilerConfiguration configuration, + File base, + String... relativePaths) { + + if (configuration == null) { + + // use a default configuration + configuration = new DefaultCompilerConfiguration(); + } + + this.configuration = configuration; + warnings = new ArrayList<>(); + errors = new ArrayList<>(); + compilingFiles = new ArrayList<>(); + + if (configuration.isShowClassDescriptorLoading()) { + ClassDescriptorHelper.setShowLoading(true); + } + // add all default files to compile + for (String relativePath : relativePaths) { + JAXXCompilerFile compilerFile = + new JAXXCompilerFile(base, new File(base, relativePath), configuration.getCssExtension()); + addFileToCompile(compilerFile); + } + + // fix once for all incoming files to compile + incomingFiles = compilingFiles.toArray( + new JAXXCompilerFile[compilingFiles.size()]); + } + + public JAXXEngineTask[] getTasks() { + if (tasks == null) { + List<JAXXEngineTask> tasks = new ArrayList<>(); + + tasks.add(new InitTask()); + tasks.add(new CompileFirstPassTask()); + tasks.add(new CompileSecondPassTask()); + tasks.add(new StyleSheetTask()); + tasks.add(new FinalizeTask()); + tasks.add(new GenerateConstructorsTask()); + tasks.add(new GenerateTask()); + + if (getConfiguration().isGenerateMissingIdsAndStyleClassesInCss()) { + tasks.add(new GenerateMissingRulesTask()); + } + + if (getConfiguration().isProfile()) { + tasks.add(new ProfileTask()); + } + + this.tasks = tasks.toArray(new JAXXEngineTask[tasks.size()]); + } + return tasks; + } + + /** @return the errors of the engine */ + public List<String> getErrors() { + return errors; + } + + /** @return the warnings of the engine */ + public List<String> getWarnings() { + return warnings; + } + + public JAXXProfile getProfiler() { + if (profiler == null && getConfiguration().isProfile()) { + profiler = new JAXXProfile(); + } + return profiler; + } + + public CompilerConfiguration getConfiguration() { + return configuration; + } + + public JAXXCompilerFile[] getIncomingFiles() { + return incomingFiles; + } + +// public JAXXCompilerFile[] getCompilingFiles() { +// return compilingFiles.toArray( +// new JAXXCompilerFile[compilingFiles.size()]); +// } + + public JAXXCompilerFile[] getFilesToCompile() { + List<JAXXCompilerFile> files = new ArrayList<>(); + for (JAXXCompilerFile file : compilingFiles) { + if (file.getCompiler() == null) { + files.add(file); + } + } + return files.toArray(new JAXXCompilerFile[files.size()]); + } + + public JAXXCompilerFile[] getCompiledFiles() { + List<JAXXCompilerFile> files = new ArrayList<>(); + for (JAXXCompilerFile file : compilingFiles) { + if (file.getCompiler() != null) { + files.add(file); + } + } + // always send a copy to be safe. + return files.toArray(new JAXXCompilerFile[files.size()]); + } + + public boolean containsJaxxFileClassName(String className) { + for (JAXXCompilerFile file : compilingFiles) { + if (className.equals(file.getClassName())) { + return true; + } + } + return false; + } + + public boolean isCompileFirstPassTask() { + return currentTask != null && + CompileFirstPassTask.TASK_NAME.equals(currentTask.getName()); + } + + /** Resets all state in preparation for a new compilation session. */ + protected void reset(boolean cleanReports) { + for (JAXXCompilerFile compilerFile : compilingFiles) { + compilerFile.clear(); + } + compilingFiles.clear(); + if (profiler != null) { + profiler.clear(); + profiler = null; + } + if (cleanReports) { + clearReports(); + } + + ClassDescriptorHelper.setShowLoading(false); + } + + public void clearReports() { + getWarnings().clear(); + getErrors().clear(); + } + + public String getVersion() { + return "2.4"; + } + + /** + * Obtain the jaxx compiler of the given class name. + * + * @param className the name of the class to use + * @return the compiler instance which is processing the specified JAXX class. + * Each class is compiled by a different compiler instance. + */ + public JAXXCompilerFile getJAXXCompilerFile(String className) { + for (JAXXCompilerFile compilingFile : compilingFiles) { + if (className.equals(compilingFile.getClassName())) { + return compilingFile; + } + } + return null; + } + + /** + * Obtain the jaxx compiler of the given class name. + * + * @param className the name of the class to use + * @return the compiler instance which is processing the specified JAXX class. + * Each class is compiled by a different compiler instance. + */ + public JAXXCompiler getJAXXCompiler(String className) { + JAXXCompilerFile compilerFile = getJAXXCompilerFile(className); + if (compilerFile == null) { + return null; + } + return compilerFile.getCompiler(); + } + + /** + * Obtain the symbo table for the given class name. + * + * @param className the name of the class to use + * @return the symbol table for the specified JAXX class. + * Must be called during the second compiler pass. + * Returns <code>null</code> if no such symbol table could be found. + */ + public SymbolTable getSymbolTable(String className) { + JAXXCompiler compiler = getJAXXCompiler(className); + if (compiler == null) { + return null; + } + return compiler.getSymbolTable(); + } + + /** + * Obtain the decorator of the given name. + * + * @param name the name of the decorator + * @return the decorator found. + * @throws IllegalArgumentException if decorator not found for the given name. + */ + public CompiledObjectDecorator getDecorator(String name) + throws IllegalArgumentException { + Map<String, CompiledObjectDecorator> decorators = + getConfiguration().getDecorators(); + CompiledObjectDecorator decorator = decorators.get(name); + if (decorator == null) { + throw new IllegalArgumentException( + "could not find decorator with key " + name + + " (known decorators : " + decorators.keySet() + ")"); + } + return decorator; + } + + /** + * Obtain the decorator of the given type. + * + * @param type the type of the decorator (syas his fqn) + * @return the decorator found + */ + public CompiledObjectDecorator getDecorator(Class<?> type) { + Map<String, CompiledObjectDecorator> decorators = + getConfiguration().getDecorators(); + for (CompiledObjectDecorator decorator : decorators.values()) { + if (decorator.getClass().equals(type)) { + return decorator; + } + } + return null; + } + + /** + * Add a warning to the engine. + * + * @param warning the warning to add + */ + public void addWarning(String warning) { + warnings.add(warning); + } + + /** + * Add an error to the engine. + * + * @param error the error to add + */ + public void addError(String error) { + errors.add(error); + } + + /** + * Compiled a set of files. + * + * @return {@code -1} if errors appears, the number of generated files + * otherwise. + */ + public int run() { + try { + boolean success = true; + + for (JAXXEngineTask task : getTasks()) { + if (!success) { + // stop as soon as a engine phase failed + break; + } + + currentTask = task; + long t0 = System.nanoTime(); + if (isVerbose()) { + log.info("Start task '" + task.getName() + "' on " + + compilingFiles.size() + " file(s)"); + } + success = task.perform(this); + if (isVerbose()) { + log.info("task '" + task.getName() + "' done in " + + StringUtil.convertTime(System.nanoTime() - t0) + ); + } + } + return success ? compilingFiles.size() : -1; + + //FIXME : deal better the exception treatment... + } catch (CompilerException e) { + log.error(e.getMessage(), e); + return -1; + } catch (Throwable e) { + log.error(e.getMessage(), e); + return -1; + } finally { + if (configuration.isResetAfterCompile()) { + reset(false); + } + } + } + + /** + * Adds a {@code file} to be compiled. + * + * @param file the {@link JAXXCompilerFile} to add. + */ + public void addFileToCompile(JAXXCompilerFile file) { + + if (isVerbose()) { + log.info("register jaxx file " + file.getJaxxFile()); + } + compilingFiles.add(file); + } + + /** + * Adds a {@link JAXXCompilerFile} given the jaxx file and the + * corresponding class fully qualified name. + * + * @param jaxxFile the jaxx file location + * @param jaxxClassName the fully qualified name of the jaxx class + */ + public void addFileToCompile(File jaxxFile, String jaxxClassName) { + + if (log.isDebugEnabled()) { + log.debug("file = " + jaxxFile + ", fqn = " + jaxxClassName); + } + + JAXXCompilerFile file = new JAXXCompilerFile(jaxxFile, jaxxClassName, configuration.getCssExtension()); + addFileToCompile(file); + } + + /** + * Create a new compiler and attach it to the given {@code jaxxFile}. + * + * @param jaxxFile the definition of jaxx file to compile + * @return the new compiler + * @throws Exception if any pb while creating of compiler + */ + public JAXXCompiler newCompiler(JAXXCompilerFile jaxxFile) throws Exception { + + Class<?> compilerClass = + getConfiguration().getCompilerClass(); + + if (compilerClass == null) { + throw new NullPointerException( + "Configuration compilerClass is null"); + } + + Constructor<?> cons = compilerClass.getConstructor( + JAXXEngine.class, + JAXXCompilerFile.class, + List.class + ); + + /* + Arrays.asList( + "java.awt.*", + "java.awt.event.*", + "java.io.*", + "java.lang.*", + "java.util.*", + "javax.swing.*", + "javax.swing.border.*", + "javax.swing.event.*", + "jaxx.runtime.*", + "jaxx.runtime.swing.*", + "static org.nuiton.i18n.I18n.t", + "static org.nuiton.jaxx.runtime.SwingUtil.createImageIcon" + ) + */ + JAXXCompiler jaxxCompiler = (JAXXCompiler) cons.newInstance( + this, + jaxxFile, + Arrays.asList( + "java.awt.*", +// "java.awt.event.*", +// "java.io.*", + "java.lang.*", +// "java.util.*", + "javax.swing.*", + "javax.swing.border.*", +// "javax.swing.event.*", +// "jaxx.runtime.*", + "org.nuiton.jaxx.runtime.swing.*" + ) + ); + jaxxFile.setCompiler(jaxxCompiler); + return jaxxCompiler; + } + + public boolean isVerbose() { + return getConfiguration().isVerbose(); + } + + /** + * Add a profile time for the given compiler and key. + * + * Note: if {@link #profiler} is {@code null}, do nothing + * + * @param compiler the compiler to profile + * @param key the key of profiling + */ + public void addProfileTime(JAXXCompiler compiler, String key) { + JAXXProfile profiler = getProfiler(); + if (profiler != null) { + profiler.addTime(compiler, key); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXFactory.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXFactory.java new file mode 100644 index 0000000..4afe4b8 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXFactory.java @@ -0,0 +1,156 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler; + +import org.nuiton.jaxx.compiler.spi.Initializer; +import org.nuiton.jaxx.compiler.tags.TagManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.File; +import java.util.ServiceLoader; + +/** + * Factory of {@link JAXXCompiler} and {@link JAXXEngine}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class JAXXFactory { + + /** Logger */ + private static final Log log = LogFactory.getLog(JAXXFactory.class); + + /** shared instance of engine. */ + protected static JAXXEngine engine; + + /** shared instance of configuration * */ + protected static CompilerConfiguration configuration; + + protected JAXXFactory() { + // no instance + } + + public static void setConfiguration(CompilerConfiguration configuration) { + JAXXFactory.configuration = configuration; + } + + /** + * Create a new empty launchor and set it as current launchor accessible + * via method {@link #getEngine()}. + * + * @return the new instanciated launchor + */ + public static JAXXEngine newDummyEngine() { + return newEngine(null); + } + + /** + * Create a new launchor and set it as current launchor accessible via + * method {@link #getEngine()}. + * + * The launchor will be prepared to run a set of files, expressed as paths + * relative to a base directory. + * The class names of the compiled files are derived from the relative path + * strings (e.g. "example/Foo.jaxx" compiles into a class named + * "example.Foo"). + * + * @param basedir the directory against which to resolve relative paths + * @param relativePaths a list of relative paths to .jaxx files being compiled + * @return the new instanciated launchor + */ + public static JAXXEngine newEngine(File basedir, String... relativePaths) { + checkConfiguration(); + if (engine != null) { + engine.reset(true); + } + engine = new JAXXEngine(configuration, basedir, relativePaths); + return engine; + } + + /** + * Creates a dummy Compiler for use in unit testing or dettached use of an + * engine. + * + * @param classLoader class loader to use + * @return the compiler + */ + public static JAXXCompiler newDummyCompiler(ClassLoader classLoader) { + JAXXCompiler compiler = new JAXXCompiler(); + if (classLoader != null) { + compiler.setClassLoader(classLoader); + } + return compiler; + } + + /** + * @return the current launchor + * @throws NullPointerException if no launchor was registred via a + * <code>newEngine-like</code> method. + */ + public static JAXXEngine getEngine() throws NullPointerException { + checkConfiguration(); + checkEngine(); + return engine; + } + + /** + * @return {@code true} if there is an engine registred, {@code false} otherwise. + */ + public static boolean isEngineRegistred() { + return engine != null; + } + + /** + * Load the {@link Initializer} services found via the{@link ServiceLoader} + * mecanism. + */ + public static void initFactory() { + + // must have a configuration + checkConfiguration(); + + TagManager.reset(); + + boolean verbose = configuration.isVerbose(); + for (Initializer initializer : + configuration.getInitializers().values()) { + if (verbose) { + log.info("load initializer " + initializer); + } + initializer.initialize(); + } + + } + + protected static void checkConfiguration() throws NullPointerException { + if (configuration == null) { + throw new NullPointerException("No configuration was registred."); + } + } + + protected static void checkEngine() throws NullPointerException { + if (engine == null) { + throw new NullPointerException("No engine was registred."); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXProfile.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXProfile.java new file mode 100644 index 0000000..d9261f7 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/JAXXProfile.java @@ -0,0 +1,386 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler; + +import org.nuiton.jaxx.compiler.tasks.CompileFirstPassTask; +import org.nuiton.jaxx.compiler.tasks.CompileSecondPassTask; +import org.nuiton.jaxx.compiler.tasks.FinalizeTask; +import org.nuiton.jaxx.compiler.tasks.GenerateTask; +import org.nuiton.jaxx.compiler.tasks.StyleSheetTask; +import org.nuiton.util.StringUtil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + * Pour profiler les temps d'execution pendant une compilation. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.3 + */ +public class JAXXProfile { + + void clear() { + entries.clear(); + compilers.clear(); + } + + protected class CompilerEntry { + + JAXXCompiler compiler; + + SortedMap<String, Long> times; + + public CompilerEntry(JAXXCompiler compiler) { + this.compiler = compiler; + times = new TreeMap<>(); + } + } + + public static class ProfileResult { + + long min, max, average, total; + + Map<JAXXCompiler, Long> delta; + + List<Long> times; + + ProfileResult(Map<JAXXCompiler, Long> delta) { + this.delta = delta; + times = new ArrayList<>(delta.values()); + Collections.sort(times); + min = times.get(0); + max = times.get(times.size() - 1); + total = 0; + average = 0; + for (Long t : times) { + total += t; + } + average = total / times.size(); + } + + public long getTime(JAXXCompiler compiler) { + for (Entry<JAXXCompiler, Long> entry : delta.entrySet()) { + if (entry.getKey().equals(compiler)) { + return entry.getValue(); + } + } + throw new IllegalArgumentException("could not find time for compiler " + compiler); + } + + public void clear() { + times.clear(); + delta.clear(); + } + + public JAXXCompiler getCompiler(Long l) { + for (Entry<JAXXCompiler, Long> entry : delta.entrySet()) { + if (entry.getValue().equals(l)) { + return entry.getKey(); + } + } + throw new IllegalArgumentException("could not find compiler for time " + l); + } + } + + SortedMap<Integer, CompilerEntry> entries; + + List<JAXXCompiler> compilers; + + public JAXXProfile() { + compilers = new ArrayList<>(); + entries = new TreeMap<>(); + } + + public void addTime(JAXXCompiler compiler, String key) { + CompilerEntry e = getEntry(compiler); + e.times.put(key, System.nanoTime()); + } + + public Map<JAXXCompiler, Long> getDelta(String keyOne, String keyTwo) { + Map<JAXXCompiler, Long> result = new HashMap<>(); + for (Map.Entry<Integer, CompilerEntry> e : entries.entrySet()) { + JAXXCompiler c = getCompiler(e.getKey()); + CompilerEntry entry = e.getValue(); + Long t0 = entry.times.get(keyOne); + Long t1 = entry.times.get(keyTwo); + if (t0 == null) { + throw new NullPointerException( + "could not find time for " + keyOne + + " on compiler " + c.getOutputClassName()); + } + if (t1 == null) { + throw new NullPointerException( + "could not find time for " + keyTwo + + " on compiler " + c.getOutputClassName()); + } + long delta = t1 - t0; + result.put(c, delta); + } + return result; + } + + public ProfileResult newProfileResult(String name) { + ProfileResult result; + Map<JAXXCompiler, Long> delta = + getDelta(name + "_start", name + "_end"); + result = new ProfileResult(delta); + return result; + } + + public ProfileResult newProfileResult(ProfileResult... toCumul) { + ProfileResult result; + Map<JAXXCompiler, Long> delta = new HashMap<>(); + for (JAXXCompiler c : compilers) { + long total = 0; + for (ProfileResult cumul : toCumul) { + long time = cumul.getTime(c); + total += time; + } + delta.put(c, total); + } + result = new ProfileResult(delta); + return result; + } + + public StringBuilder computeProfileReport() { + + StringBuilder buffer = new StringBuilder(); + + if (compilers.isEmpty()) { + return buffer.append("no jaxx file treated, no profile report"); + } + + // compute max size of the fqn of a compiled file + int maxLength = 0; + for (JAXXCompiler compiler : compilers) { + int l = compiler.getOutputClassName().length(); + if (l > maxLength) { + maxLength = l; + } + } + + ProfileResult cfp = newProfileResult(CompileFirstPassTask.TASK_NAME); + ProfileResult csp = newProfileResult(CompileSecondPassTask.TASK_NAME); + ProfileResult ssp = newProfileResult(StyleSheetTask.TASK_NAME); + ProfileResult fp = newProfileResult(FinalizeTask.TASK_NAME); + ProfileResult gp = newProfileResult(GenerateTask.TASK_NAME); + ProfileResult total = newProfileResult(cfp, csp, ssp, fp, gp); + + String reportPattern = "\n|%1$-" + maxLength + + "s|%2$15s|%3$15s|%4$15s|%5$15s|%6$15s|%7$15s|"; + + char[] tmpC = new char[maxLength]; + Arrays.fill(tmpC, '-'); + String line = String.format(reportPattern, + new String(tmpC), + "---------------", + "---------------", + "---------------", + "---------------", + "---------------", + "---------------"); + + buffer.append(line); + + buffer.append(String.format(reportPattern, + "(files / stats) \\ passes", + "compile round 1", + "compile round 2", + "stylesheet", + "finalize", + "generation", + "all passes") + ); + + buffer.append(line); + + // affiche les temps de tous les fichiers en temp total croissant + for (Long l : total.times) { + JAXXCompiler c = total.getCompiler(l); + printReportLine(buffer, + reportPattern, + c.getOutputClassName(), + cfp.getTime(c), + csp.getTime(c), + ssp.getTime(c), + fp.getTime(c), + gp.getTime(c), + total.getTime(c) + ); + } + + buffer.append(line); + + if (compilers.size() > 1) { + printReportLine(buffer, + reportPattern, + "total (" + compilers.size() + " files)", + cfp.total, + csp.total, + ssp.total, + fp.total, + gp.total, + total.total + ); + + buffer.append(line); + + printReportLine2(buffer, + reportPattern, + "min", + cfp.min, + csp.min, + ssp.min, + fp.min, + gp.min, + total.min + ); + printReportLine2(buffer, + reportPattern, + "max", + cfp.max, + csp.max, + ssp.max, + fp.max, + gp.max, + total.max + ); + printReportLine(buffer, + reportPattern, + "average", + cfp.average, + csp.average, + ssp.average, + fp.average, + gp.average, + total.average + ); + buffer.append(line); + } + cfp.clear(); + csp.clear(); + ssp.clear(); + gp.clear(); + total.clear(); + + return buffer; + } + + public static final String TIME_PATTERN = "%1$9s - %2$2d%%"; + + protected void printReportLine(StringBuilder buffer, + String reportPattern, + String label, + long firstPassCounter, + long secondPassCounter, + long cssCounter, + long finalizeCounter, + long generatorCounter, + long totalCounter) { + + float percentCFP = (float) firstPassCounter / totalCounter * 100; + float percentCSP = (float) secondPassCounter / totalCounter * 100; + float percentCSSP = (float) cssCounter / totalCounter * 100; + float percentFP = (float) finalizeCounter / totalCounter * 100; + float percentGP = (float) generatorCounter / totalCounter * 100; + + String strCFP = String.format(TIME_PATTERN, + StringUtil.convertTime(firstPassCounter), + (int) percentCFP + ); + String strCSP = String.format(TIME_PATTERN, + StringUtil.convertTime(secondPassCounter), + (int) percentCSP + ); + String strCSSP = String.format(TIME_PATTERN, + StringUtil.convertTime(cssCounter), + (int) percentCSSP + ); + String strFP = String.format(TIME_PATTERN, + StringUtil.convertTime(finalizeCounter), + (int) percentFP + ); + String strGP = String.format(TIME_PATTERN, + StringUtil.convertTime(generatorCounter), + (int) percentGP + ); + + buffer.append(String.format(reportPattern, + label, + strCFP, + strCSP, + strCSSP, + strFP, + strGP, + StringUtil.convertTime(totalCounter)) + ); + } + + protected void printReportLine2(StringBuilder buffer, + String reportPattern, + String label, + long firstPassCounter, + long secondPassCounter, + long cssCounter, + long finalizeCounter, + long generatorCounter, + long totalCounter) { + buffer.append(String.format(reportPattern, + label, + StringUtil.convertTime(firstPassCounter), + StringUtil.convertTime(secondPassCounter), + StringUtil.convertTime(cssCounter), + StringUtil.convertTime(finalizeCounter), + StringUtil.convertTime(generatorCounter), + StringUtil.convertTime(totalCounter)) + ); + } + + protected CompilerEntry getEntry(JAXXCompiler compiler) { + int key = compiler.getOutputClassName().hashCode(); + CompilerEntry result = entries.get(key); + if (result == null) { + result = new CompilerEntry(compiler); + entries.put(key, result); + compilers.add(compiler); + } + return result; + } + + protected JAXXCompiler getCompiler(int hasCode) { + for (JAXXCompiler c : compilers) { + if (hasCode == c.getOutputClassName().hashCode()) { + return c; + } + } + return null; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/SymbolTable.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/SymbolTable.java new file mode 100644 index 0000000..ff46043 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/SymbolTable.java @@ -0,0 +1,89 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler; + +import org.nuiton.jaxx.compiler.reflect.FieldDescriptor; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** Symbol table constructed during the first pass of compilation. */ +public class SymbolTable { + + private String superclass; + // maps ID strings to class names -- we can't map directly to CompiledObjects, because we + // can't create those until after the first pass + + private Map<String, String> ids = new HashMap<>(); + + private List<FieldDescriptor> scriptFields = new ArrayList<>(); + + private List<MethodDescriptor> scriptMethods = new ArrayList<>(); + + private String[] interfaces; + + /** @return the fully-qualified name of the superclass of the class described by this symbol table. */ + public String getSuperclassName() { + return superclass; + } + + public String[] getInterfaces() { + return interfaces; + } + + public void setSuperclassName(String superclass) { + this.superclass = superclass; + } + + /** + * @return a map of IDs to class names. Each entry in the map corresponds to a class tag with an + * <code>id</code> attribute. The <code>id</code> is the key, and the fully-qualified class name + * of the tag is the value. + */ + public Map<String, String> getClassTagIds() { + return ids; + } + + /** @return a list of <code>FieldDescriptors</code> for fields defined in <script> tags. */ + public List<FieldDescriptor> getScriptFields() { + return scriptFields; + } + + /** @return a list of <code>MethodDescriptors</code> for methods defined in <script> tags. */ + public List<MethodDescriptor> getScriptMethods() { + return scriptMethods; + } + + public void setInterfaces(String[] interfaces) { + this.interfaces = interfaces; + } + + public void clear() { + ids.clear(); + scriptFields.clear(); + scriptMethods.clear(); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/UnsupportedAttributeException.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/UnsupportedAttributeException.java new file mode 100644 index 0000000..902f7a6 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/UnsupportedAttributeException.java @@ -0,0 +1,67 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler; + +import org.nuiton.jaxx.compiler.tags.TagHandler; + +/** + * Thrown by <code>TagHandler</code> when an unsupported attribute is encountered. + * + * @see TagHandler + */ +public class UnsupportedAttributeException extends CompilerException { + + private static final long serialVersionUID = -6919583037172920343L; + + /** Creates a new <code>UnsupportedAttributeException</code>. */ + public UnsupportedAttributeException() { + } + + /** + * Creates a new <code>UnsupportedAttributeException</code> with the specified detail message. + * + * @param msg the exception's detail message + */ + public UnsupportedAttributeException(String msg) { + super(msg); + } + + /** + * Creates a new <code>UnsupportedAttributeException</code> with the specified cause. + * + * @param initCause the exception's initCause + */ + public UnsupportedAttributeException(Throwable initCause) { + super(initCause); + } + + /** + * Creates a new <code>UnsupportedAttributeException</code> with the specified detail message and cause. + * + * @param msg the exception's detail message + * @param initCause the exception's initCause + */ + public UnsupportedAttributeException(String msg, Throwable initCause) { + super(msg, initCause); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/UnsupportedTagException.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/UnsupportedTagException.java new file mode 100644 index 0000000..b3f0a18 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/UnsupportedTagException.java @@ -0,0 +1,63 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler; + +/** Thrown by the compiler when an unregistered tag is encountered. */ +public class UnsupportedTagException extends CompilerException { + private static final long serialVersionUID = 3199732135804426699L; + + /** Creates a new <code>UnsupportedTagException</code>. */ + public UnsupportedTagException() { + } + + + /** + * Creates a new <code>UnsupportedTagException</code> with the specified detail message. + * + * @param msg the exception's detail message + */ + public UnsupportedTagException(String msg) { + super(msg); + } + + + /** + * Creates a new <code>UnsupportedTagException</code> with the specified cause. + * + * @param initCause the exception's initCause + */ + public UnsupportedTagException(Throwable initCause) { + super(initCause); + } + + + /** + * Creates a new <code>UnsupportedTagException</code> with the specified detail message and cause. + * + * @param msg the exception's detail message + * @param initCause the exception's initCause + */ + public UnsupportedTagException(String msg, Throwable initCause) { + super(msg, initCause); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/BeanInfoUtil.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/BeanInfoUtil.java new file mode 100644 index 0000000..3c1a904 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/BeanInfoUtil.java @@ -0,0 +1,58 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.beans; + +import java.beans.Introspector; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** @author Tony Chemit - chemit@codelutin.com */ +public class BeanInfoUtil { + + public static String[] originalBeanInfoSearchPath; + + public static void addJaxxBeanInfoPath(String... packageNames) { + + String[] searchPath = Introspector.getBeanInfoSearchPath(); + if (originalBeanInfoSearchPath == null) { + originalBeanInfoSearchPath = searchPath; + } + List<String> listSearchPath = new ArrayList<>(Arrays.asList(searchPath)); + for (String packageName : packageNames) { + if (!listSearchPath.contains(packageName)) { + listSearchPath.add(packageName); + } + } + + Introspector.setBeanInfoSearchPath(listSearchPath.toArray(new String[listSearchPath.size()])); + } + + public static void reset() { + if (originalBeanInfoSearchPath != null) { + Introspector.setBeanInfoSearchPath(originalBeanInfoSearchPath); + originalBeanInfoSearchPath = null; + } + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXBeanDescriptor.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXBeanDescriptor.java new file mode 100644 index 0000000..3d09fc0 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXBeanDescriptor.java @@ -0,0 +1,37 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.beans; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; + +/** + * Mirrors the class <code>java.beans.BeanDescriptor</code>. JAXX uses its own introspector rather than the built-in + * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, + * not just <code>java.lang.Class</code>. + */ +public class JAXXBeanDescriptor extends JAXXFeatureDescriptor { + + public JAXXBeanDescriptor(ClassDescriptor beanClass) { + super(beanClass, beanClass.getName()); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXBeanInfo.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXBeanInfo.java new file mode 100644 index 0000000..b0f4a21 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXBeanInfo.java @@ -0,0 +1,59 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.beans; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; + +/** + * Mirrors the class <code>java.beans.BeanInfo</code>. JAXX uses its own introspector rather than the built-in + * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, + * not just <code>java.lang.Class</code>. + */ +public class JAXXBeanInfo { + + private JAXXBeanDescriptor beanDescriptor; + + private JAXXPropertyDescriptor[] propertyDescriptors; + + private JAXXEventSetDescriptor[] eventSetDescriptors; + + public JAXXBeanInfo(JAXXBeanDescriptor beanDescriptor, + JAXXPropertyDescriptor[] propertyDescriptors, + JAXXEventSetDescriptor[] eventSetDescriptors) { + this.beanDescriptor = beanDescriptor; + this.propertyDescriptors = propertyDescriptors; + this.eventSetDescriptors = eventSetDescriptors; + } + + public JAXXBeanDescriptor getJAXXBeanDescriptor() { + return beanDescriptor; + } + + public JAXXPropertyDescriptor[] getJAXXPropertyDescriptors() { + return propertyDescriptors; + } + + public JAXXEventSetDescriptor[] getJAXXEventSetDescriptors() { + return eventSetDescriptors; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXEventSetDescriptor.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXEventSetDescriptor.java new file mode 100644 index 0000000..76cafcd --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXEventSetDescriptor.java @@ -0,0 +1,60 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.beans; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; + +/** + * Mirrors the class <code>java.beans.EventSetDescriptor</code>. JAXX uses its own introspector rather than the built-in + * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, + * not just <code>java.lang.Class</code>. + */ +public class JAXXEventSetDescriptor extends JAXXFeatureDescriptor { + + private MethodDescriptor addListenerMethod; + + private MethodDescriptor removeListenerMethod; + + private MethodDescriptor[] listenerMethods; + + public JAXXEventSetDescriptor(ClassDescriptor classDescriptor, String name, MethodDescriptor addListenerMethod, + MethodDescriptor removeListenerMethod, MethodDescriptor[] listenerMethods) { + super(classDescriptor, name); + this.addListenerMethod = addListenerMethod; + this.removeListenerMethod = removeListenerMethod; + this.listenerMethods = listenerMethods; + } + + public MethodDescriptor getAddListenerMethod() { + return addListenerMethod; + } + + public MethodDescriptor getRemoveListenerMethod() { + return removeListenerMethod; + } + + public MethodDescriptor[] getListenerMethods() { + return listenerMethods; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXFeatureDescriptor.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXFeatureDescriptor.java new file mode 100644 index 0000000..7820e39 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXFeatureDescriptor.java @@ -0,0 +1,76 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.beans; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; + +import java.util.HashMap; +import java.util.Map; + +/** + * Mirrors the class <code>java.beans.FeatureDescriptor</code>. JAXX uses its own introspector rather than the built-in + * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, + * not just <code>java.lang.Class</code>. + */ +public class JAXXFeatureDescriptor { + + private String name; + + private Map<String, Object> values; + + private ClassDescriptor classDescriptor; + + JAXXFeatureDescriptor(ClassDescriptor classDescriptor, String name) { + if (name == null || classDescriptor == null) { + throw new NullPointerException(); + } + this.name = name; + this.classDescriptor = classDescriptor; + } + + public String getName() { + return name; + } + + public ClassDescriptor getClassDescriptor() { + return classDescriptor; + } + + public Object getValue(String key) { + return values != null ? values.get(key) : null; + } + + public void setValue(String key, Object value) { + if (values == null) { + values = new HashMap<>(); + } + values.put(key, value); + } + + public static String capitalize(String name) { + if (name.length() == 0) { + return name; + } + return Character.toUpperCase(name.charAt(0)) + name.substring(1); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXIntrospector.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXIntrospector.java new file mode 100644 index 0000000..504962f --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXIntrospector.java @@ -0,0 +1,190 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.beans; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; + +import java.beans.BeanDescriptor; +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyChangeListener; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.HashMap; +import java.util.Map; + +/** + * Performs introspection on a <code>ClassDescriptor</code>. Ideally, I could just have copied Sun's Introspector + * and changed a few things, but the licensing terms are incompatible. This implementation is incomplete -- it only + * bothers to report info that JAXX actually checks. It also relaxes some of Introspector's rules a bit, but I + * don't believe it results in any meaningful incompatibilities. + * + * JAXX uses its own introspector rather than the built-in + * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, + * not just <code>java.lang.Class</code>. + */ +public class JAXXIntrospector { + + private ClassDescriptor classDescriptor; + + private Map<String, JAXXPropertyDescriptor> propertyDescriptors = new HashMap<>(); + + private Map<String, JAXXEventSetDescriptor> eventSetDescriptors = new HashMap<>(); + + private JAXXIntrospector(ClassDescriptor classDescriptor) { + this.classDescriptor = classDescriptor; + } + + /** + * Returns the <code>JAXXBeanInfo</code> for a given class. + * + * @param classDescriptor the class to introspect + * @return the <code>JAXXBeanInfo</code> for the bean class + */ + public static JAXXBeanInfo getJAXXBeanInfo(ClassDescriptor classDescriptor) { + JAXXIntrospector introspector = new JAXXIntrospector(classDescriptor); + return introspector.createBeanInfo(); + } + + private JAXXBeanInfo createBeanInfo() { + ClassDescriptor explicitInfoClass = classDescriptor; + BeanInfo explicitBeanInfo = null; + while (explicitInfoClass != null) { + explicitBeanInfo = getExplicitBeanInfo(explicitInfoClass); + if (explicitBeanInfo != null) { + break; + } + explicitInfoClass = explicitInfoClass.getSuperclass(); + } + + if (explicitBeanInfo != null) { + PropertyDescriptor[] explicitProperties = explicitBeanInfo.getPropertyDescriptors(); + for (PropertyDescriptor explicitProperty : explicitProperties) { + Class<?> type = explicitProperty.getPropertyType(); + Method readMethod = explicitProperty.getReadMethod(); + Method writeMethod = explicitProperty.getWriteMethod(); + try { + ClassDescriptor typeDescriptor = ClassDescriptorHelper.getClassDescriptor(type.getName(), type.getClassLoader()); + JAXXPropertyDescriptor propertyDescriptor = new JAXXPropertyDescriptor(classDescriptor, explicitProperty.getName(), + readMethod != null ? classDescriptor.getMethodDescriptor(readMethod.getName()) : null, + writeMethod != null ? classDescriptor.getMethodDescriptor(writeMethod.getName(), typeDescriptor) : null); + propertyDescriptor.setBound(explicitProperty.isBound()); + Enumeration<String> attributeNames = explicitProperty.attributeNames(); + while (attributeNames.hasMoreElements()) { + String name = attributeNames.nextElement(); + propertyDescriptor.setValue(name, explicitProperty.getValue(name)); + } + propertyDescriptors.put(propertyDescriptor.getName(), propertyDescriptor); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Internal error: Could not find ClassDescriptor corresponding to Java " + type, e); + } catch (NoSuchMethodException e) { + throw new RuntimeException("Internal error: Could not find expected MethodDescriptor in " + classDescriptor, e); + } + } + } + + // if the class broadcasts PropertyChangeEvent, assume all properties are bound (java.beans.Introspector + // does the same) + boolean propertyChangeSource; + try { + classDescriptor.getMethodDescriptor("addPropertyChangeListener", ClassDescriptorHelper.getClassDescriptor(PropertyChangeListener.class)); + propertyChangeSource = true; + } catch (NoSuchMethodException e) { + propertyChangeSource = false; + } + + MethodDescriptor[] methods = classDescriptor.getMethodDescriptors(); + for (MethodDescriptor method : methods) { + String name = method.getName(); + if (name.startsWith("get") && name.length() > 3 && Character.isUpperCase(name.charAt(3)) && method.getParameterTypes().length == 0) { + String propertyName = Introspector.decapitalize(name.substring(3)); + if (!propertyDescriptors.containsKey(propertyName)) { + propertyDescriptors.put(propertyName, new JAXXPropertyDescriptor(classDescriptor, propertyName, method, null, propertyChangeSource)); + } + } else if (name.startsWith("is") && name.length() > 2 && Character.isUpperCase(name.charAt(2)) && method.getParameterTypes().length == 0) { + String propertyName = Introspector.decapitalize(name.substring(2)); + if (!propertyDescriptors.containsKey(propertyName)) { + propertyDescriptors.put(propertyName, new JAXXPropertyDescriptor(classDescriptor, propertyName, method, null, propertyChangeSource)); + } + } else if (name.startsWith("set") && name.length() > 3 && Character.isUpperCase(name.charAt(3)) && method.getParameterTypes().length == 1) { + String propertyName = Introspector.decapitalize(name.substring(3)); + if (!propertyDescriptors.containsKey(propertyName)) { + propertyDescriptors.put(propertyName, new JAXXPropertyDescriptor(classDescriptor, propertyName, null, method, propertyChangeSource)); + } + } else if (name.startsWith("add") && name.length() > 3 && Character.isUpperCase(name.charAt(3))) { + ClassDescriptor[] parameters = method.getParameterTypes(); + if (parameters.length != 1 || !ClassDescriptorHelper.getClassDescriptor(EventListener.class).isAssignableFrom(parameters[0])) { + continue; // not an event listener method + } + try { + String eventSetName = method.getName().substring(3); + MethodDescriptor remove = classDescriptor.getMethodDescriptor("remove" + eventSetName, parameters); + eventSetDescriptors.put(eventSetName, new JAXXEventSetDescriptor(classDescriptor, eventSetName, method, remove, parameters[0].getMethodDescriptors())); + } catch (NoSuchMethodException e) { + // no matching remove method, not a valid event + } + } + } + + JAXXBeanDescriptor beanDescriptor = new JAXXBeanDescriptor(classDescriptor); + if (explicitBeanInfo != null) { + BeanDescriptor explicitBeanDescriptor = explicitBeanInfo.getBeanDescriptor(); + if (explicitBeanDescriptor != null) { + Enumeration<String> attributeNames = + explicitBeanDescriptor.attributeNames(); + while (attributeNames.hasMoreElements()) { + String name = attributeNames.nextElement(); + beanDescriptor.setValue(name, explicitBeanDescriptor.getValue(name)); + } + } + } + + return new JAXXBeanInfo(beanDescriptor, + propertyDescriptors.values().toArray(new JAXXPropertyDescriptor[propertyDescriptors.size()]), + eventSetDescriptors.values().toArray(new JAXXEventSetDescriptor[eventSetDescriptors.size()])); + } + + private static BeanInfo getExplicitBeanInfo(ClassDescriptor classDescriptor) { + try { + Class<?> beanClass = Class.forName(classDescriptor.getName(), true, classDescriptor.getClassLoader()); // see if there is a class by that name in this package + Method findExplicitBeanInfo = Introspector.class.getDeclaredMethod("findExplicitBeanInfo", new Class[]{Class.class}); + findExplicitBeanInfo.setAccessible(true); + return (BeanInfo) findExplicitBeanInfo.invoke(null, beanClass); + } catch (ClassNotFoundException e) { + return null; // happens for uncompiled classes + } catch (NoClassDefFoundError e) { + return null; // wrong case, etc. + } catch (NoSuchMethodException e) { + throw new RuntimeException("Error: could not find method 'findExplicitBeanInfo' in java.beans.Introspector. You are most likely running a version of Java against which JAXX has not been tested."); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXPropertyDescriptor.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXPropertyDescriptor.java new file mode 100644 index 0000000..760ba33 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/beans/JAXXPropertyDescriptor.java @@ -0,0 +1,112 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.beans; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; + +/** + * Mirrors the class <code>java.beans.PropertyDescriptor</code>. JAXX uses its own introspector rather than the built-in + * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, + * not just <code>java.lang.Class</code>. + */ +public class JAXXPropertyDescriptor extends JAXXFeatureDescriptor { + + private ClassDescriptor propertyType; + + private MethodDescriptor readMethod; + + private MethodDescriptor writeMethod; + + private boolean bound; + + public JAXXPropertyDescriptor(ClassDescriptor classDescriptor, String propertyName) { + this(classDescriptor, propertyName, null, null); + } + + public JAXXPropertyDescriptor(ClassDescriptor classDescriptor, String propertyName, + MethodDescriptor readMethod, MethodDescriptor writeMethod) { + this(classDescriptor, propertyName, readMethod, writeMethod, false); + } + + public JAXXPropertyDescriptor(ClassDescriptor classDescriptor, String propertyName, + MethodDescriptor readMethod, MethodDescriptor writeMethod, + boolean bound) { + super(classDescriptor, propertyName); + this.readMethod = readMethod; + this.writeMethod = writeMethod; + this.bound = bound; + } + + public MethodDescriptor getReadMethodDescriptor() { + if (readMethod == null) { + try { + readMethod = getClassDescriptor().getMethodDescriptor("get" + capitalize(getName())); + } catch (NoSuchMethodException e) { + try { + readMethod = getClassDescriptor().getMethodDescriptor("is" + capitalize(getName())); + } catch (NoSuchMethodException e2) { + } + } + } + return readMethod; + } + + public MethodDescriptor getWriteMethodDescriptor() { + if (writeMethod == null) { + try { + String methodName = "set" + capitalize(getName()); + MethodDescriptor read = getReadMethodDescriptor(); + if (read != null) { + writeMethod = getClassDescriptor().getMethodDescriptor(methodName, read.getReturnType()); + } else { + throw new CompilerException("Internal error: requesting 'set' method for property of unknown type: '" + getName() + "' (in " + getClassDescriptor() + ")"); + } + } catch (NoSuchMethodException e) { + } + } + return writeMethod; + } + + public ClassDescriptor getPropertyType() { + if (propertyType == null) { + MethodDescriptor read = getReadMethodDescriptor(); + if (read != null) { + propertyType = read.getReturnType(); + } else { + MethodDescriptor write = getWriteMethodDescriptor(); + propertyType = write.getParameterTypes()[0]; + } + } + return propertyType; + } + + public boolean isBound() { + return bound; + } + + public void setBound(boolean bound) { + this.bound = bound; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/DataBinding.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/DataBinding.java new file mode 100644 index 0000000..d0823e5 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/DataBinding.java @@ -0,0 +1,309 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.binding; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.java.JavaFileGenerator; +import org.nuiton.jaxx.compiler.java.JavaMethod; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * Represents a data binding in a JAXX file. <code>DataBinding</code> uses + * {@link DataSource} to track changes to a source expression and update + * the destination. + */ +public class DataBinding { + + /** Logger. */ + protected static final Log log = LogFactory.getLog(DataBinding.class); + + /** Id of the data binding */ + private String id; + + /** Real Id of the data binding (can be suffix by a number for css binding to avoid collisions) */ + private String realId; + + /** Constant id build from the {@link #realId} and used instead of {@link #realId} in generated code */ + protected String constantId; + + /** source of the data binding */ + private String source; + + /** + * A Java snippet which will cause the destination property to be updated with the current value of + * the binding. + */ + private String assignment; + + /** A internal flag to */ + private boolean quickNoDependencies; + + /** Compiled data source */ + protected DataSource dataSource; + + /** code to add to processDataBinding (null if no binding) */ + protected String processDataBinding; + + /** code to register the databinding (null if no binding) */ + protected String initDataBinding; + + /** Extra method to add to the binding */ + protected final List<JavaMethod> methods = new ArrayList<>(); + + /** internal state passed to {@code true} when {@link #compile(JAXXCompiler)} method is invoked */ + private boolean compiled; + + /** + * Creates a new data binding. + * + * @param id the data binding destination in the form <code>id.propertyName</code> + * @param source the Java source code for the data binding expression + * @param assignment Java snippet which will cause the destination property to be updated with the current value of the binding + * @param quickNoDependencies internal flag to not treate process databinding in not a real binding + */ + public DataBinding(String id, String source, String assignment, boolean quickNoDependencies) { + this.id = id; + this.source = source; + this.assignment = assignment; + this.quickNoDependencies = quickNoDependencies; + if (log.isDebugEnabled()) { + log.debug("id=" + id + " assignement=" + assignment + " source=" + source + " quickNoDependencies=" + quickNoDependencies); + } + } + + public String getAssignment() { + return assignment; + } + + public String getSource() { + return source; + } + + public boolean isQuickNoDependencies() { + return quickNoDependencies; + } + + public String getProcessDataBinding() { + return processDataBinding; + } + + public String getInitDataBinding() { + return initDataBinding; + } + + public DataListener[] getTrackers() { + return dataSource == null ? null : dataSource.getTrackers(); + } + + public String getRealId() { + return realId; + } + + public String getConstantId() { + return constantId; + } + + public List<JavaMethod> getMethods() { + return methods; + } + + @Override + public String toString() { + ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); + b.append("id", id); + b.append("source", source.trim()); + b.append("assignement", assignment.trim()); + b.append("quickNoDependencies", quickNoDependencies); + if (compiled) { + b.append("realdId", realId); + b.append("constantId", getConstantId()); + b.append("objectCode", dataSource.getObjectCode()); + DataListener[] trackers = dataSource.getTrackers(); + if (trackers.length > 0) { + b.append("source:trackers", trackers.length); + for (DataListener d : trackers) { + b.append("source:tracker", d); + } + } + } + return b.toString(); + } + + /** + * Compiles the data binding expression. This method calls methods in + * <code>JAXXCompiler</code> to add the Java code that performs the data + * binding setup. + * + * @param compiler compiler which includes the data binding + * @return {@code true} if the expression has dependencies, {@code false} otherwise + * @throws CompilerException if a compilation error occurs + */ + public boolean compile(JAXXCompiler compiler) throws CompilerException { + + if (compiled) { + throw new IllegalStateException(this + " has already been compiled"); + } + + DataBindingHelper bindingHelper = compiler.getBindingHelper(); + + // obtain a safe id + realId = bindingHelper.getSafeId(id.trim()); + + // compute the constant id of the binding + constantId = TypeManager.convertVariableNameToConstantName("binding_" + realId); + + dataSource = new DataSource(realId, constantId, getSource(), compiler, methods); + + // compile binding + + boolean binding = dataSource.compile(); + + if (!binding) { + + // free the generated id + + bindingHelper.revertSafeId(id.trim()); + } + + // was compiled + compiled = true; + + if (dataSource.showLog()) { + if (binding) { + log.info("detect a databinding : " + this); + } else { + log.info("reject a databinding : " + getSource()); + } + } + + // compute initDataBinding code + + initDataBinding = getInitDataBindingCode(compiler, dataSource, binding); + + // compute processDataBinding code + + processDataBinding = getProcessDataBindingCode(compiler, dataSource, binding); + + Set<String> ids = dataSource.getOverrideIds(); + + if (binding && ids != null && !ids.isEmpty()) { + + // there is some overrides, check trackers + DataListener[] listeners = dataSource.getTrackers(); + for (DataListener listener : listeners) { + String code = listener.getAddListenerCode(); + String newCode = replaceOverrides(compiler, ids, code); + if (code.equals(newCode)) { + listener.addListenerCode = newCode; + if (dataSource.showLog()) { + log.info("Replace overrides [" + code + "] --> [" + newCode + "]"); + } + } + code = listener.getRemoveListenerCode(); + newCode = replaceOverrides(compiler, ids, code); + if (code.equals(newCode)) { + listener.removeListenerCode = newCode; + if (dataSource.showLog()) { + log.info("Replace overrides [" + code + "] --> [" + newCode + "]"); + } + } + } + } + return binding; + } + + protected String getInitDataBindingCode(JAXXCompiler compiler, DataSource dataSource, boolean isBinding) { + String eol = JAXXCompiler.getLineSeparator(); + if (isBinding) { + return null; + } + if (isQuickNoDependencies()) { + // layout is specially handled early in the chain + if (!id.endsWith(".layout")) { + return getAssignment() + eol; + } + } + return null; + } + + protected String getProcessDataBindingCode(JAXXCompiler compiler, DataSource dataSource, boolean isBinding) { + if (!isBinding) { + // no binding = no process code + return null; + } + String eol = JAXXCompiler.getLineSeparator(); + StringBuilder buffer = new StringBuilder(); + + String objectCode = dataSource.getObjectCode(); + + Set<String> overrideIds = dataSource.getOverrideIds(); + // no need to test objectCode not null if on root object + boolean needTest = objectCode != null && !objectCode.trim().isEmpty() && !compiler.getRootObject().getId().equals(objectCode + " != null"); + if (needTest) { + + objectCode = replaceOverrides(compiler, overrideIds, objectCode); + + buffer.append("if (").append(objectCode).append(") {").append(eol); + } + String assignment = getAssignment(compiler, overrideIds); + buffer.append(JavaFileGenerator.indent(assignment, needTest ? 4 : 0, false, eol)); + if (needTest) { + buffer.append(eol).append("}"); + } + return buffer.toString(); + } + + protected String getAssignment(JAXXCompiler compiler, Set<String> overrides) { + String s = getAssignment(); + + s = replaceOverrides(compiler, overrides, s); + + return s; + } + + protected String replaceOverrides(JAXXCompiler compiler, Set<String> overrides, String code) { + if (overrides != null && !overrides.isEmpty()) { + String tmp = code; + for (String override : overrides) { + CompiledObject o = compiler.getCompiledObject(override); + tmp = tmp.replaceAll(override + "\\.", o.getGetterName() + "()."); +// tmp = tmp.replaceFirst(override + ".", o.getJavaCode() + "."); + } + if (dataSource.showLog()) { + log.info("Assignment with overrides [" + code + "] to [" + tmp + "]"); + } + code = tmp; + } + return code; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/DataBindingHelper.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/DataBindingHelper.java new file mode 100644 index 0000000..02d10bf --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/DataBindingHelper.java @@ -0,0 +1,260 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.binding; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Helper to be used by compiler to treate data bindings. + * + * Note : The code in this class was previously directly in JAXXCompiler, now prefer have a separate + * class to make {@link JAXXCompiler} more simple and clear. + * + * Created: 27 nov. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.0 + */ +public class DataBindingHelper { + + /** To debug binding without any log interference */ + public static boolean SHOW_LOG; + + /** left brace matcher */ + protected static final Matcher leftBraceMatcher = Pattern.compile("^(\\{)|[^\\\\](\\{)").matcher(""); + + /** right brace matcher */ + protected static final Matcher rightBraceMatcher = Pattern.compile("^(\\})|[^\\\\](\\})").matcher(""); + + /** + * Registred data binding for the compiler, then after the invocation of method {@link #finalizeBindings()} + * only the real data bindings, the simple bindings will be moved to {@link #simpleBindings}. + */ + protected final List<DataBinding> dataBindings = new ArrayList<>(); + + /** Simpel bindings for the compiler */ + protected final List<DataBinding> simpleBindings = new ArrayList<>(); + + /** Associated compiler */ + protected final JAXXCompiler compiler; + + /** Counter by unsafe type */ + protected final Map<String, Integer> autoUnsafeGenIds = new TreeMap<>(); + + public DataBindingHelper(JAXXCompiler compiler) { + this.compiler = compiler; + } + + /** + * Examine an attribute value for data binding expressions. Returns a 'cooked' expression which + * can be used to determine the resulting value. It is expected that this expression will be used + * as the source expression in a call to {@link #registerDataBinding}. + * If the attribute value does not invoke data binding, this method returns <code>null</code> + * + * @param stringValue the string value of the property from the XML + * @return a processed version of the expression + * @throws CompilerException ? + */ + public static String processDataBindings(String stringValue) throws CompilerException { + int pos = getNextLeftBrace(stringValue, 0); + if (pos != -1) { + StringBuilder expression = new StringBuilder(); + int lastPos = 0; + while (pos != -1 && pos < stringValue.length()) { + if (pos > lastPos) { + if (expression.length() > 0) { + expression.append(" + "); + } + expression.append('"'); + expression.append(JAXXCompiler.escapeJavaString(stringValue.substring(lastPos, pos))); + expression.append('"'); + } + boolean multi = expression.length() > 0; + if (multi) { + expression.append(" + "); + expression.append('('); + } + int pos2 = getNextRightBrace(stringValue, pos + 1); + if (pos2 == -1) { + throw new CompilerException("unmatched '{' in expression: " + stringValue); + } + expression.append(stringValue.substring(pos + 1, pos2)); + if (multi) { + expression.append(')'); + } + pos2++; + if (pos2 < stringValue.length()) { + pos = getNextLeftBrace(stringValue, pos2); + lastPos = pos2; + } else { + pos = stringValue.length(); + lastPos = pos; + } + } + if (lastPos < stringValue.length()) { + if (expression.length() > 0) { + expression.append(" + "); + } + expression.append('"'); + expression.append(JAXXCompiler.escapeJavaString(stringValue.substring(lastPos))); + expression.append('"'); + } + //TC-20091027 : developper must write extact databinding + // the fact of adding the String boxed for String type binding is not + // a good thing, since it add one more call to process in binding + // and add nothing special more ? +// return type == ClassDescriptorHelper.getClassDescriptor(String.class) ? "String.valueOf(" + expression + ")" : expression.toString(); + return expression.toString(); + } + return null; + } + + public DataBinding[] getDataBindings() { + return dataBindings.toArray(new DataBinding[dataBindings.size()]); + } + + public DataBinding[] getSimpleBindings() { + return simpleBindings.toArray(new DataBinding[simpleBindings.size()]); + } + + public void registerDataBinding(String id, String binding, String assignment) { + binding = compiler.checkJavaCode(binding); + registerDataBinding(new DataBinding(id, binding, assignment, true)); + } + + public void registerDataBinding(DataBinding binding) { + dataBindings.add(binding); + } + + public void clear() { + simpleBindings.clear(); + dataBindings.clear(); + autoUnsafeGenIds.clear(); + } + + /** + * Obtain the next safe id for the given binding id. + * + * With css, we can obtain the same binding id, so we must + * check for unicity each time we want a new binding id. + * + * If an id is already taken, we suffix by {@code _XXX} until + * found a free id. + * + * @param id the id of the binding + * @return the safe id of the binding + */ + public String getSafeId(String id) { + + Integer integer = autoUnsafeGenIds.get(id); + String result = id; + if (integer == null) { + integer = 0; + } else { + result += "_" + integer; + } + autoUnsafeGenIds.put(id, ++integer); + return result; + } + + /** + * Revert a previous computed safe id. + * + * This is needed when a binding compiled is not an data binding, we want to free + * the safe id to avoid hole in numbers. + * + * @param id the original id to revert in counter. + */ + public void revertSafeId(String id) { + Integer integer = autoUnsafeGenIds.get(id); + if (integer != null) { + integer--; + if (integer > 0) { + autoUnsafeGenIds.put(id, integer); + } else { + autoUnsafeGenIds.remove(id); + } + } + } + + /** + * Compile all binding discovered previously. + * + * If a binding is not a dataBinding, then move it from the list {@link #dataBindings} to {@link #simpleBindings}. + */ + public void finalizeBindings() { + + for (Iterator<DataBinding> itr = dataBindings.iterator(); itr.hasNext(); ) { + DataBinding binding = itr.next(); + boolean isBinding = binding.compile(compiler); + if (!isBinding) { + // ce n'est pas un binding, on enregistre le code d'init (si il existe) + simpleBindings.add(binding); + // on supprime le faux binding + itr.remove(); + } + } + } + + protected static int getNextLeftBrace(String string, int pos) { + leftBraceMatcher.reset(string); + return leftBraceMatcher.find(pos) ? Math.max(leftBraceMatcher.start(1), leftBraceMatcher.start(2)) : -1; + } + + protected static int getNextRightBrace(String string, int pos) { + leftBraceMatcher.reset(string); + rightBraceMatcher.reset(string); + int openCount = 1; + int rightPos; + while (openCount > 0) { + pos++; + int leftPos = leftBraceMatcher.find(pos) ? + Math.max(leftBraceMatcher.start(1), leftBraceMatcher.start(2)) : + -1; + rightPos = rightBraceMatcher.find(pos) ? + Math.max(rightBraceMatcher.start(1), rightBraceMatcher.start(2)) : + -1; + assert leftPos == -1 || leftPos >= pos; + assert rightPos == -1 || rightPos >= pos; + if (leftPos != -1 && leftPos < rightPos) { + pos = leftPos; + openCount++; + } else if (rightPos != -1) { + pos = rightPos; + openCount--; + } else { + openCount = 0; + } + } + return pos; + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/DataListener.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/DataListener.java new file mode 100644 index 0000000..423ec22 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/DataListener.java @@ -0,0 +1,93 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.binding; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * Created: 5 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + * + * Mise a jour: $Date$ par : + * $Author$ + */ +public class DataListener { + + /** + * Unique id of the data listener (should be something like objectId.propertyName + */ + protected final String symbol; + + /** + * the nullity test to do before to add or remove the listener + */ + protected final String objectCode; + + /** + * code of the add listener + */ + protected String addListenerCode; + + /** + * code of the remove listener + */ + protected String removeListenerCode; + + public DataListener(String symbol, + String objectCode, + String addListenerCode, + String removeListenerCode) { + this.symbol = symbol; + this.objectCode = objectCode; + this.addListenerCode = addListenerCode; + this.removeListenerCode = removeListenerCode; + } + + public String getSymbol() { + return symbol; + } + + public String getObjectCode() { + return objectCode; + } + + public String getAddListenerCode() { + return addListenerCode; + } + + public String getRemoveListenerCode() { + return removeListenerCode; + } + + @Override + public String toString() { + ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); + b.append("symbol", symbol); + b.append("objectCode", objectCode); + b.append("addListenerCode", addListenerCode.trim()); + b.append("removeListenerCode", removeListenerCode.trim()); + return b.toString(); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/DataSource.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/DataSource.java new file mode 100644 index 0000000..94750c9 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/DataSource.java @@ -0,0 +1,882 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.binding; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.UnsupportedAttributeException; +import org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import org.nuiton.jaxx.compiler.java.JavaElementFactory; +import org.nuiton.jaxx.compiler.java.JavaFileGenerator; +import org.nuiton.jaxx.compiler.java.JavaMethod; +import org.nuiton.jaxx.compiler.java.parser.JavaParser; +import org.nuiton.jaxx.compiler.java.parser.JavaParserConstants; +import org.nuiton.jaxx.compiler.java.parser.JavaParserTreeConstants; +import org.nuiton.jaxx.compiler.java.parser.SimpleNode; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.reflect.FieldDescriptor; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; +import org.nuiton.jaxx.compiler.tags.DefaultObjectHandler; +import org.nuiton.jaxx.compiler.tags.TagManager; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.Introspector; +import java.io.StringReader; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Represents a Java expression which fires a <code>PropertyChangeEvent</code> when it can be + * determined that its value may have changed. Events are fired on a "best effort" basis, and events + * may either be fired too often (the value has not actually changed) or not often enough (the value + * changed but no event was fired). + */ +public class DataSource { + + /** Logger */ + protected static final Log log = LogFactory.getLog(DataSource.class); + + /** type attached to "null" constants in parsed expressions */ + private class NULL { + } + + /** id of data source */ + private final String id; + + /** Constant id */ + protected final String constantId; + + /** The Java source code for the expression. */ + private final String source; + + /** The current <code>JAXXCompiler</code>. */ + private final JAXXCompiler compiler; + + /** List of detected tracker (if none found, it is not a data binding) */ + private final List<DataListener> trackers; + + /** the delegate of property to be required */ + private String objectCode; + + protected final List<JavaMethod> methods; + + /** + * Creates a new data source. After creating a <code>DataSource</code>, use {@link #compile()} + * to cause it to function at runtime. + * + * @param id the DataSource's id + * @param constantId the DataSource constant id + * @param source the Java source code for the data source expression + * @param compiler the current <code>JAXXCompiler</code> + * @param methods where to store extra method to add to binding + */ + public DataSource(String id, + String constantId, + String source, + JAXXCompiler compiler, + List<JavaMethod> methods) { + this.id = id; + this.constantId = constantId; + this.source = source; + this.compiler = compiler; + this.methods = methods; + trackers = new ArrayList<>(); + } + + public String getObjectCode() { + return objectCode; + } + + public DataListener[] getTrackers() { + return trackers.toArray(new DataListener[trackers.size()]); + } + + @Override + public String toString() { + ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); + b.append("source:id", id); + b.append("source:source", source); + b.append("source:objectCode", getObjectCode()); + if (!trackers.isEmpty()) { + b.append("source:trackers", trackers.size()); + for (DataListener d : trackers) { + b.append("source:tracker", d); + } + } + return b.toString(); + } + + public boolean showLog() { +// return DataBindingHelper.SHOW_LOG || log.isDebugEnabled(); + return DataBindingHelper.SHOW_LOG; + } + + /** + * Compiles the data source expression and listener. This method calls methods in <code>JAXXCompiler</code> + * to add the Java code that performs the data source setup. Adding listeners to <code>DataSource</code> is + * slightly more complicated than with ordinary classes, because <code>DataSource</code> only exists at compile + * time. You must pass in a Java expression which evaluates to a <code>PropertyChangeListener</code>; this + * expression will be compiled and evaluated at runtime to yield the <code>DataSource's</code> listener. + * + * @return <code>true</code> if the expression has dependencies, <code>false</code> otherwise + * @throws CompilerException if a compilation error occurs + * @throws IllegalStateException if data source was already compiled + */ + protected boolean compile() throws CompilerException, IllegalStateException { + + if (showLog()) { + log.info("======= Start compile of " + source); + } + JavaParser p = new JavaParser(new StringReader(source)); + + // detect all expressions to treate + Map<SimpleNode, List<SimpleNode>> expressions = new LinkedHashMap<>(); + Map<SimpleNode, List<SimpleNode>> castsExpressions = new LinkedHashMap<>(); + List<SimpleNode> literalExpressions = new ArrayList<>(); + while (!p.Line()) { + SimpleNode node = p.popNode(); + if (log.isTraceEnabled()) { + log.trace("will scan node " + node.getText()); + } + JavaParserUtil.getExpressions(node, expressions, literalExpressions, castsExpressions); + } + + // remove literal expressions + + JavaParserUtil.removeLiteralExpressions(expressions, literalExpressions); + literalExpressions.clear(); + + // remove expressions with dependencies + + JavaParserUtil.removeNoneStandaloneExpressions(expressions, castsExpressions); + + // scan accepted expressions to detect dependencies and track listeners + + for (SimpleNode node : expressions.keySet()) { + if (showLog()) { + log.info("Will parse expression " + node.getText()); + } + scanNode(node); + } + + if (log.isDebugEnabled()) { + log.debug("trackers=" + trackers); + } + + boolean isBinding = !trackers.isEmpty(); + if (isBinding) { + + Set<String> result = JavaParserUtil.getRequired(expressions.keySet(), castsExpressions); + + if (result == null || result.isEmpty()) { + + // no requirements + + objectCode = ""; + } else { + + // build the fully test from requirements + + StringBuilder buffer = new StringBuilder(); + + Iterator<String> itr = result.iterator(); + + overrideIds = new HashSet<>(); + + String realSource = getJavaCode(itr.next()); + buffer.append(realSource).append(" != null"); + while (itr.hasNext()) { + realSource = getJavaCode(itr.next()); + buffer.append(" && ").append(realSource).append(" != null"); + } + objectCode = buffer.toString().trim(); + } + } + castsExpressions.clear(); + expressions.clear(); + return isBinding; + } + + private Set<String> overrideIds; + + private String getJavaCode(String s) { + CompiledObject o = compiler.getCompiledObject(s); + if (o != null && o.isOverride()) { + + if (showLog()) { + log.info("Use an override identifier : " + o.getJavaCode()); + } + + overrideIds.add(s); + } + return s; + } + + public Set<String> getOverrideIds() { + return overrideIds; + } + + /** + * Examines a node to identify any dependencies it contains. + * + * @param node node to scan + * @throws CompilerException ? + */ + private void scanNode(SimpleNode node) throws CompilerException { + if (node.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION || + node.getId() == JavaParserTreeConstants.JJTFIELDDECLARATION) { + return; + } + if (log.isTraceEnabled()) { + log.trace(node.getText()); + } + int count = node.jjtGetNumChildren(); + for (int i = 0; i < count; i++) { + scanNode(node.getChild(i)); + } + // determine node type + ClassDescriptor type = null; + if (node.jjtGetNumChildren() == 1) { + type = node.getChild(0).getJavaType(); + } + switch (node.getId()) { + case JavaParserTreeConstants.JJTCLASSORINTERFACETYPE: + type = ClassDescriptorHelper.getClassDescriptor(Class.class); + break; + case JavaParserTreeConstants.JJTPRIMARYEXPRESSION: + type = determineExpressionType(node); + if (log.isDebugEnabled()) { + log.debug("result of determineExpressionType for " + node.getText() + " = " + type); + } + break; + case JavaParserTreeConstants.JJTLITERAL: + type = determineLiteralType(node); + break; + case JavaParserTreeConstants.JJTCASTEXPRESSION: + type = TagManager.resolveClass(node.getChild(0).getText(), compiler); + break; + } + node.setJavaType(type); + } + + /** + * Adds type information to nodes where possible, and as a side effect adds event listeners to nodes which + * can be tracked. + * + * @param expression the node to scan + * @return the class descriptor of the return type or null + */ + private ClassDescriptor determineExpressionType(SimpleNode expression) { + assert expression.getId() == JavaParserTreeConstants.JJTPRIMARYEXPRESSION; + SimpleNode prefix = expression.getChild(0); + if (log.isDebugEnabled()) { + log.debug("for expression " + expression.getText() + " - prefix " + prefix + " - nb childrens of prefix: " + prefix.jjtGetNumChildren() + ", nb childrens of expression : " + expression.jjtGetNumChildren()); + } + + if (prefix.jjtGetNumChildren() == 1) { + int type = prefix.getChild(0).getId(); + if (type == JavaParserTreeConstants.JJTLITERAL || type == JavaParserTreeConstants.JJTEXPRESSION) { + prefix.setJavaType(prefix.getChild(0).getJavaType()); + } else if (type == JavaParserTreeConstants.JJTNAME && expression.jjtGetNumChildren() == 1) { + // name with no arguments after it + ClassDescriptor classDescriptor = scanCompoundSymbol(prefix.getText().trim(), compiler.getRootObject().getObjectClass(), false); + if (log.isTraceEnabled()) { + log.trace("scanCompoundSymbol result for node " + prefix.getText().trim() + " = " + classDescriptor); + } + prefix.setJavaType(classDescriptor); + } + } + + if (expression.jjtGetNumChildren() == 1) { + return prefix.getJavaType(); + } + + ClassDescriptor contextClass = prefix.getJavaType(); + if (contextClass == null) { + contextClass = compiler.getRootObject().getObjectClass(); + } + String lastNode = prefix.getText().trim(); + + for (int i = 1; i < expression.jjtGetNumChildren(); i++) { + SimpleNode suffix = expression.getChild(i); + if (suffix.jjtGetNumChildren() == 1 && suffix.getChild(0).getId() == JavaParserTreeConstants.JJTARGUMENTS) { + if (suffix.getChild(0).jjtGetNumChildren() == 0) { + // at the moment only no-argument methods are trackable + contextClass = scanCompoundSymbol(lastNode, contextClass, true); + if (log.isTraceEnabled()) { + log.trace("scanCompoundSymbol result for node " + lastNode + " = " + contextClass); + } + if (contextClass == null) { + return null; + } + int dotPos = lastNode.lastIndexOf("."); + String code = dotPos == -1 ? "" : lastNode.substring(0, dotPos); + for (int j = i - 2; j >= 0; j--) { + code = expression.getChild(j).getText() + code; + } + if (code.length() == 0) { + code = compiler.getRootObject().getJavaCode(); + } + String methodName = lastNode.substring(dotPos + 1).trim(); + if (log.isTraceEnabled()) { + log.trace("try to find type for method " + methodName + ", code : " + code); + } + try { + MethodDescriptor method = contextClass.getMethodDescriptor(methodName); + if (log.isDebugEnabled()) { + log.debug("Will trackMemberIfPossible from method " + method.getName() + " with objectCode = " + code); + } + trackMemberIfPossible(code, contextClass, method.getName(), true); + if (log.isTraceEnabled()) { + log.trace("method found = " + method); + } + return getMethodReturnType(contextClass, method); + } catch (NoSuchMethodException e) { + if (showLog()) { + log.info("Could not find method " + methodName + ", code : " + code + " on : " + contextClass); + if (log.isDebugEnabled()) { + for (MethodDescriptor descriptor : contextClass.getMethodDescriptors()) { + log.debug(" - " + Modifier.toString(descriptor.getModifiers()) + " " + descriptor.getName() + "(...) : " + descriptor.getReturnType()); + } + } + } + // happens for methods defined in the current JAXX file via scripts + String propertyName = null; + if (methodName.startsWith("is")) { + propertyName = Introspector.decapitalize(methodName.substring("is".length())); + } else if (methodName.startsWith("get")) { + propertyName = Introspector.decapitalize(methodName.substring("get".length())); + } + if (propertyName != null) { + //TC-20091026 use the getScriptMethod from compiler + MethodDescriptor newMethod = compiler.getScriptMethod(methodName); + if (newMethod != null) { + //TC-20091202 must suffix dependency by property, otherwise can not have two bindings + // on the same parent... + String bindingId = compiler.getRootObject().getId() + "." + propertyName; + if (log.isDebugEnabled()) { + log.debug("detect a dependency [" + bindingId + "] from a script method " + newMethod.getName() + ", will try to add a listener in method is part of javaBean ..."); + } + // check this is a javaBean + CompiledObject compiledObject = compiler.getObjects().get(propertyName); + if (compiledObject != null && compiledObject.isJavaBean()) { + String objectCode = null; + if (showLog()) { + log.info("Detect a dependency from compiled object [" + objectCode + "]a script method '" + newMethod.getName() + "' which reflect a javaBean property " + propertyName); + log.info("Try to add a listener [symbol:" + bindingId + ",objectCode:" + objectCode + "]"); + log.debug(">> lastnode = " + lastNode + "(), suffix = " + suffix.getText() + ", expression = " + expression.getText()); + } + addListener(bindingId, + objectCode, + "addPropertyChangeListener(\"" + propertyName + "\", this);" + JAXXCompiler.getLineSeparator(), + "removePropertyChangeListener(\"" + propertyName + "\", this);" + JAXXCompiler.getLineSeparator()); + } + contextClass = newMethod.getReturnType(); + } + } + } + } + } + lastNode = suffix.getText().trim(); + if (lastNode.startsWith(".")) { + lastNode = lastNode.substring(1); + } + } + + return null; + } + + private ClassDescriptor determineLiteralType(SimpleNode node) { + assert node.getId() == JavaParserTreeConstants.JJTLITERAL; + if (node.jjtGetNumChildren() == 1) { + int childId = node.getChild(0).getId(); + if (childId == JavaParserTreeConstants.JJTBOOLEANLITERAL) { + return ClassDescriptorHelper.getClassDescriptor(boolean.class); + } + if (childId == JavaParserTreeConstants.JJTNULLLITERAL) { + return ClassDescriptorHelper.getClassDescriptor(NULL.class); + } + throw new RuntimeException("Expected BooleanLiteral or NullLiteral, found " + JavaParserTreeConstants.jjtNodeName[childId]); + } + int nodeId = node.firstToken.kind; + switch (nodeId) { + case JavaParserConstants.INTEGER_LITERAL: + if (node.firstToken.image.toLowerCase().endsWith("l")) { + return ClassDescriptorHelper.getClassDescriptor(long.class); + } + return ClassDescriptorHelper.getClassDescriptor(int.class); + case JavaParserConstants.CHARACTER_LITERAL: + return ClassDescriptorHelper.getClassDescriptor(char.class); + case JavaParserConstants.FLOATING_POINT_LITERAL: + if (node.firstToken.image.toLowerCase().endsWith("f")) { + return ClassDescriptorHelper.getClassDescriptor(float.class); + } + return ClassDescriptorHelper.getClassDescriptor(double.class); + case JavaParserConstants.STRING_LITERAL: + return ClassDescriptorHelper.getClassDescriptor(String.class); + default: + throw new RuntimeException("Expected literal token, found " + JavaParserConstants.tokenImage[nodeId]); + } + } + + /** + * Scans through a compound symbol (foo.bar.baz) to identify and track all trackable pieces of it. + * + * @param symbol symbol to scan + * @param contextClass current class context + * @param isMethod flag to search a method + * @return the type of the symbol (or null if it could not be determined). + */ + private ClassDescriptor scanCompoundSymbol(String symbol, ClassDescriptor contextClass, boolean isMethod) { + String[] tokens = symbol.split("\\s*\\.\\s*"); + if (log.isDebugEnabled()) { + log.debug("for symbol " + symbol + ", contextClass " + contextClass + ", isMethod " + isMethod); + log.debug("tokens " + Arrays.toString(tokens)); + } + StringBuilder currentSymbol = new StringBuilder(); + StringBuilder tokensSeenSoFar = new StringBuilder(); + // if this ends up false, it means we weren't able to figure out + boolean accepted; + // which object the method is being invoked on + boolean recognizeClassNames = true; + for (int j = 0; j < tokens.length - (isMethod ? 1 : 0); j++) { + accepted = false; + + if (tokensSeenSoFar.length() > 0) { + tokensSeenSoFar.append('.'); + } + tokensSeenSoFar.append(tokens[j]); + if (currentSymbol.length() > 0) { + currentSymbol.append('.'); + } + currentSymbol.append(tokens[j]); + if (log.isTraceEnabled()) { + log.trace("try to find type for " + currentSymbol); + } + if (currentSymbol.indexOf(".") == -1) { + String memberName = currentSymbol.toString(); + CompiledObject object = compiler.getCompiledObject(memberName); + if (object != null) { + if (log.isTraceEnabled()) { + log.trace("detected an object " + object); + } + contextClass = object.getObjectClass(); + currentSymbol.setLength(0); + accepted = true; + recognizeClassNames = false; + } else { + try { + FieldDescriptor field = contextClass.getFieldDescriptor(memberName); + if (log.isDebugEnabled()) { + log.debug("Will trackMemberIfPossible from field " + field.getName() + " with objectCode = " + tokensSeenSoFar.toString()); + } + trackMemberIfPossible(tokensSeenSoFar.toString(), contextClass, field.getName(), false); + try { + contextClass = field.getType(); + } catch (Exception e) { + log.warn("could not find type for field " + field); + throw new NoSuchFieldException(e.getMessage()); + } + + currentSymbol.setLength(0); + accepted = true; + recognizeClassNames = false; + } catch (NoSuchFieldException e) { + if (j == 0 || j == 1 && tokens[0].equals(compiler.getRootObject().getId())) { + // still in root context + FieldDescriptor newField = compiler.getScriptField(memberName); + if (newField != null) { + contextClass = newField.getType(); + if (showLog()) { + log.info("Detect a dependency from a script field '" + newField + "'"); + log.info("Try to add a listenenr [symbol:" + tokensSeenSoFar.toString() + ",objectCode:" + null + "]"); + } + String eol = JAXXCompiler.getLineSeparator(); + addListener(tokensSeenSoFar.toString(), + null, + "addPropertyChangeListener(\"" + memberName + "\", this);" + eol, +// "addPropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + eol, + "removePropertyChangeListener(\"" + memberName + "\", this);" + eol); +// "removePropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + eol); + + assert contextClass != null : "script field '" + memberName + "' is defined, but has type null"; + currentSymbol.setLength(0); + accepted = true; + recognizeClassNames = false; + } + } + } + } + } + if (currentSymbol.length() > 0 && recognizeClassNames) { + if (log.isDebugEnabled()) { + log.debug("Try to recognizeClassNames for symbol " + currentSymbol); + } + contextClass = TagManager.resolveClass(currentSymbol.toString(), compiler); + if (contextClass != null) { + currentSymbol.setLength(0); + //accepted = true; + //recognizeClassNames = false; + // TODO: for now we don't handle statics + return null; + } + } + if (!accepted) { + if (log.isDebugEnabled()) { + log.debug("symbol " + symbol + " was not accepted."); + } + return null; + } + } + + return contextClass; + } + + private void trackMemberIfPossible(String objectCode, ClassDescriptor objectClass, String memberName, boolean method) { + + if (log.isDebugEnabled()) { + log.debug("for [objectCode:" + objectCode + ", objectClass:" + objectClass + ", memberName:" + memberName + ", isMethod:" + method); + } + DefaultObjectHandler handler = TagManager.getTagHandler(objectClass); + try { + if (handler.isMemberBound(memberName)) { + String bindingId = objectCode + "." + memberName + (method ? "()" : ""); + if (showLog()) { + log.info("Detect a dependency from a event handler for memberName '" + memberName + "' for class " + objectClass); + log.info("Try to add a listener [symbol:" + bindingId + ", objectCode:" + objectCode + "]"); + } + addListener(bindingId, + objectCode, + getAddMemberListenerCode(handler, objectCode, memberName, "this", compiler), + getRemoveMemberListenerCode(handler, objectCode, memberName, "this", compiler)); + } + } catch (UnsupportedAttributeException e) { + // ignore -- this is thrown for methods like toString(), for which there is no tracking and + // no setting support + } + } + + private void addListener(String dependencySymbol, + String objectCode, + String addCode, + String removeCode) { + if (objectCode != null) { + objectCode = objectCode.trim(); + } + boolean needTest = objectCode != null && + !compiler.getRootObject().getId().equals(objectCode); + if (!needTest) { + objectCode = null; + } + if (log.isDebugEnabled()) { + log.debug("try to add listener [dependencySymbol:" + + dependencySymbol + ", objectCode:" + objectCode + + ", addCode:" + addCode + "]"); + } + + for (DataListener tracker : trackers) { + if (dependencySymbol.equals(tracker.getSymbol())) { + // listener already existing + return; + } + } + DataListener tracker = new DataListener(dependencySymbol, + objectCode, + addCode, + removeCode + ); + if (log.isDebugEnabled()) { + log.debug("add tracker " + tracker); + } + trackers.add(tracker); + } + + public boolean hasMethod(String methodName) { + for (JavaMethod method : methods) { + if (methodName.equals(method.getName())) { + return true; + } + } + return false; + } + + /** + * Returns a snippet of Java code which will cause a <code>PropertyChangeListener</code> to be notified + * when the member's value changes. The <code>PropertyChangeListener</code> is provided in the form + * of a Java code snippet that evaluates to a listener object. + * + * For ordinary bound JavaBeans properties, the Java code returned is a simple call to + * <code>addPropertyChangeListener</code>. Fields and methods which do not actually fire + * <code>PropertyChangeEvents</code> when they change necessitate more complex code. + * + * @param handler Object handler (containts known events + * @param objectCode Java code which evaluates to the object to which to add the listener + * *@param dataBinding the name of the data binding this listener is a part of + * @param memberName the name of the field or method to listen to + * @param propertyChangeListenerCode Java code which evaluates to a <code>PropertyChangeListener</code> + * @param compiler the current <code>JAXXCompiler</code> + * @return Java code snippet which causes the listener to be added to the object + */ + public String getAddMemberListenerCode(DefaultObjectHandler handler, + String objectCode, + String memberName, + String propertyChangeListenerCode, + JAXXCompiler compiler) { + if ("getClass".equals(memberName)) { + return null; + } + + DefaultObjectHandler.ProxyEventInfo eventInfo = handler.getEventInfo(memberName); + if (eventInfo != null) { + // a "proxied" event is one that doesn't fire PropertyChangeEvent, so we need to convert its native event type into PropertyChangeEvents + StringBuilder result = new StringBuilder(); + String methodName = "$pr" + compiler.getUniqueId(propertyChangeListenerCode.equals("this") ? constantId : propertyChangeListenerCode); + boolean methodExists = hasMethod(methodName); + ClassDescriptor eventClass = DefaultObjectHandler.getEventClass(eventInfo.getListenerClass()); + String type = compiler.getImportedType(JAXXCompiler.getCanonicalName(eventClass)); + if (!methodExists) { + String code = JavaFileGenerator.addDebugLoggerInvocation(compiler, "event"); + code += "propertyChange(null);"; + JavaMethod method = JavaElementFactory.newMethod( + Modifier.PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + methodName, + code, + false, + JavaElementFactory.newArgument(type, "event")); + methods.add(method); + } + String code = objectCode + (eventInfo.getModelName() != null ? ".get" + StringUtils.capitalize(eventInfo.getModelName()) + "()" : ""); + result.append("$bindingSources.put(\"").append(code).append("\", ").append(code).append(");").append(JAXXCompiler.getLineSeparator()); + //TC-20091105 JAXXUtil.getEventListener is generic, no more need cast and use simple listener name + ClassDescriptor listenerClass = eventInfo.getListenerClass(); + String listenerType = compiler.getImportedType(listenerClass.getName()); + String jaxxUtilPrefix = compiler.getImportedType(JAXXUtil.class); + result.append(code); + result.append('.'); + result.append(eventInfo.getAddMethod()); + result.append("( ").append(jaxxUtilPrefix).append(".getEventListener("); + result.append(listenerType); + result.append(".class, "); + result.append("this"); + result.append(", "); + result.append(TypeManager.getJavaCode(methodName)); + result.append("));"); + result.append(JAXXCompiler.getLineSeparator()); + if (eventInfo.getModelName() != null) { + String addCode = getAddMemberListenerCode( + handler, + objectCode, + "get" + StringUtils.capitalize(eventInfo.getModelName()), + jaxxUtilPrefix + ".getDataBindingUpdateListener(" + compiler.getOutputClassName() + ".this" + ", " + constantId + ")", + compiler + ); + result.append(addCode); + } + return result.toString(); + } + String propertyName = null; + if (memberName.startsWith("get")) { + propertyName = Introspector.decapitalize(memberName.substring(3)); + } else if (memberName.startsWith("is")) { + propertyName = Introspector.decapitalize(memberName.substring(2)); + } else { + try { + handler.getBeanClass().getFieldDescriptor(memberName); + propertyName = memberName; + } catch (NoSuchFieldException e) { + // ignore ? + } + } + if (propertyName != null) { + //TC-20091026 when on root object, do not prefix with objectCode + String prefix = objectCode.trim() + "."; + if (objectCode.equals(compiler.getRootObject().getJavaCode())) { + prefix = ""; + } + //TC-20091203 : always use the property specific method, this is part of the javaBeans 1.1 norm + //TC-20091203 : if developpers do bad, shame on them... + return prefix + "addPropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; + +// try { +// // check for property-specific addPropertyChangeListener method +//// getBeanClass().getMethodDescriptor("addPropertyChangeListener", ClassDescriptorHelper.getClassDescriptor(String.class), +// handler.getBeanClass().getMethodDescriptor("addPropertyChangeListener", ClassDescriptorHelper.getClassDescriptor(String.class), +// ClassDescriptorHelper.getClassDescriptor(PropertyChangeListener.class)); +// return prefix + "addPropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; +// } catch (NoSuchMethodException e) { +// if (log.isInfoEnabled()) { +// log.info("Could not get named addPropertyChangeListener on class " + handler.getBeanClass()); +// } +// // no property-specific method, use general one +// return prefix + "addPropertyChangeListener(" + propertyChangeListenerCode + ");\n"; +// } + } + return null; + } + + public String getRemoveMemberListenerCode(DefaultObjectHandler handler, + String objectCode, + String memberName, + String propertyChangeListenerCode, + JAXXCompiler compiler) { + if ("getClass".equals(memberName)) { + return null; + } + + DefaultObjectHandler.ProxyEventInfo eventInfo = handler.getEventInfo(memberName); + if (eventInfo != null) { + // a "proxied" event is one that doesn't fire PropertyChangeEvent, + // so we need to convert its native event type into PropertyChangeEvents + StringBuilder result = new StringBuilder(); + String methodName = "$pr" + compiler.getUniqueId(propertyChangeListenerCode.equals("this") ? constantId : propertyChangeListenerCode); + boolean methodExists = hasMethod(methodName); + if (!methodExists) { + ClassDescriptor eventClass = DefaultObjectHandler.getEventClass(eventInfo.getListenerClass()); + String type = compiler.getImportedType(JAXXCompiler.getCanonicalName(eventClass)); + String code = JavaFileGenerator.addDebugLoggerInvocation(compiler, "event"); + code += "propertyChange(null);"; + JavaMethod method = JavaElementFactory.newMethod( + Modifier.PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + methodName, + code, + false, + JavaElementFactory.newArgument(type, "event")); + methods.add(method); + } + try { + String modelMemberName = eventInfo.getModelName() != null ? "get" + StringUtils.capitalize(eventInfo.getModelName()) : null; + String modelClassName = modelMemberName != null ? handler.getBeanClass().getMethodDescriptor(modelMemberName).getReturnType().getName() : JAXXCompiler.getCanonicalName(handler.getBeanClass()); + String modelType = compiler.getImportedType(modelClassName); + String code = objectCode + (eventInfo.getModelName() != null ? "." + modelMemberName + "()" : ""); + String eol = JAXXCompiler.getLineSeparator(); + String jaxxUtilPrefix = compiler.getImportedType(JAXXUtil.class); + result.append(modelType).append(" $target = (").append(modelType).append(") $bindingSources.remove(\"").append(code).append("\");").append(eol); + //TC-20091105 test if $target is not null + result.append("if ($target != null) {").append(eol); + //TC-20091105 JAXXUtil.getEventListener is generic, no more need cast and use simple listener name + ClassDescriptor listenerClass = eventInfo.getListenerClass(); + String listenerType = compiler.getImportedType(listenerClass.getName()); + result.append(" $target."); + result.append(eventInfo.getRemoveMethod()); + result.append("( ").append(jaxxUtilPrefix).append(".getEventListener("); + result.append(listenerType); + result.append(".class, "); + result.append("this"); + result.append(", "); + result.append(TypeManager.getJavaCode(methodName)); + result.append("));"); + result.append(eol); + result.append("}").append(eol); + if (eventInfo.getModelName() != null) { + result.append(getRemoveMemberListenerCode(handler, objectCode, "get" + StringUtils.capitalize(eventInfo.getModelName()), + jaxxUtilPrefix + ".getDataBindingUpdateListener(" + compiler.getOutputClassName() + ".this, " + constantId + ")", + compiler)); + } + return result.toString(); + } catch (NoSuchMethodException e) { + throw new CompilerException("Internal error: " + e); + } + } + + String propertyName = null; + if (memberName.startsWith("get")) { + propertyName = Introspector.decapitalize(memberName.substring("get".length())); + } else if (memberName.startsWith("is")) { + propertyName = Introspector.decapitalize(memberName.substring("is".length())); + } else { + try { + handler.getBeanClass().getFieldDescriptor(memberName); + propertyName = memberName; + } catch (NoSuchFieldException e) { + // ignore ? + } + } + if (propertyName == null) { + return null; + } + + String prefix = objectCode.trim() + "."; + if (objectCode.equals(compiler.getRootObject().getJavaCode())) { + prefix = ""; + } + //TC-20091203 : always use the property specific method, this is part of the javaBeans 1.1 norm + //TC-20091203 : if developpers do bad, shame on them... + return prefix + "removePropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; +// try { +// // check for property-specific removePropertyChangeListener method +// handler.getBeanClass().getMethodDescriptor("removePropertyChangeListener", ClassDescriptorHelper.getClassDescriptor(String.class), +// ClassDescriptorHelper.getClassDescriptor(PropertyChangeListener.class)); +// return prefix + "removePropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; +// } catch (NoSuchMethodException e) { +// // no property-specific method, use general one +// return prefix + "removePropertyChangeListener(" + propertyChangeListenerCode + ");\n"; +// } + } + + /** + * Given a method from a given context class, try to obtain his method + * return type. + * + * Sometimes, the return type is unknown (generics can not be bind for + * example). As a fallback, we try if the context class is exactly the + * root context class of the compiler, replace it by the script method with + * same name on which we can have more chance to obtain a return type... + * + * @param contextClass the context class of the method + * @param method the method + * @return the method return type + * @since 2.4.2 + */ + protected ClassDescriptor getMethodReturnType(ClassDescriptor contextClass, + MethodDescriptor method) { + ClassDescriptor returnType = method.getReturnType(); + if (returnType == null && + contextClass.equals(compiler.getRootObject().getObjectClass())) { + + // special case to deal with generics (we need to + // have the concrete type)... + method = compiler.getScriptMethod(method.getName()); + if (method != null) { + returnType = method.getReturnType(); + } + } + return returnType; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/JavaParserUtil.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/JavaParserUtil.java new file mode 100644 index 0000000..1c95557 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/JavaParserUtil.java @@ -0,0 +1,387 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.binding; + +import org.nuiton.jaxx.compiler.java.parser.JavaParserTreeConstants; +import org.nuiton.jaxx.compiler.java.parser.SimpleNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.Introspector; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Created: 4 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + * + * Mise a jour: $Date$ par : + * $Author$ + */ +public class JavaParserUtil { + + /** + * Logger + */ + private static final Log log = LogFactory.getLog(JavaParserUtil.class); + + private static final Comparator<String> STRING_LENGTH_COMPARATOR = new Comparator<String>() { + + @Override + public int compare(String o1, String o2) { + return o1.length() - o2.length(); + } + }; + + /** + * Obtain all expressions of a node and store them in {@code store} with their dependencies expressions. + * + * Also fill the {@code literals} list of literal expressions. + * + * @param node the node to scan + * @param store the store of expressions detected with all the expression which compose the expression (can be empty) + * @param literals the list of literal expressions detected + * @param casts the list of casted expression detected + */ + public static void getExpressions(SimpleNode node, Map<SimpleNode, List<SimpleNode>> store, List<SimpleNode> literals, Map<SimpleNode, List<SimpleNode>> casts) { + + if (node.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION || + node.getId() == JavaParserTreeConstants.JJTFIELDDECLARATION) { + //TODO add all others non intressing type of node to reject directly + return; + } + + if (node.getId() == JavaParserTreeConstants.JJTPRIMARYEXPRESSION) { + // get a primary expression, look for his dependencies + scanForExpressions(node, null, store, literals, casts); + return; + } + + // recurse of childs of node + for (int i = 0, count = node.jjtGetNumChildren(); i < count; i++) { + getExpressions(node.getChild(i), store, literals, casts); + } + + } + + /** + * Remove from expressions store, all literal expressions and dependencies on it. + * + * @param store the store of expressions with theirs dependencies + * @param literalExpressions the unvierse of literal expressions + */ + public static void removeLiteralExpressions(Map<SimpleNode, List<SimpleNode>> store, List<SimpleNode> literalExpressions) { + for (SimpleNode n : literalExpressions) { + + // on supprime toutes les dependences sur les expression literales + // car on en a pas besoin pour decouvrir les expressions qui peuvent etre nulles... + + if (log.isDebugEnabled()) { + log.debug("Reject literal expression " + n.getText()); + } + for (List<SimpleNode> dependencies : store.values()) { + dependencies.remove(n); + } + store.remove(n); + } + } + + /** + * Remove from expressions sotre, all expressions with dependencies. + * + * @param store the store of expressions with their dependencies + * @param castsExpressions list of cast expression to keep + */ + public static void removeNoneStandaloneExpressions(Map<SimpleNode, List<SimpleNode>> store, Map<SimpleNode, List<SimpleNode>> castsExpressions) { + List<SimpleNode> rejectedExpressions = new ArrayList<>(); + + for (Map.Entry<SimpleNode, List<SimpleNode>> e : store.entrySet()) { + + List<SimpleNode> dependencies = e.getValue(); + SimpleNode node = e.getKey(); + if (castsExpressions.containsKey(node)) { + // the expression is part of a cast, need to keep it + continue; + } + if (!dependencies.isEmpty()) { + + // expression with dependencies, don't treate it, but treate all in dependencies :) + rejectedExpressions.add(node); + if (log.isDebugEnabled()) { + log.debug("Reject expression " + node.getText() + " with " + dependencies.size() + " dependencies"); + for (SimpleNode n : dependencies) { + log.debug(" " + n.getText()); + } + } + } + } + + for (SimpleNode node : rejectedExpressions) { + store.remove(node); + } + + rejectedExpressions.clear(); + } + + + public static Set<String> getRequired(Set<SimpleNode> store, Map<SimpleNode, List<SimpleNode>> casts) { + if (store.isEmpty()) { + return null; + } + + Set<SimpleNode> castCodes = new LinkedHashSet<>(); + for (List<SimpleNode> cast : casts.values()) { + for (SimpleNode node : cast) { + castCodes.add(node); + if (log.isDebugEnabled()) { + log.debug("cast = " + node.getText().trim()); + } + } + } + + List<String> result = new ArrayList<>(); + for (SimpleNode node : store) { + String expression = node.getText().trim(); + if (result.contains(expression)) { + // already treated + continue; + } + for (SimpleNode castCode : castCodes) { + String str = castCode.getText().trim(); + int index = expression.indexOf(str); + if (index > -1) { + // got a cast, replace the cast expression, by the simple expression + // we have (CAST)XXX --> XXX + if (log.isDebugEnabled()) { + log.debug("got a cast in expresion " + expression + " = " + castCode); + } + String tmp = ""; + //FIXME : should check this is a complete cast : could be only a conversion... + if (index > 1) { + tmp = expression.substring(0, index - 1); + } + tmp += ((SimpleNode) castCode.jjtGetChild(1)).getText().trim() + expression.substring(index + str.length() + 1); + if (log.isDebugEnabled()) { + log.debug("REMOVED CAST : " + tmp); + } + expression = tmp; + } + } + if (expression.indexOf(".") == -1) { + // not an expression to keep + // a simple field use like 'isEnabled()' or 'field' + // or a not method invocation + if (log.isDebugEnabled()) { + log.debug("Reject simple expression " + expression); + } + continue; + } + if (expression.indexOf("(") == -1) { + // expression with no called method, probably is a constant + // should test it, but for the moment just limits bindings to interfield expressions : a.b + // is not possible, use a.getB() instead of + if (log.isDebugEnabled()) { + log.debug("Reject constant or static expression " + expression); + } + continue; + } + + if (log.isDebugEnabled()) { + log.debug("Keep expression " + expression); + } + result.add(expression); + } + + if (result.isEmpty()) { + return null; + } + + Collections.sort(result, STRING_LENGTH_COMPARATOR); + if (log.isDebugEnabled()) { + log.debug("======= start with values : " + result); + } + + + Set<String> objectCodes = new LinkedHashSet<>(); + + for (String expression : result) { + + // test if we have a cast in this expression + + Set<String> tmp = new LinkedHashSet<>(); + + String[] paths = expression.split("\\s*\\.\\s*"); + if (paths.length < 2) { + // just a simple expression + // TODO Should never come here... + continue; + } + + if (log.isDebugEnabled()) { + log.debug("Expression to treate : " + expression + " :: " + Arrays.toString(paths)); + } + + StringBuilder buffer = new StringBuilder(); + String last = paths[0].trim(); + if (last.indexOf("(") > -1) { + // first path is a method invocation or a cast + // at the moment allow cast only on the first member and do no perform any check + + // must check this is a complete method invocation + String args = getMethodInvocationParameters(last); + if (args == null) { + // this path is not a method invocation + // must break + continue; + } + if (!args.isEmpty()) { + // for the moment, we only accept method with no args + // must break + continue; + } + + } + buffer.append(last); + tmp.add(buffer.toString()); + for (int i = 1, max = paths.length - 1; i < max; i++) { + String s = paths[i].trim(); + String args = getMethodInvocationParameters(s); + if (args == null) { + // this path is not a method invocation + // must break + // if previous + break; + } + if (!args.isEmpty()) { + // for the moment, we only accept method with no args + // must break + break; + } + buffer.append(".").append(s); + last = buffer.toString(); + tmp.add(last); + } + objectCodes.addAll(tmp); + } + + if (log.isDebugEnabled()) { + log.debug("Detected requirements : " + objectCodes); + } + return objectCodes; + } + + public static String getMethodInvocationParameters(String code) { + int openIndex = code.indexOf("("); + int closeIndex = code.lastIndexOf(")"); + if (openIndex > -1 && closeIndex > -1) { + if (closeIndex == openIndex + 1) { + return ""; + } + // missing something + return code.substring(openIndex + 1, closeIndex - 1).trim(); + } + return null; + } + + public static String getPropertyNameFromMethod(String code) { + int openIndex = code.indexOf("("); + if (openIndex != -1) { + code = code.substring(0, openIndex); + } + int index = 3; + if (code.startsWith("is")) { + index = 2; + } + code = code.substring(index); + code = Introspector.decapitalize(code); + return code; + } + + public static void scanForExpressions(SimpleNode node, SimpleNode lastExpressionNode, Map<SimpleNode, List<SimpleNode>> store, List<SimpleNode> literals, Map<SimpleNode, List<SimpleNode>> casts) { + + String nodeExpression = node.getText().trim(); + if (log.isTraceEnabled()) { + log.trace("node " + node.getId() + " nbChilds : " + node.jjtGetNumChildren() + " : " + nodeExpression); + } + if (node.getId() == JavaParserTreeConstants.JJTLITERAL) { + // expression literal qu'on ne veut pas garder ? + if (log.isDebugEnabled()) { + log.debug("detected literal " + nodeExpression + " for last expression " + lastExpressionNode.getText()); + } + literals.add(lastExpressionNode); + return; + } + if (node.getId() == JavaParserTreeConstants.JJTCASTEXPRESSION) { + // expression literal qu'on ne veut pas garder ? + if (log.isDebugEnabled()) { + log.debug("detected cast " + nodeExpression + " for last expression " + lastExpressionNode.getText()); + } + List<SimpleNode> simpleNodeList = casts.get(lastExpressionNode); + if (simpleNodeList == null) { + simpleNodeList = new ArrayList<>(); + casts.put(lastExpressionNode, simpleNodeList); + } + simpleNodeList.add(node); + } + + if (node.getId() == JavaParserTreeConstants.JJTPRIMARYEXPRESSION) { + + if (store.get(node) == null) { + store.put(node, new ArrayList<SimpleNode>()); + } + if (lastExpressionNode == null) { + + // premiere entree dans la methode (detection d'une nouvelle expression) + // rien a faire + + + } else { + + // on vient d'un appel recursif, on ajoute le noeud courant a la liste des expression de l'expression parent + + List<SimpleNode> simpleNodeList = store.get(lastExpressionNode); + if (simpleNodeList == null) { + simpleNodeList = new ArrayList<>(); + store.put(node, simpleNodeList); + } + simpleNodeList.add(node); + } + + // on change la derniere expression rencontree + lastExpressionNode = node; + } + + // on parcours tous les fils du noeud courant + for (int i = 0, count = node.jjtGetNumChildren(); i < count; i++) { + scanForExpressions(node.getChild(i), lastExpressionNode, store, literals, casts); + } + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/PseudoClassDataBinding.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/PseudoClassDataBinding.java new file mode 100644 index 0000000..934d0b2 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/PseudoClassDataBinding.java @@ -0,0 +1,130 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.binding; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.java.JavaFileGenerator; +import org.nuiton.jaxx.compiler.java.parser.JavaParser; +import org.nuiton.jaxx.compiler.java.parser.JavaParserTreeConstants; +import org.nuiton.jaxx.compiler.java.parser.SimpleNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.StringReader; + +/** + * Represents a data binding in a JAXX file. <code>DataBinding</code> uses + * {@link DataSource} to track changes to a source expression and update + * the destination. + */ +public class PseudoClassDataBinding extends DataBinding { + + /** + * Logger + */ + protected static final Log log = LogFactory.getLog(PseudoClassDataBinding.class); + + protected final boolean invert; + + public static PseudoClassDataBinding newPseudoClassDataBinding(String pseudoClass, CompiledObject object, String propertyCode, String methodName, boolean invertTest) { + PseudoClassDataBinding binding = null; + if (pseudoClass.startsWith("{")) { + pseudoClass = pseudoClass.substring(1, pseudoClass.length() - 1).trim(); + pseudoClass = replaceObjectReferences(pseudoClass, object.getJavaCode()); + String id = object.getId() + ".style." + pseudoClass + "." + methodName; + + if (log.isDebugEnabled()) { + log.debug("will test if databinding : [" + pseudoClass + "] " + id); + } + binding = new PseudoClassDataBinding(id, pseudoClass, propertyCode, invertTest); + } + return binding; + } + + protected PseudoClassDataBinding(String id, String source, String assignment, boolean invert) { + super(id, source, assignment, false); + this.invert = invert; + } + + /** + * Replaces all references to the variable "object" with the actual object ID. + * + * @param code ? + * @param id ? + * @return ? + * @throws CompilerException ? + */ + public static String replaceObjectReferences(String code, String id) throws CompilerException { + JavaParser p = new JavaParser(new StringReader(code + ";")); + p.Expression(); + SimpleNode node = p.popNode(); + scanNode(node, id); + return node.getText(); + } + + public static void scanNode(SimpleNode node, String id) { + if (node.getId() == JavaParserTreeConstants.JJTNAME) { + String name = node.getText(); + if (name.equals("object") || + (name.indexOf(".") != -1 && + name.substring(0, name.indexOf(".")).trim().equals("object"))) { + node.firstToken.image = id; + } + } else { + int count = node.jjtGetNumChildren(); + for (int i = 0; i < count; i++) { + scanNode(node.getChild(i), id); + } + } + } + + @Override + protected String getInitDataBindingCode(JAXXCompiler compiler, DataSource dataSource, boolean isBinding) { + // nothing to init + return null; + } + + @Override + protected String getProcessDataBindingCode(JAXXCompiler compiler, DataSource dataSource, boolean isBinding) { + if (!isBinding) { + return null; + } + + String eol = JAXXCompiler.getLineSeparator(); + + StringBuilder buffer = new StringBuilder(); + + String realSource = invert ? invert(getSource()) : getSource(); + buffer.append("if (").append(realSource).append(") {").append(eol); + buffer.append(JavaFileGenerator.indent(getAssignment(), 4, false, eol)).append(eol); + buffer.append("}"); + return buffer.toString(); + } + + protected String invert(String javaCode) { + javaCode = javaCode.trim(); + return javaCode.startsWith("!") ? javaCode.substring(1) : "!(" + javaCode + ")"; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/writers/AbstractJAXXBindingWriter.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/writers/AbstractJAXXBindingWriter.java new file mode 100644 index 0000000..dc09bd0 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/writers/AbstractJAXXBindingWriter.java @@ -0,0 +1,94 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.binding.writers; + +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.binding.DataBinding; +import org.nuiton.jaxx.compiler.binding.DataListener; +import org.nuiton.jaxx.compiler.finalizers.DefaultFinalizer; +import org.nuiton.jaxx.compiler.java.JavaFileGenerator; +import org.nuiton.jaxx.compiler.java.JavaMethod; +import org.nuiton.jaxx.runtime.JAXXBinding; + +import java.util.List; + +/** + * Created: 5 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Id$ + */ +public abstract class AbstractJAXXBindingWriter<B extends JAXXBinding> implements JAXXBindingWriter<B> { + + private final Class<B> type; + + protected boolean used; + + protected AbstractJAXXBindingWriter(Class<B> type) { + this.type = type; + } + + @Override + public boolean isUsed() { + return used; + } + + @Override + public Class<B> getType() { + return type; + } + + @Override + public void reset() { + used = false; + } + + protected abstract String getConstructorParams(DataBinding binding, + DataListener[] trackers); + + protected void writeInvocationMethod(DataBinding binding, + DataListener[] trackers, + JavaFileGenerator generator, + StringBuilder buffer, + List<JavaMethod> bMethods) { + used = true; + String eol = JAXXCompiler.getLineSeparator(); + buffer.append(DefaultFinalizer.METHOD_NAME_REGISTER_DATA_BINDING); + buffer.append("(new "); + buffer.append(getType().getSimpleName()); + buffer.append("("); + buffer.append(getConstructorParams(binding, trackers)); + buffer.append(") {"); + buffer.append(eol); + for (JavaMethod m : bMethods) { + buffer.append(eol); + String source = generator.generateMethod(m); + buffer.append(JavaFileGenerator.indent(source, 4, false, eol)); + buffer.append(eol); + } + buffer.append("});").append(eol); + + if (binding.getInitDataBinding() != null) { + buffer.append(binding.getInitDataBinding()); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/writers/DefaultJAXXBindingWriter.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/writers/DefaultJAXXBindingWriter.java new file mode 100644 index 0000000..ec07435 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/writers/DefaultJAXXBindingWriter.java @@ -0,0 +1,134 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.binding.writers; + +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.binding.DataBinding; +import org.nuiton.jaxx.compiler.binding.DataListener; +import org.nuiton.jaxx.compiler.finalizers.DefaultFinalizer; +import org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import org.nuiton.jaxx.compiler.java.JavaElementFactory; +import org.nuiton.jaxx.compiler.java.JavaFileGenerator; +import org.nuiton.jaxx.compiler.java.JavaMethod; +import org.nuiton.jaxx.runtime.binding.DefaultJAXXBinding; + +import java.util.List; + +import static java.lang.reflect.Modifier.PUBLIC; + +/** + * Created: 5 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + * + * Mise a jour: $Date$ par : + * $Author$ + */ +public class DefaultJAXXBindingWriter extends AbstractJAXXBindingWriter<DefaultJAXXBinding> { + + public DefaultJAXXBindingWriter() { + super(DefaultJAXXBinding.class); + } + + @Override + public boolean accept(DataBinding binding) { + return true; + } + + @Override + public void write(DataBinding binding, + JavaFileGenerator generator, + StringBuilder buffer) { + DataListener[] trackers = binding.getTrackers(); + String eol = JAXXCompiler.getLineSeparator(); + + StringBuilder addBuffer = new StringBuilder(); + StringBuilder removeBuffer = new StringBuilder(); + + for (DataListener tracker : trackers) { + boolean needTest = tracker.getObjectCode() != null; + if (needTest) { + addBuffer.append("if ("); + addBuffer.append(tracker.getObjectCode()); + addBuffer.append(" != null) {"); + addBuffer.append(eol); + + removeBuffer.append("if ("); + removeBuffer.append(tracker.getObjectCode()); + removeBuffer.append(" != null) {"); + removeBuffer.append(eol); + } + int indentLevel = needTest ? 4 : 0; + addBuffer.append(JavaFileGenerator.indent( + tracker.getAddListenerCode(), indentLevel, false, eol)); + removeBuffer.append(JavaFileGenerator.indent( + tracker.getRemoveListenerCode(), indentLevel, false, eol)); + if (needTest) { + addBuffer.append(eol).append("}"); + removeBuffer.append(eol).append("}"); + } + addBuffer.append(eol); + removeBuffer.append(eol); + } + + List<JavaMethod> bMethods = binding.getMethods(); + bMethods.add(0, JavaElementFactory.newMethod( + PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + DefaultFinalizer.METHOD_NAME_REMOVE_DATA_BINDING, + removeBuffer.toString(), + true) + ); + bMethods.add(0, JavaElementFactory.newMethod( + PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + DefaultFinalizer.METHOD_NAME_PROCESS_DATA_BINDING, + binding.getProcessDataBinding(), + true) + ); + bMethods.add(0, JavaElementFactory.newMethod( + PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + DefaultFinalizer.METHOD_NAME_APPLY_DATA_BINDING, + addBuffer.toString(), + true) + ); + + writeInvocationMethod(binding, trackers, generator, buffer, bMethods); + } + + @Override + protected String getConstructorParams(DataBinding binding, + DataListener[] trackers) { + + String params = "this, " + binding.getConstantId() + ", true"; + if (trackers.length > 1) { + //FIXME tchemit-2011-04-21 Must improve this : only need a complex binding + // when chaining properties : example getA().getB() but not getA() || getB() + // with a complex binding, we will need to reload de binding after each fire... + params += ", true"; + + } + return params; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/writers/JAXXBindingWriter.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/writers/JAXXBindingWriter.java new file mode 100644 index 0000000..5d93f45 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/writers/JAXXBindingWriter.java @@ -0,0 +1,84 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.binding.writers; + +import org.nuiton.jaxx.compiler.binding.DataBinding; +import org.nuiton.jaxx.compiler.java.JavaFileGenerator; +import org.nuiton.jaxx.runtime.JAXXBinding; + +/** + * The contract of a writer of {@link JAXXBinding} creation code from a + * {@link DataBinding}. + * + * Created: 5 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + * + * Mise a jour: $Date$ par : + * $Author$ + */ +public interface JAXXBindingWriter<B extends JAXXBinding> { + + /** + * Test if a binding can be treated by the writer. + * + * @param binding the binding to test + * @return {@code true} if this writer can be used to generate binding creation code, {@code false} otherwise. + */ + boolean accept(DataBinding binding); + + /** + * Test if the writer was at least used once (says that the method + * {@link #write(DataBinding, JavaFileGenerator, StringBuilder)} was at least invoked once). + * + * @return {@code true} if this writer was used + */ + boolean isUsed(); + + /** @return the type of {@link JAXXBinding} to generate */ + Class<B> getType(); + + /** + * Generate the creation code of the given {@code binding} and push it in the given {@code buffer}. + * + * Note: after beean in this method, the {@link #isUsed()} should always return {@code true}. + * + * @param binding the binding to use + * @param generator common generator to build creation code + * @param buffer where to push creation code + */ + void write(DataBinding binding, + JavaFileGenerator generator, + StringBuilder buffer); + + /** + * Reset internal states. + * + * At the moment, there is only the {@code used} property which is + * internal and must be reset to {@code false} for each compiler in order + * to know if a type of writer is used for the file. + * + * @since 2.4 + */ + void reset(); +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/writers/SimpleJAXXObjectBindingWriter.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/writers/SimpleJAXXObjectBindingWriter.java new file mode 100644 index 0000000..097ccc5 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/binding/writers/SimpleJAXXObjectBindingWriter.java @@ -0,0 +1,108 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.binding.writers; + +import org.nuiton.jaxx.compiler.binding.DataBinding; +import org.nuiton.jaxx.compiler.binding.DataListener; +import org.nuiton.jaxx.compiler.binding.JavaParserUtil; +import org.nuiton.jaxx.compiler.finalizers.DefaultFinalizer; +import org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import org.nuiton.jaxx.compiler.java.JavaElementFactory; +import org.nuiton.jaxx.compiler.java.JavaFileGenerator; +import org.nuiton.jaxx.compiler.java.JavaMethod; +import org.nuiton.jaxx.runtime.binding.SimpleJAXXObjectBinding; + +import java.lang.reflect.Modifier; +import java.util.List; + +/** + * Created: 5 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + * + * Mise a jour: $Date$ par : + * $Author$ + */ +public class SimpleJAXXObjectBindingWriter extends AbstractJAXXBindingWriter<SimpleJAXXObjectBinding> { + + protected boolean used; + + public SimpleJAXXObjectBindingWriter() { + super(SimpleJAXXObjectBinding.class); + } + + @Override + public boolean accept(DataBinding binding) { + DataListener[] trackers = binding.getTrackers(); + if (trackers.length > 0) { + for (DataListener tracker : trackers) { + if (tracker.getObjectCode() != null) { + // tracker must be without any requirement + return false; + } + } + } + return true; + } + + @Override + protected String getConstructorParams(DataBinding binding, + DataListener[] trackers) { + + StringBuilder addBuffer = new StringBuilder(); + addBuffer.append("this, "); + addBuffer.append(binding.getConstantId()); + addBuffer.append(", true"); + + for (DataListener tracker : trackers) { + String symbol = tracker.getSymbol(); + String name = symbol.substring(symbol.indexOf(".") + 1); + if (JavaParserUtil.getMethodInvocationParameters(name) != null) { + // obtain the property name from the method name + name = JavaParserUtil.getPropertyNameFromMethod(name); + } + addBuffer.append(" ,\"").append(name).append("\""); + } + return addBuffer.toString(); + } + + @Override + public void write(DataBinding binding, + JavaFileGenerator generator, + StringBuilder buffer) { + DataListener[] trackers = binding.getTrackers(); + List<JavaMethod> bMethods = binding.getMethods(); + + JavaMethod method = JavaElementFactory.newMethod( + Modifier.PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + DefaultFinalizer.METHOD_NAME_PROCESS_DATA_BINDING, + binding.getProcessDataBinding(), + true + ); + + bMethods.add(0, method); + + writeInvocationMethod(binding, trackers, generator, buffer, bMethods); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/StylesheetHelper.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/StylesheetHelper.java new file mode 100644 index 0000000..5f7a73b --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/StylesheetHelper.java @@ -0,0 +1,702 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.css; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.binding.DataBinding; +import org.nuiton.jaxx.compiler.binding.DataBindingHelper; +import org.nuiton.jaxx.compiler.binding.PseudoClassDataBinding; +import org.nuiton.jaxx.compiler.css.parser.CSSParser; +import org.nuiton.jaxx.compiler.css.parser.CSSParserConstants; +import org.nuiton.jaxx.compiler.css.parser.CSSParserTreeConstants; +import org.nuiton.jaxx.compiler.css.parser.SimpleNode; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.nuiton.jaxx.compiler.tags.DefaultObjectHandler; +import org.nuiton.jaxx.compiler.tags.TagManager; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.css.Pseudoclasses; +import org.nuiton.jaxx.runtime.css.Rule; +import org.nuiton.jaxx.runtime.css.Selector; +import org.nuiton.jaxx.runtime.css.Stylesheet; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * A helper class to compute {@link Stylesheet}, {@link Rule} and {@link Selector} + * and extract all the compiler logic from this class. + * + * In that way we can make the compiler as a single module and a runtime as another module. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class StylesheetHelper { + + /** Logger */ + static private final Log log = LogFactory.getLog(StylesheetHelper.class); + + public static Stylesheet processStylesheet(String stylesheetText) throws CompilerException { + CSSParser p = new CSSParser(new StringReader(stylesheetText)); + SimpleNode node; + try { + node = p.Stylesheet(); + } catch (Error e) { + throw new CompilerException(e); + } + List<Rule> rules = new ArrayList<>(); + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + SimpleNode ruleNode = node.getChild(i); + Rule rule = processRule(ruleNode); + rules.add(rule); + } + Stylesheet stylesheet; + stylesheet = new Stylesheet(rules.toArray(new Rule[rules.size()])); + return stylesheet; + } + + public static Rule processRule(SimpleNode ruleNode) { + if (ruleNode.getId() != CSSParserTreeConstants.JJTRULE) { + throw new IllegalArgumentException("argument node is not a Rule"); + } + SimpleNode selectorsNode = ruleNode.getChild(0); + assert selectorsNode.getId() == CSSParserTreeConstants.JJTSELECTORS : + "expected node to be of type Selectors"; + + List<Selector> selectors = new ArrayList<>(); + for (int i = 0; i < selectorsNode.jjtGetNumChildren(); i++) { + SimpleNode selectorNode = selectorsNode.getChild(i); + selectors.add(processSelector(selectorNode)); + } + + Map<String, String> properties = new HashMap<>(); + for (int i = 1; i < ruleNode.jjtGetNumChildren(); i++) { + SimpleNode declarationNode = ruleNode.getChild(i); + if (declarationNode.getId() == CSSParserTreeConstants.JJTDECLARATION) { + String key = declarationNode.getChild(0).getText(); + SimpleNode valueNode = declarationNode.getChild(1); + String value = valueNode.getText(); + if (valueNode.firstToken.kind == CSSParserConstants.STRING) { + value = value.substring(1, value.length() - 1); + } + properties.put(key, value); + } + } + Rule rule; + rule = new Rule(selectors.toArray( + new Selector[selectors.size()]), properties); + return rule; + } + + public static Selector processSelector(SimpleNode selector) { + if (selector.getId() != CSSParserTreeConstants.JJTSELECTOR) { + throw new IllegalArgumentException("argument node is not a Selector"); + } + String javaClassName = null; + String styleClass = null; + String pseudoClass = null; + String id = null; + + for (int i = 0; i < selector.jjtGetNumChildren(); i++) { + SimpleNode child = selector.getChild(i); + switch (child.getId()) { + case CSSParserTreeConstants.JJTJAVACLASS: + if (!child.getText().trim().equals("*")) { + javaClassName = child.getText(); + } + break; + case CSSParserTreeConstants.JJTCLASS: + styleClass = child.getText().substring(1); + break; + case CSSParserTreeConstants.JJTPSEUDOCLASS: + pseudoClass = child.getText().substring(1); + break; + case CSSParserTreeConstants.JJTID: + id = child.getText().substring(1); + break; + + default: + throw new IllegalStateException( + "unexpected child of Selector node, type=" + + child.getId()); + } + } + + return new Selector(javaClassName, styleClass, pseudoClass, id); + } + + public enum MouseEventEnum { + + mouseover("mouseEntered", "mouseExited"), + mouseout("mouseExited", "mouseReleased"), + mousedown("mousePressed", "mousePressed"), + mouseup("mouseReleased", "mousePressed"); + + final String addMethod; + + final String removeMethod; + +// ClassDescriptor mouseListenerDescriptor; +// ClassDescriptor mouseEventDescriptor; + + MouseEventEnum(String addMethod, String removeMethod) { + this.removeMethod = removeMethod; + this.addMethod = addMethod; + } + + public String getProperty(int i) { + return i == 0 ? addMethod : removeMethod; + } + } + + static ClassDescriptor mouseListenerDescriptor; + + static ClassDescriptor mouseEventDescriptor; + + public static ClassDescriptor getMouseEventDescriptor() { + if (mouseEventDescriptor == null) { + mouseEventDescriptor = + ClassDescriptorHelper.getClassDescriptor(MouseEvent.class); + } + return mouseEventDescriptor; + } + + public static ClassDescriptor getMouseListenerDescriptor() { + if (mouseListenerDescriptor == null) { + mouseListenerDescriptor = + ClassDescriptorHelper.getClassDescriptor(MouseListener.class); + } + return mouseListenerDescriptor; + } + + public static MethodDescriptor getAddMouseListenerMethod(CompiledObject object) { + try { + return object.getObjectClass().getMethodDescriptor( + "addMouseListener", + getMouseListenerDescriptor() + ); + } catch (NoSuchMethodException e) { + throw new CompilerException( + "could not find addMouseListener for object " + object); + } + } + + public static MethodDescriptor getMouseListenerMethod(CompiledObject object, String property) { + try { + return getMouseListenerDescriptor().getMethodDescriptor( + property, + getMouseEventDescriptor() + ); + } catch (NoSuchMethodException e) { + throw new CompilerException( + "could not find " + property + " for object " + object); + } + } + + public static void applyTo(CompiledObject object, + JAXXCompiler compiler, + Stylesheet stylesheet, + Stylesheet overrides) throws CompilerException { + Map<String, String> overriddenProperties; + if (overrides != null) { + overriddenProperties = getApplicableProperties(overrides, object); + //overriddenProperties = overrides.getApplicableProperties(s,object); + } else { + overriddenProperties = null; + } + + Map<String, String> properties = getApplicableProperties(stylesheet, + object); + if (properties != null) { + if (overriddenProperties != null) { + properties.keySet().removeAll(overriddenProperties.keySet()); + } + DefaultObjectHandler handler = + TagManager.getTagHandler(object.getObjectClass()); + for (Map.Entry<String, String> e : properties.entrySet()) { + String value = e.getValue(); + if (value.equals(Rule.INLINE_ATTRIBUTE) || + value.equals(Rule.DATA_BINDING)) { + continue; + } + + if (handler instanceof DefaultComponentHandler) + handler.setAttribute(object, e.getKey(), e.getValue(), + false, compiler); + else { + handler.setAttributeFromCss(object, e.getKey(), value, compiler); + } + } + } + + Rule[] pseudoClasses = getApplicablePseudoClasses(stylesheet, object); + if (pseudoClasses != null) { + Map<String, Map<String, String>> combinedPseudoClasses = + new LinkedHashMap<>(); + for (Rule pseudoClass1 : pseudoClasses) { + Selector[] selectors = pseudoClass1.getSelectors(); + for (Selector selector : selectors) { + if (appliesTo(selector, object) == + Selector.PSEUDOCLASS_APPLIES) { + properties = pseudoClass1.getProperties(); + String pseudoClass = selector.getPseudoClass(); + // TODO: overrides by downstream pseudoclasses are not handled + Map<String, String> combinedProperties = + combinedPseudoClasses.get(pseudoClass); + if (combinedProperties == null) { + combinedProperties = new HashMap<>(); + combinedPseudoClasses.put(pseudoClass, + combinedProperties); + } + combinedProperties.putAll(properties); + } + } + } + + int count = 0; + for (Map.Entry<String, Map<String, String>> e : + combinedPseudoClasses.entrySet()) { + applyPseudoClass(e.getKey(), e.getValue(), object, compiler, + count++); + } + } + } + + public static String unwrap(ClassDescriptor type, String valueCode) { + if (ClassDescriptorHelper.getClassDescriptor(boolean.class).equals(type)) { + return "((Boolean) " + valueCode + ").booleanValue()"; + } + if (ClassDescriptorHelper.getClassDescriptor(byte.class).equals(type)) { + return "((Byte) " + valueCode + ").byteValue()"; + } + if (ClassDescriptorHelper.getClassDescriptor(short.class).equals(type)) { + return "((Short) " + valueCode + ").shortValue()"; + } + if (ClassDescriptorHelper.getClassDescriptor(int.class).equals(type)) { + return "((Integer) " + valueCode + ").intValue()"; + } + if (ClassDescriptorHelper.getClassDescriptor(long.class).equals(type)) { + return "((Long) " + valueCode + ").longValue()"; + } + if (ClassDescriptorHelper.getClassDescriptor(float.class).equals(type)) { + return "((Float) " + valueCode + ").floatValue()"; + } + if (ClassDescriptorHelper.getClassDescriptor(double.class).equals(type)) { + return "((Double) " + valueCode + ").doubleValue()"; + } + if (ClassDescriptorHelper.getClassDescriptor(char.class).equals(type)) { + return "((Character) " + valueCode + ").charValue()"; + } + return valueCode; + } + + public enum PseudoClassEnum { + focused("{ object.hasFocus() }"), + unfocused("{ !object.hasFocus() }"), + enabled("{ object.isEnabled() }"), + disabled("{ !object.isEnabled() }"), + selected("{ object.isSelected() }"), + deselected("{ !object.isSelected() }"); + + final String code; + + PseudoClassEnum(String code) { + this.code = code; + } + + public String getCode() { + return code; + } + } + + public static void applyPseudoClass(String pseudoClass, + Map<String, String> properties, + CompiledObject object, + JAXXCompiler compiler, + int priority) throws CompilerException { + if (pseudoClass.contains("[")) { + pseudoClass = pseudoClass.substring(0, pseudoClass.indexOf("[")); + } + StringBuilder buffer = new StringBuilder(); + + DefaultObjectHandler handler = + TagManager.getTagHandler(object.getObjectClass()); + boolean valueDeclared = false; + String eol = JAXXCompiler.getLineSeparator(); + DataBindingHelper bindingHelper = compiler.getBindingHelper(); + + String pseudoClassesPrefix = null; + String dataBindingPrefix = null; + + if (!properties.isEmpty()) { + pseudoClassesPrefix = compiler.getImportedType(Pseudoclasses.class); + dataBindingPrefix = compiler.getImportedType(org.nuiton.jaxx.runtime.css.DataBinding.class); + } + + String outputClassName = + compiler.getImportedType(compiler.getOutputClassName()); + + for (Map.Entry<String, String> e : properties.entrySet()) { + String property = e.getKey(); + ClassDescriptor type = handler.getPropertyType(object, + property, + compiler + ); + if (log.isDebugEnabled()) { + log.debug("will test if databinding : [" + e.getValue() + + "] type=" + type); + } + String dataBindingCode = + DataBindingHelper.processDataBindings(e.getValue()); + String valueCode; + String simpleType = compiler.getImportedType(JAXXCompiler.getCanonicalName(type)); + + if (dataBindingCode != null) { + String code = object.getId() + "." + property + "." + priority; + valueCode = "new " + dataBindingPrefix + "(" + + TypeManager.getJavaCode(code) + ")"; + DataBinding binding = new DataBinding( + code, + dataBindingCode, + handler.getSetPropertyCode( + object.getJavaCode(), + property, + "(" + simpleType + ") " + dataBindingCode, +// "(" + JAXXCompiler.getCanonicalName(type) + ") " + dataBindingCode, + compiler + ), + false + ); + bindingHelper.registerDataBinding(binding); + } else { + try { + Class<?> typeClass = type != null ? + ClassDescriptorHelper.getClass( + type.getName(), + type.getClassLoader() + ) : + null; + valueCode = TypeManager.getJavaCode( + TypeManager.convertFromString(e.getValue(), typeClass) + ); + } catch (ClassNotFoundException ex) { + compiler.reportError( + "could not find class " + type.getName()); + return; + } + } + if (!valueDeclared) { + buffer.append("Object "); + valueDeclared = true; + } + + buffer.append("value = "); + buffer.append(pseudoClassesPrefix); + buffer.append(".applyProperty("); + buffer.append(outputClassName); + buffer.append(".this, "); + buffer.append(object.getJavaCode()); + buffer.append(", "); + buffer.append(TypeManager.getJavaCode(property)); + buffer.append(", "); + buffer.append(valueCode); + buffer.append(", "); + buffer.append(pseudoClassesPrefix); + buffer.append(".wrap("); + buffer.append(handler.getGetPropertyCode(object.getJavaCode(), property, compiler)); + buffer.append("), "); + buffer.append(priority); + buffer.append(");"); + buffer.append(eol); + + buffer.append("if (!(value instanceof "); + buffer.append(dataBindingPrefix); + buffer.append(")) {"); + buffer.append(eol); + + String unwrappedValue = unwrap(type, "value"); + buffer.append(" "); + buffer.append(handler.getSetPropertyCode(object.getJavaCode(), property, "(" + simpleType + ") " + unwrappedValue, compiler)); + buffer.append(eol); + buffer.append("}").append(eol); + } + + try { + PseudoClassEnum classEnum = PseudoClassEnum.valueOf(pseudoClass); + pseudoClass = classEnum.getCode(); + } catch (IllegalArgumentException e) { + // should never happens ? +// throw new RuntimeException("could not find " + PseudoClassEnum.class + " with pseudoClass " + pseudoClass, e); + } + + compilePseudoClass(pseudoClass, object, buffer.toString(), 0, "add", compiler, false); + + buffer.setLength(0); + valueDeclared = false; + for (Map.Entry<String, String> e : properties.entrySet()) { + String property = e.getKey(); + ClassDescriptor type = handler.getPropertyType(object, property, compiler); + String simpleType = compiler.getImportedType(JAXXCompiler.getCanonicalName(type)); + if (log.isDebugEnabled()) { + log.debug("will test if databinding : [" + e.getValue() + "] type=" + type); + } + String dataBindingCode = DataBindingHelper.processDataBindings(e.getValue()); + String valueCode; + if (dataBindingCode != null) { + String code = object.getId() + "." + property + "." + priority; + valueCode = "new " + dataBindingPrefix + "(" + TypeManager.getJavaCode(code) + ")"; + DataBinding binding = new DataBinding( + code, + dataBindingCode, + handler.getSetPropertyCode( + object.getJavaCode(), + property, + "(" + simpleType + ") " + dataBindingCode, + compiler + ), + false + ); + bindingHelper.registerDataBinding(binding); + } else { + try { + Class<?> typeClass = + type != null ? + ClassDescriptorHelper.getClass(type.getName(), type.getClassLoader()) : + null; + valueCode = TypeManager.getJavaCode(TypeManager.convertFromString(e.getValue(), typeClass)); + } catch (ClassNotFoundException ex) { + compiler.reportError("could not find class " + type.getName()); + return; + } + } + if (!valueDeclared) { + buffer.append("Object "); + valueDeclared = true; + } + buffer.append("value = ").append(pseudoClassesPrefix).append(".removeProperty("); + + buffer.append(outputClassName); + buffer.append(".this, "); + buffer.append(object.getJavaCode()); + buffer.append(", "); + buffer.append(TypeManager.getJavaCode(property)); + buffer.append(", "); + buffer.append(valueCode); + buffer.append(", ").append(pseudoClassesPrefix).append(".wrap("); + buffer.append(handler.getGetPropertyCode(object.getJavaCode(), + property, + compiler) + ); + buffer.append("), "); + buffer.append(priority); + buffer.append(");"); + buffer.append(eol); + + buffer.append("if (!(value instanceof "); + buffer.append(dataBindingPrefix); + buffer.append(")) {"); + buffer.append(eol); + +// String simpleType = importManager.getType(JAXXCompiler.getCanonicalName(type)); + String unwrappedValue = unwrap(type, "value"); + buffer.append(" "); + buffer.append(handler.getSetPropertyCode( + object.getJavaCode(), + property, + "(" + simpleType + ") " + unwrappedValue, + compiler) + ); + buffer.append(eol); + buffer.append("}").append(eol); + } + compilePseudoClass(pseudoClass, + object, + buffer.toString(), + 1, + "remove", + compiler, + true + ); + } + + + public static void compilePseudoClass(String pseudoClass, + CompiledObject object, + String propertyCode, + int pos, + String methodName, + JAXXCompiler compiler, + boolean invertTest) throws CompilerException { + + PseudoClassDataBinding binding = + PseudoClassDataBinding.newPseudoClassDataBinding( + pseudoClass, + object, + propertyCode, + methodName, + invertTest + ); + if (binding != null) { + compiler.getBindingHelper().registerDataBinding(binding); + return; + } + MouseEventEnum constant = MouseEventEnum.valueOf(pseudoClass); + String property = constant.getProperty(pos); + MethodDescriptor addMouseListener = getAddMouseListenerMethod(object); + MethodDescriptor methodDescriptor = + getMouseListenerMethod(object, property); + object.addEventHandler("style." + pseudoClass + "." + methodName, + addMouseListener, + methodDescriptor, + propertyCode, + compiler + ); + } + + public static Map<String, String> getApplicableProperties( + Stylesheet s, CompiledObject object) throws CompilerException { + DefaultObjectHandler handler = + TagManager.getTagHandler(object.getObjectClass()); + Map<String, String> result = null; + for (Rule rule : s.getRules()) { + int apply = appliesTo(rule, object); + if (apply == Selector.ALWAYS_APPLIES || + apply == Selector.ALWAYS_APPLIES_INHERIT_ONLY) { + if (result == null) { + result = new HashMap<>(); + } + for (Map.Entry<String, String> entry : + rule.getProperties().entrySet()) { + String property = entry.getKey(); + if (apply == Selector.ALWAYS_APPLIES || + handler.isPropertyInherited(property)) { + result.put(property, entry.getValue()); + } + } + } + } + return result; + } + + public static Rule[] getApplicablePseudoClasses( + Stylesheet s, CompiledObject object) throws CompilerException { + List<Rule> result = null; + for (Rule rule : s.getRules()) { + if (appliesTo(rule, object) == Selector.PSEUDOCLASS_APPLIES) { + if (result == null) { + result = new ArrayList<>(); + } + result.add(rule); + } + } + return result != null ? result.toArray(new Rule[result.size()]) : null; + } + + public static Rule inlineAttribute(CompiledObject object, + String propertyName, + boolean dataBinding) { + Map<String, String> properties = new HashMap<>(); + properties.put(propertyName, dataBinding ? + Rule.DATA_BINDING : + Rule.INLINE_ATTRIBUTE); + return new Rule(new Selector[]{ + new Selector(null, null, null, object.getId(), true)}, + properties + ); + } + + public static int appliesTo(Rule rule, + CompiledObject object) throws CompilerException { + int appliesTo = Selector.NEVER_APPLIES; + for (Selector selector : rule.getSelectors()) { + appliesTo = Math.max(appliesTo(selector, object), appliesTo); + if (appliesTo == Selector.ALWAYS_APPLIES || + appliesTo == Selector.ALWAYS_APPLIES_INHERIT_ONLY) { + break; + } + } + return appliesTo; + } + + public static int appliesTo(Selector selector, CompiledObject object) { + boolean inheritOnly = false; + CompiledObject parent = object; + String javaClassName = selector.getJavaClassName(); + String styleClass = selector.getStyleClass(); + String pseudoClass = selector.getPseudoClass(); + String id = selector.getId(); + + while (parent != null) { + boolean classMatch = javaClassName == null; + if (!classMatch) { + ClassDescriptor javaClass = parent.getObjectClass(); + do { + String name = javaClass.getName(); + if (name.equals(javaClassName) || + name.substring(name.lastIndexOf(".") + 1).equals(javaClassName)) { + classMatch = true; + break; + } + javaClass = javaClass.getSuperclass(); + } while (javaClass != null); + } + + boolean styleClassMatch = styleClass == null || + styleClass.equals(parent.getStyleClass()); + + String objectId = parent.getId(); + objectId = objectId.substring(objectId.lastIndexOf(".") + 1); + boolean idMatch = id == null || + (' ' + objectId + ' ').contains(' ' + id + ' '); + + if (classMatch && styleClassMatch && idMatch) { + if (pseudoClass != null) { + return inheritOnly ? + Selector.PSEUDOCLASS_APPLIES_INHERIT_ONLY : + Selector.PSEUDOCLASS_APPLIES; + } else { + return inheritOnly ? + Selector.ALWAYS_APPLIES_INHERIT_ONLY : + Selector.ALWAYS_APPLIES; + } + } + + parent = parent.getParent(); + inheritOnly = true; + } + return Selector.NEVER_APPLIES; + } + +} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSS.jj b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSS.jj similarity index 100% rename from jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSS.jj rename to jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSS.jj diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSS.jjt b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSS.jjt similarity index 100% rename from jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSS.jjt rename to jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSS.jjt diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSSParser.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSSParser.java new file mode 100644 index 0000000..7c2d3d3 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSSParser.java @@ -0,0 +1,831 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree&JavaCC: Do not edit this line. CSSParser.java */ + +package org.nuiton.jaxx.compiler.css.parser; + +public class CSSParser/*@bgen(jjtree)*/ implements CSSParserTreeConstants, CSSParserConstants {/*@bgen(jjtree)*/ + + protected JJTCSSParserState jjtree = new JJTCSSParserState(); + + public SimpleNode popNode() { + if (jjtree.nodeArity() > 0) // number of child nodes + return (SimpleNode) jjtree.popNode(); + else + return null; + } + + void jjtreeOpenNodeScope(Node n) { + ((SimpleNode) n).firstToken = getToken(1); + } + + void jjtreeCloseNodeScope(Node n) { + ((SimpleNode) n).lastToken = getToken(0); + } + + public static void main(String args[]) { + System.out.println("Reading from standard input..."); + CSSParser css = new CSSParser(System.in); + try { + SimpleNode n = css.Stylesheet(); + n.dump(""); + System.out.println("Thank you."); + } catch (Exception e) { + System.out.println("Oops."); + System.out.println(e.getMessage()); + e.printStackTrace(); + } + } + + final public SimpleNode Stylesheet() throws ParseException { + /*@bgen(jjtree) Stylesheet */ + SimpleNode jjtn000 = new SimpleNode(JJTSTYLESHEET); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + label_1: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + case PSEUDOCLASS_COLON: + case 29: + case 30: + case 31: + ; + break; + default: + jj_la1[0] = jj_gen; + break label_1; + } + Rule(); + } + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return jjtn000; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + throw new Error("Missing return statement in function"); + } + + final public void Rule() throws ParseException { + /*@bgen(jjtree) Rule */ + SimpleNode jjtn000 = new SimpleNode(JJTRULE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Selectors(); + jj_consume_token(LEFT_BRACE); + Declaration(); + label_2: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case SEMICOLON: + ; + break; + default: + jj_la1[1] = jj_gen; + break label_2; + } + jj_consume_token(SEMICOLON); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + Declaration(); + break; + default: + jj_la1[2] = jj_gen; + ; + } + } + jj_consume_token(RIGHT_BRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Selectors() throws ParseException { + /*@bgen(jjtree) Selectors */ + SimpleNode jjtn000 = new SimpleNode(JJTSELECTORS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Selector(); + label_3: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 28: + ; + break; + default: + jj_la1[3] = jj_gen; + break label_3; + } + jj_consume_token(28); + Selector(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Selector() throws ParseException { + /*@bgen(jjtree) Selector */ + SimpleNode jjtn000 = new SimpleNode(JJTSELECTOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + case 29: + JavaClass(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 30: + Id(); + break; + default: + jj_la1[4] = jj_gen; + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 31: + Class(); + break; + default: + jj_la1[5] = jj_gen; + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PSEUDOCLASS_COLON: + PseudoClass(); + break; + default: + jj_la1[6] = jj_gen; + ; + } + break; + case 30: + Id(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 31: + Class(); + break; + default: + jj_la1[7] = jj_gen; + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PSEUDOCLASS_COLON: + PseudoClass(); + break; + default: + jj_la1[8] = jj_gen; + ; + } + break; + case 31: + Class(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PSEUDOCLASS_COLON: + PseudoClass(); + break; + default: + jj_la1[9] = jj_gen; + ; + } + break; + case PSEUDOCLASS_COLON: + PseudoClass(); + break; + default: + jj_la1[10] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void JavaClass() throws ParseException { + /*@bgen(jjtree) JavaClass */ + SimpleNode jjtn000 = new SimpleNode(JJTJAVACLASS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + jj_consume_token(IDENTIFIER); + break; + case 29: + jj_consume_token(29); + break; + default: + jj_la1[11] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Id() throws ParseException { + /*@bgen(jjtree) Id */ + SimpleNode jjtn000 = new SimpleNode(JJTID); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(30); + jj_consume_token(IDENTIFIER); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Class() throws ParseException { + /*@bgen(jjtree) Class */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(31); + jj_consume_token(IDENTIFIER); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PseudoClass() throws ParseException { + /*@bgen(jjtree) PseudoClass */ + SimpleNode jjtn000 = new SimpleNode(JJTPSEUDOCLASS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(PSEUDOCLASS_COLON); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PSEUDOCLASS_IDENTIFIER: + jj_consume_token(PSEUDOCLASS_IDENTIFIER); + break; + case PROGRAMMATIC_PSEUDOCLASS: + jj_consume_token(PROGRAMMATIC_PSEUDOCLASS); + break; + default: + jj_la1[12] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 32: + AnimationProperties(); + break; + default: + jj_la1[13] = jj_gen; + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AnimationProperties() throws ParseException { + /*@bgen(jjtree) AnimationProperties */ + SimpleNode jjtn000 = new SimpleNode(JJTANIMATIONPROPERTIES); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(32); + AnimationProperty(); + label_4: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 28: + ; + break; + default: + jj_la1[14] = jj_gen; + break label_4; + } + jj_consume_token(28); + AnimationProperty(); + } + jj_consume_token(33); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AnimationProperty() throws ParseException { + /*@bgen(jjtree) AnimationProperty */ + SimpleNode jjtn000 = new SimpleNode(JJTANIMATIONPROPERTY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + jj_consume_token(34); + jj_consume_token(DECIMAL_LITERAL); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + jj_consume_token(IDENTIFIER); + break; + default: + jj_la1[15] = jj_gen; + ; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Declaration() throws ParseException { + /*@bgen(jjtree) Declaration */ + SimpleNode jjtn000 = new SimpleNode(JJTDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Property(); + jj_consume_token(COLON); + Expression(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Property() throws ParseException { + /*@bgen(jjtree) Property */ + SimpleNode jjtn000 = new SimpleNode(JJTPROPERTY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Expression() throws ParseException { + /*@bgen(jjtree) Expression */ + SimpleNode jjtn000 = new SimpleNode(JJTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case DECIMAL_LITERAL: + jj_consume_token(DECIMAL_LITERAL); + break; + case STRING: + jj_consume_token(STRING); + break; + case IDENTIFIER: + jj_consume_token(IDENTIFIER); + break; + case HEXCOLOR: + jj_consume_token(HEXCOLOR); + break; + case EMS: + jj_consume_token(EMS); + break; + case EXS: + jj_consume_token(EXS); + break; + case LENGTH: + jj_consume_token(LENGTH); + break; + case JAVA_CODE_START: + JavaCode(); + break; + default: + jj_la1[16] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void JavaCode() throws ParseException { + /*@bgen(jjtree) JavaCode */ + SimpleNode jjtn000 = new SimpleNode(JJTJAVACODE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(JAVA_CODE_START); + jj_consume_token(JAVA_CODE); + jj_consume_token(JAVA_CODE_END); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Identifier() throws ParseException { + /*@bgen(jjtree) Identifier */ + SimpleNode jjtn000 = new SimpleNode(JJTIDENTIFIER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + public CSSParserTokenManager token_source; + + SimpleCharStream jj_input_stream; + + public Token token, jj_nt; + + private int jj_ntk; + + private int jj_gen; + + final private int[] jj_la1 = new int[17]; + + static private int[] jj_la1_0; + + static private int[] jj_la1_1; + + static { + jj_la1_0(); + jj_la1_1(); + } + + private static void jj_la1_0() { + jj_la1_0 = new int[]{0xe0002200, 0x8000, 0x200, 0x10000000, 0x40000000, 0x80000000, 0x2000, 0x80000000, 0x2000, 0x2000, 0xe0002200, 0x20000200, 0x201000, 0x0, 0x10000000, 0x200, 0xec40280,}; + } + + private static void jj_la1_1() { + jj_la1_1 = new int[]{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,}; + } + + public CSSParser(java.io.InputStream stream) { + this(stream, null); + } + + public CSSParser(java.io.InputStream stream, String encoding) { + try { + jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); + } catch (java.io.UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + token_source = new CSSParserTokenManager(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 17; i++) jj_la1[i] = -1; + } + + public void ReInit(java.io.InputStream stream) { + ReInit(stream, null); + } + + public void ReInit(java.io.InputStream stream, String encoding) { + try { + jj_input_stream.ReInit(stream, encoding, 1, 1); + } catch (java.io.UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + token_source.ReInit(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + jj_gen = 0; + for (int i = 0; i < 17; i++) jj_la1[i] = -1; + } + + public CSSParser(java.io.Reader stream) { + jj_input_stream = new SimpleCharStream(stream, 1, 1); + token_source = new CSSParserTokenManager(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 17; i++) jj_la1[i] = -1; + } + + public void ReInit(java.io.Reader stream) { + jj_input_stream.ReInit(stream, 1, 1); + token_source.ReInit(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + jj_gen = 0; + for (int i = 0; i < 17; i++) jj_la1[i] = -1; + } + + public CSSParser(CSSParserTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 17; i++) jj_la1[i] = -1; + } + + public void ReInit(CSSParserTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + jj_gen = 0; + for (int i = 0; i < 17; i++) jj_la1[i] = -1; + } + + final private Token jj_consume_token(int kind) throws ParseException { + Token oldToken; + if ((oldToken = token).next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + if (token.kind == kind) { + jj_gen++; + return token; + } + token = oldToken; + jj_kind = kind; + throw generateParseException(); + } + + final public Token getNextToken() { + if (token.next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + jj_gen++; + return token; + } + + final public Token getToken(int index) { + Token t = token; + for (int i = 0; i < index; i++) { + if (t.next != null) t = t.next; + else t = t.next = token_source.getNextToken(); + } + return t; + } + + final private int jj_ntk() { + if ((jj_nt = token.next) == null) + return (jj_ntk = (token.next = token_source.getNextToken()).kind); + else + return (jj_ntk = jj_nt.kind); + } + + private java.util.Vector jj_expentries = new java.util.Vector(); + + private int[] jj_expentry; + + private int jj_kind = -1; + + public ParseException generateParseException() { + Token errortok = token.next; + int line = errortok.beginLine, column = errortok.beginColumn; + String mess = (errortok.kind == 0) ? tokenImage[0] : errortok.image; + return new ParseException("Parse error. Encountered: " + mess, line, column); + } + + final public void enable_tracing() { + } + + final public void disable_tracing() { + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSSParserConstants.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSSParserConstants.java new file mode 100644 index 0000000..a270c00 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSSParserConstants.java @@ -0,0 +1,118 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree&JavaCC: Do not edit this line. CSSParserConstants.java */ + +package org.nuiton.jaxx.compiler.css.parser; + +public interface CSSParserConstants { + + int EOF = 0; + + int DECIMAL_LITERAL = 7; + + int INTEGER_LITERAL = 8; + + int IDENTIFIER = 9; + + int LETTER = 10; + + int DIGIT = 11; + + int PSEUDOCLASS_IDENTIFIER = 12; + + int PSEUDOCLASS_COLON = 13; + + int COLON = 14; + + int SEMICOLON = 15; + + int LEFT_BRACE = 16; + + int RIGHT_BRACE = 17; + + int JAVA_CODE_START = 18; + + int JAVA_CODE = 19; + + int JAVA_CODE_END = 20; + + int PROGRAMMATIC_PSEUDOCLASS = 21; + + int STRING = 22; + + int HEXCOLOR = 23; + + int HEXDIGIT = 24; + + int EMS = 25; + + int EXS = 26; + + int LENGTH = 27; + + int DEFAULT = 0; + + int IN_RULE = 1; + + int JAVA_CODE_RULE = 2; + + int IN_PSEUDOCLASS = 3; + + String[] tokenImage = { + "<EOF>", + "\" \"", + "\"\\t\"", + "\"\\n\"", + "\"\\r\"", + "<token of kind 5>", + "<token of kind 6>", + "<DECIMAL_LITERAL>", + "<INTEGER_LITERAL>", + "<IDENTIFIER>", + "<LETTER>", + "<DIGIT>", + "<PSEUDOCLASS_IDENTIFIER>", + "\":\"", + "\":\"", + "\";\"", + "\"{\"", + "\"}\"", + "<JAVA_CODE_START>", + "<JAVA_CODE>", + "<JAVA_CODE_END>", + "<PROGRAMMATIC_PSEUDOCLASS>", + "<STRING>", + "<HEXCOLOR>", + "<HEXDIGIT>", + "<EMS>", + "<EXS>", + "<LENGTH>", + "\",\"", + "\"*\"", + "\"#\"", + "\".\"", + "\"[\"", + "\"]\"", + "\"=\"", + }; + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSSParserTokenManager.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSSParserTokenManager.java new file mode 100644 index 0000000..27841e4 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSSParserTokenManager.java @@ -0,0 +1,1176 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree&JavaCC: Do not edit this line. CSSParserTokenManager.java */ + +package org.nuiton.jaxx.compiler.css.parser; + +public class CSSParserTokenManager implements CSSParserConstants { + public java.io.PrintStream debugStream = System.out; + + public void setDebugStream(java.io.PrintStream ds) { + debugStream = ds; + } + + private int jjStopStringLiteralDfa_0(int pos, long active0) { + switch (pos) { + default: + return -1; + } + } + + private int jjStartNfa_0(int pos, long active0) { + return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1); + } + + private int jjStopAtPos(int pos, int kind) { + jjmatchedKind = kind; + jjmatchedPos = pos; + return pos + 1; + } + + private int jjStartNfaWithStates_0(int pos, int kind, int state) { + jjmatchedKind = kind; + jjmatchedPos = pos; + try { + curChar = input_stream.readChar(); + } catch (java.io.IOException e) { + return pos + 1; + } + return jjMoveNfa_0(state, pos + 1); + } + + private int jjMoveStringLiteralDfa0_0() { + switch (curChar) { + case 35: + return jjStopAtPos(0, 30); + case 42: + return jjStopAtPos(0, 29); + case 44: + return jjStopAtPos(0, 28); + case 46: + return jjStopAtPos(0, 31); + case 58: + return jjStopAtPos(0, 13); + case 59: + return jjStopAtPos(0, 15); + case 61: + return jjStopAtPos(0, 34); + case 91: + return jjStopAtPos(0, 32); + case 93: + return jjStopAtPos(0, 33); + case 123: + return jjStopAtPos(0, 16); + default: + return jjMoveNfa_0(3, 0); + } + } + + private void jjCheckNAdd(int state) { + if (jjrounds[state] != jjround) { + jjstateSet[jjnewStateCnt++] = state; + jjrounds[state] = jjround; + } + } + + private void jjAddStates(int start, int end) { + do { + jjstateSet[jjnewStateCnt++] = jjnextStates[start]; + } while (start++ != end); + } + + private void jjCheckNAddTwoStates(int state1, int state2) { + jjCheckNAdd(state1); + jjCheckNAdd(state2); + } + + private void jjCheckNAddStates(int start, int end) { + do { + jjCheckNAdd(jjnextStates[start]); + } while (start++ != end); + } + + private void jjCheckNAddStates(int start) { + jjCheckNAdd(jjnextStates[start]); + jjCheckNAdd(jjnextStates[start + 1]); + } + + static final long[] jjbitVec0 = { + 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL + }; + + private int jjMoveNfa_0(int startState, int curPos) { + int[] nextStates; + int startsAt = 0; + jjnewStateCnt = 17; + int i = 1; + jjstateSet[0] = startState; + int j, kind = 0x7fffffff; + for (; ; ) { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) { + long l = 1L << curChar; + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 3: + if ((0x3ff000000000000L & l) != 0L) { + if (kind > 7) + kind = 7; + jjCheckNAddTwoStates(0, 1); + } else if (curChar == 47) + jjAddStates(0, 1); + else if (curChar == 45) { + if (kind > 9) + kind = 9; + jjCheckNAdd(4); + } + break; + case 0: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAddTwoStates(0, 1); + break; + case 1: + if (curChar == 46) + jjCheckNAdd(2); + break; + case 2: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAdd(2); + break; + case 4: + if ((0x3ff200000000000L & l) == 0L) + break; + if (kind > 9) + kind = 9; + jjCheckNAdd(4); + break; + case 5: + if (curChar == 47) + jjAddStates(0, 1); + break; + case 6: + if (curChar == 47) + jjCheckNAddStates(2, 4); + break; + case 7: + if ((0xffffffffffffdbffL & l) != 0L) + jjCheckNAddStates(2, 4); + break; + case 8: + if ((0x2400L & l) != 0L && kind > 5) + kind = 5; + break; + case 9: + if (curChar == 10 && kind > 5) + kind = 5; + break; + case 10: + if (curChar == 13) + jjstateSet[jjnewStateCnt++] = 9; + break; + case 11: + if (curChar == 42) + jjCheckNAddTwoStates(12, 13); + break; + case 12: + if ((0xfffffbffffffffffL & l) != 0L) + jjCheckNAddTwoStates(12, 13); + break; + case 13: + if (curChar == 42) + jjAddStates(5, 6); + break; + case 14: + if ((0xffff7fffffffffffL & l) != 0L) + jjCheckNAddTwoStates(15, 13); + break; + case 15: + if ((0xfffffbffffffffffL & l) != 0L) + jjCheckNAddTwoStates(15, 13); + break; + case 16: + if (curChar == 47 && kind > 6) + kind = 6; + break; + default: + break; + } + } while (i != startsAt); + } else if (curChar < 128) { + long l = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 3: + case 4: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 9) + kind = 9; + jjCheckNAdd(4); + break; + case 7: + jjAddStates(2, 4); + break; + case 12: + jjCheckNAddTwoStates(12, 13); + break; + case 14: + case 15: + jjCheckNAddTwoStates(15, 13); + break; + default: + break; + } + } while (i != startsAt); + } else { + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 7: + if ((jjbitVec0[i2] & l2) != 0L) + jjAddStates(2, 4); + break; + case 12: + if ((jjbitVec0[i2] & l2) != 0L) + jjCheckNAddTwoStates(12, 13); + break; + case 14: + case 15: + if ((jjbitVec0[i2] & l2) != 0L) + jjCheckNAddTwoStates(15, 13); + break; + default: + break; + } + } while (i != startsAt); + } + if (kind != 0x7fffffff) { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 17 - (jjnewStateCnt = startsAt))) + return curPos; + try { + curChar = input_stream.readChar(); + } catch (java.io.IOException e) { + return curPos; + } + } + } + + private int jjStopStringLiteralDfa_3(int pos, long active0) { + switch (pos) { + default: + return -1; + } + } + + private int jjStartNfa_3(int pos, long active0) { + return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1); + } + + private int jjStartNfaWithStates_3(int pos, int kind, int state) { + jjmatchedKind = kind; + jjmatchedPos = pos; + try { + curChar = input_stream.readChar(); + } catch (java.io.IOException e) { + return pos + 1; + } + return jjMoveNfa_3(state, pos + 1); + } + + private int jjMoveStringLiteralDfa0_3() { + switch (curChar) { + case 59: + return jjStopAtPos(0, 15); + default: + return jjMoveNfa_3(3, 0); + } + } + + private int jjMoveNfa_3(int startState, int curPos) { + int[] nextStates; + int startsAt = 0; + jjnewStateCnt = 8; + int i = 1; + jjstateSet[0] = startState; + int j, kind = 0x7fffffff; + for (; ; ) { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) { + long l = 1L << curChar; + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 3: + if ((0x3ff000000000000L & l) != 0L) { + if (kind > 7) + kind = 7; + jjCheckNAddTwoStates(0, 1); + } else if (curChar == 45) { + if (kind > 12) + kind = 12; + jjCheckNAdd(4); + } + break; + case 0: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAddTwoStates(0, 1); + break; + case 1: + if (curChar == 46) + jjCheckNAdd(2); + break; + case 2: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAdd(2); + break; + case 4: + if ((0x3ff200000000000L & l) == 0L) + break; + if (kind > 12) + kind = 12; + jjCheckNAdd(4); + break; + case 6: + jjAddStates(7, 8); + break; + default: + break; + } + } while (i != startsAt); + } else if (curChar < 128) { + long l = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 3: + if ((0x7fffffe87fffffeL & l) != 0L) { + if (kind > 12) + kind = 12; + jjCheckNAdd(4); + } else if (curChar == 123) + jjCheckNAdd(6); + break; + case 4: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 12) + kind = 12; + jjCheckNAdd(4); + break; + case 5: + if (curChar == 123) + jjCheckNAdd(6); + break; + case 6: + if ((0xdfffffffffffffffL & l) != 0L) + jjCheckNAddTwoStates(6, 7); + break; + case 7: + if (curChar == 125) + kind = 21; + break; + default: + break; + } + } while (i != startsAt); + } else { + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 6: + if ((jjbitVec0[i2] & l2) != 0L) + jjAddStates(7, 8); + break; + default: + break; + } + } while (i != startsAt); + } + if (kind != 0x7fffffff) { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 8 - (jjnewStateCnt = startsAt))) + return curPos; + try { + curChar = input_stream.readChar(); + } catch (java.io.IOException e) { + return curPos; + } + } + } + + private int jjStopStringLiteralDfa_1(int pos, long active0) { + switch (pos) { + default: + return -1; + } + } + + private int jjStartNfa_1(int pos, long active0) { + return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1); + } + + private int jjStartNfaWithStates_1(int pos, int kind, int state) { + jjmatchedKind = kind; + jjmatchedPos = pos; + try { + curChar = input_stream.readChar(); + } catch (java.io.IOException e) { + return pos + 1; + } + return jjMoveNfa_1(state, pos + 1); + } + + private int jjMoveStringLiteralDfa0_1() { + switch (curChar) { + case 58: + return jjStopAtPos(0, 14); + case 59: + return jjStopAtPos(0, 15); + case 125: + return jjStopAtPos(0, 17); + default: + return jjMoveNfa_1(0, 0); + } + } + + private int jjMoveNfa_1(int startState, int curPos) { + int[] nextStates; + int startsAt = 0; + jjnewStateCnt = 50; + int i = 1; + jjstateSet[0] = startState; + int j, kind = 0x7fffffff; + for (; ; ) { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) { + long l = 1L << curChar; + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 0: + if ((0x3ff000000000000L & l) != 0L) { + if (kind > 7) + kind = 7; + jjCheckNAddStates(9, 22); + } else if (curChar == 47) + jjAddStates(23, 24); + else if (curChar == 35) + jjstateSet[jjnewStateCnt++] = 7; + else if (curChar == 34) + jjCheckNAddTwoStates(4, 5); + else if (curChar == 45) { + if (kind > 9) + kind = 9; + jjCheckNAdd(1); + } + break; + case 1: + if ((0x3ff200000000000L & l) == 0L) + break; + if (kind > 9) + kind = 9; + jjCheckNAdd(1); + break; + case 3: + if (curChar == 34) + jjCheckNAddTwoStates(4, 5); + break; + case 4: + if ((0xfffffffbffffdbffL & l) != 0L) + jjCheckNAddTwoStates(4, 5); + break; + case 5: + if (curChar == 34 && kind > 22) + kind = 22; + break; + case 6: + if (curChar == 35) + jjstateSet[jjnewStateCnt++] = 7; + break; + case 7: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 8; + break; + case 8: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 9; + break; + case 9: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 23) + kind = 23; + jjstateSet[jjnewStateCnt++] = 10; + break; + case 10: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 11; + break; + case 11: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 12; + break; + case 12: + if ((0x3ff000000000000L & l) != 0L && kind > 23) + kind = 23; + break; + case 13: + if (curChar == 47) + jjAddStates(23, 24); + break; + case 14: + if (curChar == 47) + jjCheckNAddStates(25, 27); + break; + case 15: + if ((0xffffffffffffdbffL & l) != 0L) + jjCheckNAddStates(25, 27); + break; + case 16: + if ((0x2400L & l) != 0L && kind > 5) + kind = 5; + break; + case 17: + if (curChar == 10 && kind > 5) + kind = 5; + break; + case 18: + if (curChar == 13) + jjstateSet[jjnewStateCnt++] = 17; + break; + case 19: + if (curChar == 42) + jjCheckNAddTwoStates(20, 21); + break; + case 20: + if ((0xfffffbffffffffffL & l) != 0L) + jjCheckNAddTwoStates(20, 21); + break; + case 21: + if (curChar == 42) + jjAddStates(28, 29); + break; + case 22: + if ((0xffff7fffffffffffL & l) != 0L) + jjCheckNAddTwoStates(23, 21); + break; + case 23: + if ((0xfffffbffffffffffL & l) != 0L) + jjCheckNAddTwoStates(23, 21); + break; + case 24: + if (curChar == 47 && kind > 6) + kind = 6; + break; + case 25: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAddStates(9, 22); + break; + case 26: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAddTwoStates(26, 27); + break; + case 27: + if (curChar == 46) + jjCheckNAdd(28); + break; + case 28: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAdd(28); + break; + case 29: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(30, 32); + break; + case 30: + if (curChar == 46) + jjCheckNAdd(31); + break; + case 31: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(31, 33); + break; + case 34: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(33, 35); + break; + case 35: + if (curChar == 46) + jjCheckNAdd(36); + break; + case 36: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(36, 38); + break; + case 39: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(36, 41); + break; + case 40: + if (curChar == 46) + jjCheckNAdd(41); + break; + case 41: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(42, 46); + break; + default: + break; + } + } while (i != startsAt); + } else if (curChar < 128) { + long l = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 0: + if ((0x7fffffe87fffffeL & l) != 0L) { + if (kind > 9) + kind = 9; + jjCheckNAdd(1); + } else if (curChar == 123) { + if (kind > 18) + kind = 18; + } + break; + case 1: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 9) + kind = 9; + jjCheckNAdd(1); + break; + case 2: + if (curChar == 123 && kind > 18) + kind = 18; + break; + case 4: + if ((0xffffffffefffffffL & l) != 0L) + jjAddStates(47, 48); + break; + case 7: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 8; + break; + case 8: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 9; + break; + case 9: + if ((0x7e0000007eL & l) == 0L) + break; + if (kind > 23) + kind = 23; + jjstateSet[jjnewStateCnt++] = 10; + break; + case 10: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 11; + break; + case 11: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 12; + break; + case 12: + if ((0x7e0000007eL & l) != 0L && kind > 23) + kind = 23; + break; + case 15: + jjAddStates(25, 27); + break; + case 20: + jjCheckNAddTwoStates(20, 21); + break; + case 22: + case 23: + jjCheckNAddTwoStates(23, 21); + break; + case 32: + if (curChar == 109 && kind > 25) + kind = 25; + break; + case 33: + if (curChar == 101) + jjstateSet[jjnewStateCnt++] = 32; + break; + case 37: + if (curChar == 120 && kind > 26) + kind = 26; + break; + case 38: + if (curChar == 101) + jjstateSet[jjnewStateCnt++] = 37; + break; + case 42: + if (curChar == 109 && kind > 27) + kind = 27; + break; + case 43: + if (curChar == 109) + jjCheckNAdd(42); + break; + case 44: + if (curChar == 99) + jjCheckNAdd(42); + break; + case 45: + if (curChar == 110 && kind > 27) + kind = 27; + break; + case 46: + if (curChar == 105) + jjstateSet[jjnewStateCnt++] = 45; + break; + case 47: + if (curChar == 112) + jjAddStates(49, 50); + break; + case 48: + if (curChar == 116 && kind > 27) + kind = 27; + break; + case 49: + if (curChar == 99 && kind > 27) + kind = 27; + break; + default: + break; + } + } while (i != startsAt); + } else { + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 4: + if ((jjbitVec0[i2] & l2) != 0L) + jjAddStates(47, 48); + break; + case 15: + if ((jjbitVec0[i2] & l2) != 0L) + jjAddStates(25, 27); + break; + case 20: + if ((jjbitVec0[i2] & l2) != 0L) + jjCheckNAddTwoStates(20, 21); + break; + case 22: + case 23: + if ((jjbitVec0[i2] & l2) != 0L) + jjCheckNAddTwoStates(23, 21); + break; + default: + break; + } + } while (i != startsAt); + } + if (kind != 0x7fffffff) { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 50 - (jjnewStateCnt = startsAt))) + return curPos; + try { + curChar = input_stream.readChar(); + } catch (java.io.IOException e) { + return curPos; + } + } + } + + private int jjStopStringLiteralDfa_2(int pos, long active0) { + switch (pos) { + default: + return -1; + } + } + + private int jjStartNfa_2(int pos, long active0) { + return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1); + } + + private int jjStartNfaWithStates_2(int pos, int kind, int state) { + jjmatchedKind = kind; + jjmatchedPos = pos; + try { + curChar = input_stream.readChar(); + } catch (java.io.IOException e) { + return pos + 1; + } + return jjMoveNfa_2(state, pos + 1); + } + + private int jjMoveStringLiteralDfa0_2() { + switch (curChar) { + case 59: + return jjStartNfaWithStates_2(0, 15, 3); + default: + return jjMoveNfa_2(4, 0); + } + } + + private int jjMoveNfa_2(int startState, int curPos) { + int[] nextStates; + int startsAt = 0; + jjnewStateCnt = 5; + int i = 1; + jjstateSet[0] = startState; + int j, kind = 0x7fffffff; + for (; ; ) { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) { + long l = 1L << curChar; + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 4: + if (kind > 19) + kind = 19; + jjCheckNAdd(3); + if ((0x3ff000000000000L & l) != 0L) { + if (kind > 7) + kind = 7; + jjCheckNAddTwoStates(0, 1); + } + break; + case 0: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAddTwoStates(0, 1); + break; + case 1: + if (curChar == 46) + jjCheckNAdd(2); + break; + case 2: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAdd(2); + break; + case 3: + if (kind > 19) + kind = 19; + jjCheckNAdd(3); + break; + default: + break; + } + } while (i != startsAt); + } else if (curChar < 128) { + long l = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 4: + if ((0xdfffffffffffffffL & l) != 0L) { + if (kind > 19) + kind = 19; + jjCheckNAdd(3); + } else if (curChar == 125) { + if (kind > 20) + kind = 20; + } + break; + case 3: + if ((0xdfffffffffffffffL & l) == 0L) + break; + kind = 19; + jjCheckNAdd(3); + break; + default: + break; + } + } while (i != startsAt); + } else { + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 4: + case 3: + if ((jjbitVec0[i2] & l2) == 0L) + break; + if (kind > 19) + kind = 19; + jjCheckNAdd(3); + break; + default: + break; + } + } while (i != startsAt); + } + if (kind != 0x7fffffff) { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 5 - (jjnewStateCnt = startsAt))) + return curPos; + try { + curChar = input_stream.readChar(); + } catch (java.io.IOException e) { + return curPos; + } + } + } + + static final int[] jjnextStates = { + 6, 11, 7, 8, 10, 14, 16, 6, 7, 26, 27, 29, 30, 33, 34, 35, + 38, 39, 40, 43, 44, 46, 47, 14, 19, 15, 16, 18, 22, 24, 29, 30, + 33, 34, 35, 38, 39, 40, 43, 44, 46, 47, 41, 43, 44, 46, 47, 4, + 5, 48, 49, + }; + + public static final String[] jjstrLiteralImages = { + "", null, null, null, null, null, null, null, null, null, null, null, null, + "\72", "\72", "\73", "\173", "\175", null, null, null, null, null, null, null, null, + null, null, "\54", "\52", "\43", "\56", "\133", "\135", "\75",}; + + public static final String[] lexStateNames = { + "DEFAULT", + "IN_RULE", + "JAVA_CODE_RULE", + "IN_PSEUDOCLASS", + }; + + public static final int[] jjnewLexState = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 3, -1, -1, 1, 0, 2, -1, 1, 0, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + + static final long[] jjtoToken = { + 0x7fefff281L, + }; + + static final long[] jjtoSkip = { + 0x7eL, + }; + + protected SimpleCharStream input_stream; + + private final int[] jjrounds = new int[50]; + + private final int[] jjstateSet = new int[100]; + + protected char curChar; + + public CSSParserTokenManager(SimpleCharStream stream) { + if (SimpleCharStream.staticFlag) + throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); + input_stream = stream; + } + + public CSSParserTokenManager(SimpleCharStream stream, int lexState) { + this(stream); + SwitchTo(lexState); + } + + public void ReInit(SimpleCharStream stream) { + jjmatchedPos = jjnewStateCnt = 0; + curLexState = defaultLexState; + input_stream = stream; + ReInitRounds(); + } + + private void ReInitRounds() { + int i; + jjround = 0x80000001; + for (i = 50; i-- > 0; ) + jjrounds[i] = 0x80000000; + } + + public void ReInit(SimpleCharStream stream, int lexState) { + ReInit(stream); + SwitchTo(lexState); + } + + public void SwitchTo(int lexState) { + if (lexState >= 4 || lexState < 0) + throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); + else + curLexState = lexState; + } + + protected Token jjFillToken() { + Token t = Token.newToken(jjmatchedKind); + t.kind = jjmatchedKind; + String im = jjstrLiteralImages[jjmatchedKind]; + t.image = (im == null) ? input_stream.GetImage() : im; + t.beginLine = input_stream.getBeginLine(); + t.beginColumn = input_stream.getBeginColumn(); + t.endLine = input_stream.getEndLine(); + t.endColumn = input_stream.getEndColumn(); + return t; + } + + int curLexState = 0; + + int defaultLexState = 0; + + int jjnewStateCnt; + + int jjround; + + int jjmatchedPos; + + int jjmatchedKind; + + public Token getNextToken() { + int kind; + Token specialToken = null; + Token matchedToken; + int curPos = 0; + + EOFLoop: + for (; ; ) { + try { + curChar = input_stream.BeginToken(); + } catch (java.io.IOException e) { + jjmatchedKind = 0; + matchedToken = jjFillToken(); + return matchedToken; + } + + switch (curLexState) { + case 0: + try { + input_stream.backup(0); + while (curChar <= 32 && (0x100002600L & (1L << curChar)) != 0L) + curChar = input_stream.BeginToken(); + } catch (java.io.IOException e1) { + continue EOFLoop; + } + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_0(); + break; + case 1: + try { + input_stream.backup(0); + while (curChar <= 32 && (0x100002600L & (1L << curChar)) != 0L) + curChar = input_stream.BeginToken(); + } catch (java.io.IOException e1) { + continue EOFLoop; + } + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_1(); + break; + case 2: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_2(); + break; + case 3: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_3(); + break; + } + if (jjmatchedKind != 0x7fffffff) { + if (jjmatchedPos + 1 < curPos) + input_stream.backup(curPos - jjmatchedPos - 1); + if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) { + matchedToken = jjFillToken(); + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + return matchedToken; + } else { + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + continue EOFLoop; + } + } + int error_line = input_stream.getEndLine(); + int error_column = input_stream.getEndColumn(); + String error_after = null; + boolean EOFSeen = false; + try { + input_stream.readChar(); + input_stream.backup(1); + } catch (java.io.IOException e1) { + EOFSeen = true; + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + if (curChar == '\n' || curChar == '\r') { + error_line++; + error_column = 0; + } else + error_column++; + } + if (!EOFSeen) { + input_stream.backup(1); + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + } + throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); + } + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSSParserTreeConstants.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSSParserTreeConstants.java new file mode 100644 index 0000000..b870801 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/CSSParserTreeConstants.java @@ -0,0 +1,76 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. .\CSSParserTreeConstants.java */ + + +package org.nuiton.jaxx.compiler.css.parser; + +public interface CSSParserTreeConstants { + int JJTSTYLESHEET = 0; + + int JJTRULE = 1; + + int JJTSELECTORS = 2; + + int JJTSELECTOR = 3; + + int JJTJAVACLASS = 4; + + int JJTID = 5; + + int JJTCLASS = 6; + + int JJTPSEUDOCLASS = 7; + + int JJTANIMATIONPROPERTIES = 8; + + int JJTANIMATIONPROPERTY = 9; + + int JJTDECLARATION = 10; + + int JJTPROPERTY = 11; + + int JJTEXPRESSION = 12; + + int JJTJAVACODE = 13; + + int JJTIDENTIFIER = 14; + + + String[] jjtNodeName = { + "Stylesheet", + "Rule", + "Selectors", + "Selector", + "JavaClass", + "Id", + "Class", + "PseudoClass", + "AnimationProperties", + "AnimationProperty", + "Declaration", + "Property", + "Expression", + "JavaCode", + "Identifier", + }; +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/JJTCSSParserState.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/JJTCSSParserState.java new file mode 100644 index 0000000..91030ab --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/JJTCSSParserState.java @@ -0,0 +1,148 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. .\JJTCSSParserState.java */ + + +package org.nuiton.jaxx.compiler.css.parser; + +class JJTCSSParserState { + private java.util.Stack<Node> nodes; + + private java.util.Stack<Integer> marks; + + private int sp; // number of nodes on stack + + private int mk; // current mark + + private boolean node_created; + + JJTCSSParserState() { + nodes = new java.util.Stack<>(); + marks = new java.util.Stack<>(); + sp = 0; + mk = 0; + } + + /* Determines whether the current node was actually closed and + pushed. This should only be called in the final user action of a + node scope. */ + boolean nodeCreated() { + return node_created; + } + + /* Call this to reinitialize the node stack. It is called +automatically by the parser's ReInit() method. */ + void reset() { + nodes.removeAllElements(); + marks.removeAllElements(); + sp = 0; + mk = 0; + } + + /* Returns the root node of the AST. It only makes sense to call +this after a successful parse. */ + Node rootNode() { + return nodes.elementAt(0); + } + + /* Pushes a node on to the stack. */ + void pushNode(Node n) { + nodes.push(n); + ++sp; + } + + /* Returns the node on the top of the stack, and remove it from the + stack. */ + Node popNode() { + if (--sp < mk) { + mk = marks.pop(); + } + return nodes.pop(); + } + + /* Returns the node currently on the top of the stack. */ + Node peekNode() { + return nodes.peek(); + } + + /* Returns the number of children on the stack in the current node + scope. */ + int nodeArity() { + return sp - mk; + } + + + void clearNodeScope(Node n) { + while (sp > mk) { + popNode(); + } + mk = marks.pop(); + } + + + void openNodeScope(Node n) { + marks.push(mk); + mk = sp; + n.jjtOpen(); + } + + + /* A definite node is constructed from a specified number of +children. That number of nodes are popped from the stack and +made the children of the definite node. Then the definite node +is pushed on to the stack. */ + void closeNodeScope(Node n, int num) { + mk = marks.pop(); + while (num-- > 0) { + Node c = popNode(); + c.jjtSetParent(n); + n.jjtAddChild(c, num); + } + n.jjtClose(); + pushNode(n); + node_created = true; + } + + + /* A conditional node is constructed if its condition is true. All +the nodes that have been pushed since the node was opened are +made children of the the conditional node, which is then pushed +on to the stack. If the condition is false the node is not +constructed and they are left on the stack. */ + void closeNodeScope(Node n, boolean condition) { + if (condition) { + int a = nodeArity(); + mk = marks.pop(); + while (a-- > 0) { + Node c = popNode(); + c.jjtSetParent(n); + n.jjtAddChild(c, a); + } + n.jjtClose(); + pushNode(n); + node_created = true; + } else { + mk = marks.pop(); + node_created = false; + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/Node.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/Node.java new file mode 100644 index 0000000..a5c4716 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/Node.java @@ -0,0 +1,73 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. Node.java */ + + +package org.nuiton.jaxx.compiler.css.parser; + +/* All AST nodes must implement this interface. It provides basic + machinery for constructing the parent and child relationships + between nodes. */ + +public interface Node { + + /** + * This method is called after the node has been made the current + * node. It indicates that child nodes can now be added to it. + */ + public void jjtOpen(); + + /** + * This method is called after all the child nodes have been + * added. + */ + public void jjtClose(); + + /** + * This pair of methods are used to inform the node of its + * parent. + * + * @param n node + */ + public void jjtSetParent(Node n); + + public Node jjtGetParent(); + + /** + * This method tells the node to add its argument to the node's + * list of children. + * + * @param n node + * @param i pos + */ + public void jjtAddChild(Node n, int i); + + /** + * @param i pos + * @return a child node. The children are numbered + * from zero, left to right. + */ + public Node jjtGetChild(int i); + + /** @return the number of children the node has. */ + public int jjtGetNumChildren(); +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/ParseException.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/ParseException.java new file mode 100644 index 0000000..6e06c79 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/ParseException.java @@ -0,0 +1,42 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */ + +package org.nuiton.jaxx.compiler.css.parser; + +public class ParseException extends org.nuiton.jaxx.compiler.java.parser.ParseException { + private static final long serialVersionUID = 229575674880359031L; + + public ParseException() { + super(); + } + + + public ParseException(String message) { + super(message); + } + + + public ParseException(String message, int line, int column) { + super(message, line, column); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/SimpleCharStream.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/SimpleCharStream.java new file mode 100644 index 0000000..1f147f4 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/SimpleCharStream.java @@ -0,0 +1,429 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.0 */ + +package org.nuiton.jaxx.compiler.css.parser; + +/** + * An implementation of interface CharStream, where the stream is assumed to + * contain only ASCII characters (without unicode processing). + */ + +public class SimpleCharStream { + public static final boolean staticFlag = false; + + int bufsize; + + int available; + + int tokenBegin; + + public int bufpos = -1; + + protected int bufline[]; + + protected int bufcolumn[]; + + protected int column = 0; + + protected int line = 1; + + protected boolean prevCharIsCR = false; + + protected boolean prevCharIsLF = false; + + protected java.io.Reader inputStream; + + protected char[] buffer; + + protected int maxNextCharInd = 0; + + protected int inBuf = 0; + + protected int tabSize = 8; + + protected void setTabSize(int i) { + tabSize = i; + } + + protected int getTabSize(int i) { + return tabSize; + } + + + protected void ExpandBuff(boolean wrapAround) { + char[] newbuffer = new char[bufsize + 2048]; + int newbufline[] = new int[bufsize + 2048]; + int newbufcolumn[] = new int[bufsize + 2048]; + + try { + if (wrapAround) { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + System.arraycopy(buffer, 0, newbuffer, + bufsize - tokenBegin, bufpos); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); + bufcolumn = newbufcolumn; + + maxNextCharInd = (bufpos += (bufsize - tokenBegin)); + } else { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + bufcolumn = newbufcolumn; + + maxNextCharInd = (bufpos -= tokenBegin); + } + } catch (Throwable t) { + throw new Error(t.getMessage()); + } + + + bufsize += 2048; + available = bufsize; + tokenBegin = 0; + } + + protected void FillBuff() throws java.io.IOException { + if (maxNextCharInd == available) { + if (available == bufsize) { + if (tokenBegin > 2048) { + bufpos = maxNextCharInd = 0; + available = tokenBegin; + } else if (tokenBegin < 0) + bufpos = maxNextCharInd = 0; + else + ExpandBuff(false); + } else if (available > tokenBegin) + available = bufsize; + else if ((tokenBegin - available) < 2048) + ExpandBuff(true); + else + available = tokenBegin; + } + + int i; + try { + if ((i = inputStream.read(buffer, maxNextCharInd, + available - maxNextCharInd)) == -1) { + inputStream.close(); + throw new java.io.IOException(); + } else + maxNextCharInd += i; + } catch (java.io.IOException e) { + --bufpos; + backup(0); + if (tokenBegin == -1) + tokenBegin = bufpos; + throw e; + } + } + + public char BeginToken() throws java.io.IOException { + tokenBegin = -1; + char c = readChar(); + tokenBegin = bufpos; + + return c; + } + + protected void UpdateLineColumn(char c) { + column++; + + if (prevCharIsLF) { + prevCharIsLF = false; + line += (column = 1); + } else if (prevCharIsCR) { + prevCharIsCR = false; + if (c == '\n') { + prevCharIsLF = true; + } else + line += (column = 1); + } + + switch (c) { + case '\r': + prevCharIsCR = true; + break; + case '\n': + prevCharIsLF = true; + break; + case '\t': + column--; + column += (tabSize - (column % tabSize)); + break; + default: + break; + } + + bufline[bufpos] = line; + bufcolumn[bufpos] = column; + } + + public char readChar() throws java.io.IOException { + if (inBuf > 0) { + --inBuf; + + if (++bufpos == bufsize) + bufpos = 0; + + return buffer[bufpos]; + } + + if (++bufpos >= maxNextCharInd) + FillBuff(); + + char c = buffer[bufpos]; + + UpdateLineColumn(c); + return (c); + } + + /** + * @return ??? + * @see #getEndColumn + * @deprecated + */ + + public int getColumn() { + return bufcolumn[bufpos]; + } + + /** + * @return ??? + * @see #getEndLine + * @deprecated + */ + + public int getLine() { + return bufline[bufpos]; + } + + public int getEndColumn() { + return bufcolumn[bufpos]; + } + + public int getEndLine() { + return bufline[bufpos]; + } + + public int getBeginColumn() { + return bufcolumn[tokenBegin]; + } + + public int getBeginLine() { + return bufline[tokenBegin]; + } + + public void backup(int amount) { + + inBuf += amount; + if ((bufpos -= amount) < 0) + bufpos += bufsize; + } + + public SimpleCharStream(java.io.Reader dstream, int startline, + int startcolumn, int buffersize) { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + } + + public SimpleCharStream(java.io.Reader dstream, int startline, + int startcolumn) { + this(dstream, startline, startcolumn, 4096); + } + + public SimpleCharStream(java.io.Reader dstream) { + this(dstream, 1, 1, 4096); + } + + public void ReInit(java.io.Reader dstream, int startline, + int startcolumn, int buffersize) { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + if (buffer == null || buffersize != buffer.length) { + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + } + prevCharIsLF = prevCharIsCR = false; + tokenBegin = inBuf = maxNextCharInd = 0; + bufpos = -1; + } + + public void ReInit(java.io.Reader dstream, int startline, + int startcolumn) { + ReInit(dstream, startline, startcolumn, 4096); + } + + public void ReInit(java.io.Reader dstream) { + ReInit(dstream, 1, 1, 4096); + } + + public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, + int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { + this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + public SimpleCharStream(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) { + this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); + } + + public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, + int startcolumn) throws java.io.UnsupportedEncodingException { + this(dstream, encoding, startline, startcolumn, 4096); + } + + public SimpleCharStream(java.io.InputStream dstream, int startline, + int startcolumn) { + this(dstream, startline, startcolumn, 4096); + } + + public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { + this(dstream, encoding, 1, 1, 4096); + } + + public SimpleCharStream(java.io.InputStream dstream) { + this(dstream, 1, 1, 4096); + } + + public void ReInit(java.io.InputStream dstream, String encoding, int startline, + int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { + ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) { + ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); + } + + public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { + ReInit(dstream, encoding, 1, 1, 4096); + } + + public void ReInit(java.io.InputStream dstream) { + ReInit(dstream, 1, 1, 4096); + } + + public void ReInit(java.io.InputStream dstream, String encoding, int startline, + int startcolumn) throws java.io.UnsupportedEncodingException { + ReInit(dstream, encoding, startline, startcolumn, 4096); + } + + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn) { + ReInit(dstream, startline, startcolumn, 4096); + } + + public String GetImage() { + if (bufpos >= tokenBegin) + return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); + else + return new String(buffer, tokenBegin, bufsize - tokenBegin) + + new String(buffer, 0, bufpos + 1); + } + + public char[] GetSuffix(int len) { + char[] ret = new char[len]; + + if ((bufpos + 1) >= len) + System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); + else { + System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, + len - bufpos - 1); + System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); + } + + return ret; + } + + public void Done() { + buffer = null; + bufline = null; + bufcolumn = null; + } + + /** + * Method to adjust line and column numbers for the start of a token. + * + * @param newLine ? + * @param newCol ? + */ + public void adjustBeginLineColumn(int newLine, int newCol) { + int start = tokenBegin; + int len; + + if (bufpos >= tokenBegin) { + len = bufpos - tokenBegin + inBuf + 1; + } else { + len = bufsize - tokenBegin + bufpos + 1 + inBuf; + } + + int i = 0, j = 0, k; + int nextColDiff, columnDiff = 0; + + while (i < len && + bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) { + bufline[j] = newLine; + nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; + bufcolumn[j] = newCol + columnDiff; + columnDiff = nextColDiff; + i++; + } + + if (i < len) { + bufline[j] = newLine++; + bufcolumn[j] = newCol + columnDiff; + + while (i++ < len) { + if (bufline[j = start % bufsize] != bufline[++start % bufsize]) + bufline[j] = newLine++; + else + bufline[j] = newLine; + } + } + + line = bufline[j]; + column = bufcolumn[j]; + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/SimpleNode.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/SimpleNode.java new file mode 100644 index 0000000..d8123ac --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/SimpleNode.java @@ -0,0 +1,149 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. SimpleNode.java */ + + +package org.nuiton.jaxx.compiler.css.parser; + +public class SimpleNode implements Node { + protected Node parent; + + protected Node[] children; + + protected int id; + + protected CSSParser parser; + + public Token firstToken; + + public Token lastToken; + + + public SimpleNode(int i) { + id = i; + } + + public SimpleNode(CSSParser p, int i) { + this(i); + parser = p; + } + + + public int getId() { + return id; + } + + public void jjtOpen() { + } + + public void jjtClose() { + } + + public void jjtSetParent(Node n) { + parent = n; + } + + public Node jjtGetParent() { + return parent; + } + + public SimpleNode getParent() { + return (SimpleNode) parent; + } + + public void jjtAddChild(Node n, int i) { + if (children == null) { + children = new Node[i + 1]; + } else if (i >= children.length) { + Node c[] = new Node[i + 1]; + System.arraycopy(children, 0, c, 0, children.length); + children = c; + } + children[i] = n; + } + + public Node jjtGetChild(int i) { + return children[i]; + } + + public SimpleNode getChild(int i) { + return (SimpleNode) children[i]; + } + + public int jjtGetNumChildren() { + return children == null ? 0 : children.length; + } + + /* You can override these two methods in subclasses of SimpleNode to +customize the way the node appears when the tree is dumped. If +your output uses more than one line you should override +toString(String), otherwise overriding toString() is probably all +you need to do. */ + + @Override + public String toString() { + return getClass().getName() + "[" + getText() + "]"; + } + + public String toString(String prefix) { + return prefix + toString(); + } + + /* Override this method if you want to customize how the node dumps + out its children. */ + + public void dump(String prefix) { + System.out.println(toString(prefix)); + if (children != null) { + for (Node aChildren : children) { + SimpleNode n = (SimpleNode) aChildren; + if (n != null) { + n.dump(prefix + " "); + } + } + } + } + + private void appendSpecialTokens(StringBuilder s, Token st) { + if (st != null) { + appendSpecialTokens(s, st.specialToken); + s.append(st.image); + } + } + + + /** @return the text of the tokens comprising this node. */ + public String getText() { + StringBuilder text = new StringBuilder(); + Token t = firstToken; + while (t != null) { + appendSpecialTokens(text, t.specialToken); + text.append(t.image); + if (t == lastToken) + break; + t = t.next; + } + + return text.toString(); + } +} + diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/Token.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/Token.java new file mode 100644 index 0000000..6f001dd --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/Token.java @@ -0,0 +1,98 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */ + +package org.nuiton.jaxx.compiler.css.parser; + +/** Describes the input token stream. */ + +public class Token { + + /** + * An integer that describes the kind of this token. This numbering + * system is determined by JavaCCParser, and a table of these numbers is + * stored in the file ...Constants.java. + */ + public int kind; + + /** + * beginLine and beginColumn describe the position of the first character + * of this token; endLine and endColumn describe the position of the + * last character of this token. + */ + public int beginLine, beginColumn, endLine, endColumn; + + /** The string image of the token. */ + public String image; + + /** + * A reference to the next regular (non-special) token from the input + * stream. If this is the last token from the input stream, or if the + * token manager has not read tokens beyond this one, this field is + * set to null. This is true only if this token is also a regular + * token. Otherwise, see below for a description of the contents of + * this field. + */ + public Token next; + + /** + * This field is used to access special tokens that occur prior to this + * token, but after the immediately preceding regular (non-special) token. + * If there are no such special tokens, this field is set to null. + * When there are more than one such special token, this field refers + * to the last of these special tokens, which in turn refers to the next + * previous special token through its specialToken field, and so on + * until the first special token (whose specialToken field is null). + * The next fields of special tokens refer to other special tokens that + * immediately follow it (without an intervening regular token). If there + * is no such token, this field is null. + */ + public Token specialToken; + + /** Returns the image. */ + public String toString() { + return image; + } + + /** + * Returns a new Token object, by default. However, if you want, you + * can create and return subclass objects based on the value of ofKind. + * Simply add the cases to the switch for all those special cases. + * For example, if you have a subclass of Token called IDToken that + * you want to create if ofKind is ID, simlpy add something like : + * + * case MyParserConstants.ID : return new IDToken(); + * + * to the following switch statement. Then you can cast matchedToken + * variable to the appropriate type and use it in your lexical actions. + * + * @param ofKind kind of token + * @return the new token + */ + public static Token newToken(int ofKind) { + switch (ofKind) { + default: + return new Token(); + } + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/TokenMgrError.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/TokenMgrError.java new file mode 100644 index 0000000..6587f99 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/css/parser/TokenMgrError.java @@ -0,0 +1,149 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */ + +package org.nuiton.jaxx.compiler.css.parser; + +public class TokenMgrError extends Error { + /* + * Ordinals for various reasons why an Error of this type can be thrown. + */ + + /** Lexical error occured. */ + static final int LEXICAL_ERROR = 0; + + /** An attempt wass made to create a second instance of a static token manager. */ + static final int STATIC_LEXER_ERROR = 1; + + /** Tried to change to an invalid lexical state. */ + static final int INVALID_LEXICAL_STATE = 2; + + /** Detected (and bailed out of) an infinite loop in the token manager. */ + static final int LOOP_DETECTED = 3; + + /** + * Indicates the reason why the exception is thrown. It will have + * one of the above 4 values. + */ + int errorCode; + + private static final long serialVersionUID = -4308847190164230336L; + + /** + * Replaces unprintable characters by their espaced (or unicode escaped) + * equivalents in the given string + * + * @param str text to espace + * @return the espaced text + */ + protected static String addEscapes(String str) { + StringBuilder retval = new StringBuilder(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) { + case 0: + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u").append(s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + } + } + return retval.toString(); + } + + /** + * @param EOFSeen : indicates if EOF caused the lexicl error + * @param lexState : lexical state in which this error occured + * @param errorLine : line number when the error occured + * @param errorColumn : column number when the error occured + * @param errorAfter : prefix that was seen before this error occured + * @param curChar : the offending character + * Note: You can customize the lexical error message by modifying this method. + * @return a detailed message for the Error when it is thrown by the + * token manager to indicate a lexical error. + */ + protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { + return "Lexical error at line " + + errorLine + ", column " + + errorColumn + ". Encountered: " + + (EOFSeen ? "<EOF> " : "\"" + addEscapes(String.valueOf(curChar)) + "\"" + " (" + (int) curChar + "), ") + + "after : \"" + addEscapes(errorAfter) + "\""; + } + + /** + * You can also modify the body of this method to customize your error messages. + * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not + * of end-users concern, so you can return something like : + * + * "Internal Error : Please file a bug report .... " + * + * from this method for such cases in the release version of your parser. + */ + @Override + public String getMessage() { + return super.getMessage(); + } + + /* + * Constructors of various flavors follow. + */ + + public TokenMgrError() { + } + + public TokenMgrError(String message, int reason) { + super(message); + errorCode = reason; + } + + public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { + this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/decorators/BoxedCompiledObjectDecorator.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/decorators/BoxedCompiledObjectDecorator.java new file mode 100644 index 0000000..c5e33ea --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/decorators/BoxedCompiledObjectDecorator.java @@ -0,0 +1,77 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.decorators; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompiledObject.ChildRef; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.java.JavaFile; +import org.nuiton.jaxx.runtime.SwingUtil; + +/** + * A decorator to surround a compiled object (should be a component at least) + * with a JXLayer. + * + * @author Tony Chemit - chemit@codelutin.com + * @plexus.component role-hint="boxed" role="org.nuiton.jaxx.compiler.CompiledObjectDecorator" + * @since 1.2 + */ +public class BoxedCompiledObjectDecorator extends DefaultCompiledObjectDecorator { + + @Override + public String getName() { + return "boxed"; + } + + @Override + public void finalizeCompiler(JAXXCompiler compiler, + CompiledObject root, + CompiledObject object, + JavaFile javaFile, + String packageName, + String className, + String fullClassName) throws ClassNotFoundException { + CompiledObject parent = object.getParent(); + if (parent == null) { + parent = root; + } + for (ChildRef child : parent.getChilds()) { + if (child.getChild() == object) { + String javaCode = child.getChildJavaCode(); + String type = compiler.getImportedType(SwingUtil.class); + child.setChildJavaCode( + type + + ".boxComponentWithJxLayer(" + javaCode + ")"); + break; + } + } + super.finalizeCompiler(compiler, + root, + object, + javaFile, + packageName, + className, + fullClassName + ); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java new file mode 100644 index 0000000..cd6495e --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java @@ -0,0 +1,359 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.decorators; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompiledObjectDecorator; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import org.nuiton.jaxx.compiler.java.JavaElementFactory; +import org.nuiton.jaxx.compiler.java.JavaField; +import org.nuiton.jaxx.compiler.java.JavaFile; +import org.nuiton.jaxx.compiler.java.JavaMethod; +import org.nuiton.jaxx.compiler.script.ScriptInitializer; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.Modifier; +import java.util.Map.Entry; + +/** + * The default decorator to use on all compiled objects. + * + * @author Tony Chemit - chemit@codelutin.com + * @plexus.component role-hint="default" role="org.nuiton.jaxx.compiler.CompiledObjectDecorator" + * @since 1.2 + */ +public class DefaultCompiledObjectDecorator implements CompiledObjectDecorator { + + + /** Logger */ + protected static final Log log = + LogFactory.getLog(DefaultCompiledObjectDecorator.class); + + @Override + public String getName() { + return "default"; + } + + @Override + public void finalizeCompiler(JAXXCompiler compiler, + CompiledObject root, + CompiledObject object, + JavaFile javaFile, + String packageName, + String className, + String fullClassName) throws ClassNotFoundException { + + if (object instanceof ScriptInitializer) { + + // nothing to finalize + return; + } + + String fqn = JAXXCompiler.getCanonicalName(object); + + String id = object.getId(); + + if (log.isDebugEnabled()) { + log.debug("finalize " + id); + } + + boolean override = object.isOverride(); + + if (override) { + + if (object.isOverrideType()) { + + // add a specialized getter, only if type has changed + + String methodName = object.getGetterName(); + + String type = object.getSimpleType(); + String body = "return (" + type + ") super." + methodName + "();"; + + if (log.isDebugEnabled()) { + log.debug("Add specialized getter " + methodName + " : " + body); + } + JavaMethod getter = JavaElementFactory.newMethod( + Modifier.PUBLIC, + fqn, + methodName, + body, + true + ); + javaFile.addMethod(getter); + } + } else { + + int access = id.startsWith("$") ? Modifier.PRIVATE : + Modifier.PROTECTED; + if (root.equals(object)) { + + // add the generic type if required + String type = className + root.getGenericTypes(); + + JavaField field = JavaElementFactory.newField(access, + type, + id, + false, + null + ); + + javaFile.addSimpleField(field); + } else { + + JavaField field = JavaElementFactory.newField(access, + fqn, + id, + override + ); + javaFile.addField(field, object.isJavaBean()); + } + } + + if (compiler.inlineCreation(object) || root.equals(object)) { + + // nothing more to do here + return; + } + + String code = getCreationCode(compiler, object); + + // tchemit 20100519 Do not add the method only if overriden and code is null + + if (code != null) { + + JavaMethod javaMethod = JavaElementFactory.newMethod( + Modifier.PROTECTED, + JAXXCompilerFinalizer.TYPE_VOID, + object.getCreationMethodName(), + code, + override + ); + javaFile.addMethod(javaMethod); + } + } + + @Override + public String getCreationCode(JAXXCompiler compiler, + CompiledObject object) throws CompilerException { + if (object instanceof ScriptInitializer) { + throw new IllegalStateException( + "A script initializer can not come in getCreationcode method!"); + } + String eol = JAXXCompiler.getLineSeparator(); + + StringBuilder result = new StringBuilder(); + StringBuilder init = new StringBuilder(); + + if (compiler.getRootObject().equals(object) || + compiler.inlineCreation(object)) { + result.append("// inline creation of ").append(object.getId()); + } + + if (object.isJavaBean() && object.getJavaBeanInitCode() != null) { + init.append(object.getJavaBeanInitCode()); + } else if (object.getInitializer() != null) { + init.append(object.getInitializer()); + } + + boolean addToObjectMap = true; + String id = TypeManager.getJavaCode(object.getId()); + String constructorParams = object.getConstructorParams(); + + if (object.isOverride()) { + + if (init.length() == 0 && constructorParams == null) { + + // no init code is given, no need to add to objectMap + addToObjectMap = false; + } + } + + if (addToObjectMap && init.length() == 0) { + + // on special init, use constructor + String canonicalName = JAXXCompiler.getCanonicalName(object); + String impl = compiler.getImportedType(canonicalName); + + init.append("new ").append(impl).append("("); + + if (constructorParams != null) { + init.append(constructorParams); + } + init.append(")"); + } + + String superCall = "super." + object.getCreationMethodName() + "();"; + + if (addToObjectMap) { + result.append(eol); + result.append("$objectMap.put("); + result.append(id); + result.append(", "); + result.append(object.getId()).append(" = "); + result.append(init); + result.append(");"); + result.append(eol); + } else { + if (object.isOverride()) { + + // when override has no special init code, just use the super method + + result.append(superCall); + + } + } + + String initCode = object.getInitializationCode(compiler); + if (StringUtils.isNotEmpty(initCode)) { + result.append(eol).append(initCode); + } + + // add client properties + addClientProperties(object, result, eol); + + String code = result.toString(); + + if (!compiler.inlineCreation(object) && + object.isOverride() && + superCall.equals(code.trim())) { + + // special case : when override but do nothing more + // method creation can be skipped + return null; + } + return code; + } + + @Override + public String createCompleteSetupMethod(JAXXCompiler compiler, + CompiledObject object, + JavaFile javaFile) { + StringBuilder code = new StringBuilder(); + String eol = JAXXCompiler.getLineSeparator(); + if (object.getId().startsWith("$")) { + String additionCode = object.getAdditionCode(); + //TC-20091025 only generate the code if not empty + if (!additionCode.isEmpty()) { + code.append("// inline complete setup of "); + code.append(object.getId()); + code.append(eol); + code.append(additionCode); + } + } else { + //TODO-TC-20091202 should always create the method to make api more consistent ? + //TODO-TC-20091202 While generating, we deal with this case, it seems not sa natural + //TODO-TC-20091202 to NOT having the setup method on each public property ? +// code.append(object.getAdditionMethodName()).append("();").append(eol); +// if (!additionCode.isEmpty()) { +// additionCode = "if (!allComponentsCreated) {" + eol + " return;" + eol + "}" + eol + additionCode; +// } +// javaFile.addMethod(JavaFileGenerator.newMethod(Modifier.PROTECTED, "void", object.getAdditionMethodName(), additionCode, false)); + String additionCode = object.getAdditionCode(); + if (additionCode.length() > 0) { + code.append(object.getAdditionMethodName()).append("();").append(eol); +// additionCode = "if (!allComponentsCreated) {" + eol + " return;" + eol + "}" + eol + additionCode; + javaFile.addMethod(JavaElementFactory.newMethod( + Modifier.PROTECTED, + JAXXCompilerFinalizer.TYPE_VOID, + object.getAdditionMethodName(), + additionCode, + false) + ); + } + } + return code.toString(); + } + + @Override + public boolean createInitializer(JAXXCompiler compiler, + CompiledObject root, + CompiledObject object, + StringBuilder code, + boolean lastWasMethodCall) { + String eol = JAXXCompiler.getLineSeparator(); + + if (object instanceof ScriptInitializer) { + + // initializer has special direct treatment : can not be in a method + // just push code to compiler + code.append(object.getInitializationCode(compiler)); + + // nothing to initialize of a script + return lastWasMethodCall; + } + + if (root.equals(object)) { + String rootCode = root.getInitializationCode(compiler); + if (rootCode != null && rootCode.length() > 0) { + code.append("// inline creation of "); + code.append(object.getId()); + code.append(eol); + code.append(rootCode); + //TC-20091025 generate client properties at creation time (not at setup time) + // in some case can save to create a setup method (when there is only client properties + // to store) + addClientProperties(object, code, eol); + code.append(eol); + } + } else { + if (!object.isOverride()) { + if (compiler.inlineCreation(object)) { + if (lastWasMethodCall) { + lastWasMethodCall = false; + } + code.append(getCreationCode(compiler, object)); + } else { + code.append(object.getCreationMethodName()).append("();"); + code.append(eol); + lastWasMethodCall = true; + } + } + } + return lastWasMethodCall; + } + + protected void addClientProperties(CompiledObject object, + StringBuilder code, + String eol) { + //TC-20090327 generate client properties + if (object.hasClientProperties()) { + // generate putClientProperty invocations + for (Entry<String, String> entry : + object.getClientProperties().entrySet()) { + code.append(object.getJavaCode()); + code.append(".putClientProperty(\""); + code.append(entry.getKey()); + code.append("\", "); + code.append(entry.getValue()); + code.append(");"); + code.append(eol); + } + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java new file mode 100644 index 0000000..8289a33 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java @@ -0,0 +1,218 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.decorators; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompiledObjectDecorator; +import org.nuiton.jaxx.compiler.CompilerConfiguration; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import org.nuiton.jaxx.compiler.java.JavaElementFactory; +import org.nuiton.jaxx.compiler.java.JavaFile; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.runtime.swing.help.JAXXHelpUI; + +import java.awt.Component; +import java.lang.reflect.Modifier; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import static org.nuiton.jaxx.compiler.java.JavaElementFactory.newArgument; + +/** + * A decorator to place on a root compiled object to process javaHelp on the file. + * + * @author Tony Chemit - chemit@codelutin.com + * @plexus.component role-hint="help" role="org.nuiton.jaxx.compiler.CompiledObjectDecorator" + * @since 1.2 + */ +public class HelpRootCompiledObjectDecorator extends DefaultCompiledObjectDecorator { + + /** the list of discovered helpId */ + protected static Set<String> helpIds = new HashSet<>(); + + @Override + public String getName() { + return "help"; + } + + protected String getBrokerFQN(JAXXCompiler compiler) { + return compiler.getConfiguration().getHelpBrokerFQN(); + } + + protected String getHelpId(CompiledObject o) { + String helpID = null; + if (o.hasClientProperties()) { + helpID = o.getClientProperty("help"); + } + return helpID; + } + + @Override + public void finalizeCompiler(JAXXCompiler compiler, + CompiledObject root, + CompiledObject object, + JavaFile javaFile, + String packageName, + String className, + String fullClassName) throws ClassNotFoundException { + super.finalizeCompiler(compiler, + root, + object, + javaFile, + packageName, + className, + fullClassName) + ; + CompilerConfiguration options = compiler.getConfiguration(); + + if (options.isGenerateHelp()) { + + // add JAXXHelpUI interface + Class<?> validatorInterface = JAXXHelpUI.class; + String helpBrokerFQN = getBrokerFQN(compiler); + + boolean needInterface = isNeedInterface(compiler, + validatorInterface); + + if (needInterface) { + + // only add the contract if needed + + if (log.isDebugEnabled()) { + log.debug("Add " + validatorInterface + " on " + + javaFile.getName() + " : parent " + + JAXXCompiler.getCanonicalName( + compiler.getRootObject())); + } + + javaFile.addInterface(validatorInterface.getName() + + "<" + helpBrokerFQN + ">"); + } + + javaFile.addMethod(JavaElementFactory.newMethod( + Modifier.PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + "registerHelpId", + "broker.installUI(component, helpId);", + true, + newArgument(helpBrokerFQN, "broker"), + newArgument(Component.class.getName(), "component"), + newArgument(JAXXCompilerFinalizer.TYPE_STRING, "helpId")) + ); + + javaFile.addMethod(JavaElementFactory.newMethod( + Modifier.PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + "showHelp", + "getBroker().showHelp(this, helpId);", + true, + newArgument(JAXXCompilerFinalizer.TYPE_STRING, "helpId")) + ); + + StringBuilder buffer = new StringBuilder(); + + String eol = JAXXCompiler.getLineSeparator(); + +// if (options.isGenerateHelp()) { + + // add code to init javax help system + Iterator<CompiledObject> itr = compiler.getObjectCreationOrder(); + + for (; itr.hasNext(); ) { + CompiledObject o = itr.next(); + String helpID = getHelpId(o); + if (helpID != null) { + buffer.append(eol); + // detects a helpId to register + buffer.append("registerHelpId(_broker, "); + buffer.append(o.getJavaCode()); + buffer.append(", "); + buffer.append(helpID); + buffer.append(");"); + //keep the helpID for helpSet generation + helpIds.add(helpID); + } + } +// } + if (buffer.length() > 0) { + + String type = compiler.getImportedType(helpBrokerFQN); + + buffer.append(eol).append("_broker.prepareUI(this);"); + buffer.append(eol); + + // add the calls + compiler.appendLateInitializer("// help broker setup" + eol); + compiler.appendLateInitializer(type + " _broker = getBroker();"); + compiler.appendLateInitializer(buffer.toString()); + } + } + } + + /** + * Detects if the given {@code compiler} need the validatorInterface. + * + * We need to test it deeply since the interface is added by the decorator + * and is not present on the symbol table of compiled objects. + * + * @param compiler the compiler to test + * @param validatorInterface the validator interface to seek for + * @return {@code true} if we need to add the interface, {@code false} otherwise + * @throws ClassNotFoundException if could not find a class + * @since 2.4 + */ + protected boolean isNeedInterface(JAXXCompiler compiler, + Class<?> validatorInterface) throws ClassNotFoundException { + if (compiler.isSuperClassAware(validatorInterface)) { + + // parent has already the interface + return false; + } + CompiledObject root = compiler.getRootObject(); + ClassDescriptor rootObjectClass = root.getObjectClass(); + String superClassName = JAXXCompiler.getCanonicalName(rootObjectClass); + JAXXCompiler parentCompiler = compiler.getEngine().getJAXXCompiler(superClassName); + if (parentCompiler == null) { + + // parent was not compiled + return true; + } + + CompiledObjectDecorator decorator = parentCompiler.getRootObject().getDecorator(); + + if (decorator != null && decorator instanceof HelpRootCompiledObjectDecorator) { + + // parent is already with help, no need of the interface + return false; + } + + // ok must add the interface + return isNeedInterface(parentCompiler, validatorInterface); + } + + public static Set<String> getHelpIds() { + return new HashSet<>(helpIds); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/AbstractFinalizer.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/AbstractFinalizer.java new file mode 100644 index 0000000..4312a4d --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/AbstractFinalizer.java @@ -0,0 +1,87 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.finalizers; + +import org.nuiton.jaxx.compiler.java.JavaElementFactory; +import org.nuiton.jaxx.compiler.java.JavaField; +import org.nuiton.jaxx.compiler.java.JavaFile; +import org.nuiton.jaxx.compiler.java.JavaMethod; + +/** + * Base implementation of a {@link JAXXCompilerFinalizer}. + * + * Contains commons methods and constants. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.4 + */ +public abstract class AbstractFinalizer implements JAXXCompilerFinalizer { + + /** + * Clones the given {@code field} and adds it to the {@code file} as a + * property via the method {@link JavaFile#addField(JavaField)}. + * + * @param file the file where to add the cloned field + * @param field the field to clone + * @since 2.4 + */ + protected void addField(JavaFile file, JavaField field) { + + JavaField clonedField = JavaElementFactory.cloneField(field); + file.addField(clonedField); + } + + /** + * Clones the given {@code method} and adds it to the {@code file} as a + * simple method using the method {@link JavaFile#addMethod(JavaMethod)}. + * + * @param file the file where to add the cloned field + * @param field the field to clone + * @since 2.4 + */ + protected void addSimpleField(JavaFile file, JavaField field) { + + JavaField clonedField = JavaElementFactory.cloneField(field); + file.addSimpleField(clonedField); + } + + /** + * Clones the given {@code field} and adds it to the {@code file} as a + * simple field using the method {@link JavaFile#addSimpleField(JavaField)}. + * + * @param file the file where to add the cloned method + * @param method the method to clone + * @param types optional types to use to simplify the body of the method + * @since 2.4 + */ + protected void addMethod(JavaFile file, JavaMethod method, String... types) { + + JavaMethod clonedMethod = JavaElementFactory.cloneMethod(method); + if (types.length > 0) { + String body = clonedMethod.getBody(); + String simplifiedBody = file.simplifyCode(body, types); + clonedMethod.setBody(simplifiedBody); + } + file.addMethod(clonedMethod); + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/DefaultFinalizer.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/DefaultFinalizer.java new file mode 100644 index 0000000..9ba8439 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/DefaultFinalizer.java @@ -0,0 +1,1191 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.finalizers; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompiledObjectDecorator; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.EventHandler; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.binding.DataBinding; +import org.nuiton.jaxx.compiler.binding.writers.DefaultJAXXBindingWriter; +import org.nuiton.jaxx.compiler.binding.writers.JAXXBindingWriter; +import org.nuiton.jaxx.compiler.binding.writers.SimpleJAXXObjectBindingWriter; +import org.nuiton.jaxx.compiler.java.JavaArgument; +import org.nuiton.jaxx.compiler.java.JavaElementFactory; +import org.nuiton.jaxx.compiler.java.JavaField; +import org.nuiton.jaxx.compiler.java.JavaFile; +import org.nuiton.jaxx.compiler.java.JavaFileGenerator; +import org.nuiton.jaxx.compiler.java.JavaMethod; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.Base64Coder; +import org.nuiton.jaxx.runtime.JAXXBinding; +import org.nuiton.jaxx.runtime.JAXXContext; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.JAXXObjectDescriptor; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Container; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import static java.lang.reflect.Modifier.FINAL; +import static java.lang.reflect.Modifier.PRIVATE; +import static java.lang.reflect.Modifier.PROTECTED; +import static java.lang.reflect.Modifier.PUBLIC; +import static java.lang.reflect.Modifier.STATIC; +import static java.lang.reflect.Modifier.isProtected; +import static java.lang.reflect.Modifier.isPublic; +import static org.nuiton.jaxx.compiler.java.JavaElementFactory.newArgument; +import static org.nuiton.jaxx.compiler.java.JavaElementFactory.newField; +import static org.nuiton.jaxx.compiler.java.JavaElementFactory.newMethod; + +/** + * This class is a refactoring of the {@link JAXXCompiler}. + * + * We delegate now the generation of a {@link JAXXObject} to this class, the + * {@link JAXXCompiler} now only deals with the compilation of files. + * + * @author Tony Chemit - chemit@codelutin.com + * @plexus.component role-hint="default" role="org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer" + */ +public class DefaultFinalizer extends AbstractFinalizer { + + /** Logger. */ + protected static final Log log = LogFactory.getLog(DefaultFinalizer.class); + + private static final String PARAMETER_NAME_$BINDING = "$binding"; + + public static final String FIELD_NAME_$BINDING_SOURCES = "$bindingSources"; + + public static final String FIELD_NAME_$OBJECT_MAP = "$objectMap"; + + public static final String FIELD_NAME_$ACTIVE_BINDINGS = "$activeBindings"; + + public static final String FIELD_NAME_$PREVIOUS_VALUES = "$previousValues"; + + public static final String FIELD_NAME_$BINDINGS = "$bindings"; + + public static final String FIELD_NAME_$PROPERTY_CHANGE_SUPPORT = "$propertyChangeSupport"; + + public static final String FIELD_NAME_DELEGATE_CONTEXT = "delegateContext"; + + public static final String FIELD_NAME_SERIAL_VERSION_UID = "serialVersionUID"; + + public static final String FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR = "$jaxxObjectDescriptor"; + + public static final String METHOD_NAME_$GET_JAXXOBJECT_DESCRIPTOR = "$getJAXXObjectDescriptor"; + + public static final String METHOD_NAME_REGISTER_DATA_BINDING = "registerDataBinding"; + + public static final String METHOD_NAME_REMOVE_DATA_BINDING = "removeDataBinding"; + + public static final String METHOD_NAME_APPLY_DATA_BINDING = "applyDataBinding"; + + public static final String METHOD_NAME_PROCESS_DATA_BINDING = "processDataBinding"; + + public static final String METHOD_NAME_FIRE_PROPERTY_CHANGE = "firePropertyChange"; + + public static final String METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT = "$getPropertyChangeSupport"; + + public static final String METHOD_NAME_$INITIALIZE = "$initialize"; + public static final String METHOD_NAME_$INITIALIZE_01_CREATE_COMPONENTS = "$initialize_01_createComponents"; + public static final String METHOD_NAME_$INITIALIZE_02_REGISTER_DATA_BINDINGS = "$initialize_02_registerDataBindings"; + public static final String METHOD_NAME_$INITIALIZE_03_FINALIZE_CREATE_COMPONENTS = "$initialize_03_finalizeCreateComponents"; + public static final String METHOD_NAME_$INITIALIZE_04_APPLY_DATA_BINDINGS = "$initialize_04_applyDataBindings"; + public static final String METHOD_NAME_$INITIALIZE_05_SET_PROPERTIES = "$initialize_05_setProperties"; + public static final String METHOD_NAME_$INITIALIZE_06_FINALIZE_INITIALIZE = "$initialize_06_finalizeInitialize"; + + /** serialVersionUID field */ + + protected static final JavaField SERIAL_VERSION_UID_FIELD = newField( + PRIVATE | STATIC | FINAL, + "long", + FIELD_NAME_SERIAL_VERSION_UID, + false, + "1L" + ); + + /** + * + */ + protected static final JavaField ACTIVE_BINDINGS_FIELD = newField( + PROTECTED, + List.class.getName() + "<" + TYPE_OBJECT + ">", + FIELD_NAME_$ACTIVE_BINDINGS, + false, + "new %s<" + TYPE_OBJECT + ">()", + ArrayList.class.getName() + ); + + /** + * + */ + protected static final JavaField BINDING_SOURCES_FIELD = newField( + PROTECTED, + Map.class.getName() + "<" + TYPE_STRING + ", " + TYPE_OBJECT + ">", + FIELD_NAME_$BINDING_SOURCES, + false, + "new %s<" + TYPE_STRING + ", " + TYPE_OBJECT + ">()", + HashMap.class.getName() + ); + + /** + * + */ + protected static final JavaField OBJECT_MAP_FIELD = newField( + PROTECTED, + Map.class.getName() + "<" + TYPE_STRING + ", " + TYPE_OBJECT + ">", + FIELD_NAME_$OBJECT_MAP, + true, + "new %s<" + TYPE_STRING + ", " + TYPE_OBJECT + ">()", + HashMap.class.getName() + ); + + /** + * + */ + protected static final JavaField PREVIOUS_VALUES_FIELD = newField( + PROTECTED, + Map.class.getName() + "<?,?>", FIELD_NAME_$PREVIOUS_VALUES, + false, + "new %s<" + TYPE_OBJECT + ", " + TYPE_OBJECT + ">()", + HashMap.class.getName() + ); + + /** + * + */ + protected static final JavaField BINDINGS_FIELD = newField( + PROTECTED | FINAL, + Map.class.getName() + "<" + TYPE_STRING + ", " + JAXXBinding.class.getName() + ">", + FIELD_NAME_$BINDINGS, + false, + "new %s<" + TYPE_STRING + ", %s>()", + TreeMap.class.getName(), + JAXXBinding.class.getName() + ); + + /** + * + */ + protected static final JavaField PROPERTY_CHANGE_SUPPORT_FIELD = newField( + PROTECTED, + PropertyChangeSupport.class.getName(), + FIELD_NAME_$PROPERTY_CHANGE_SUPPORT, + false + ); + + /** + * + */ + protected static final JavaMethod GET_CONTEXT_VALUE_METHOD = newMethod( + PUBLIC, + "<T> T", + "getContextValue", + "return " + FIELD_NAME_DELEGATE_CONTEXT + ".getContextValue(clazz, null);", + true, + newArgument("Class<T>", "clazz") + ); + + /** + * + */ + protected static final JavaMethod GET_CONTEXT_VALUE_NAMED_METHOD = newMethod( + PUBLIC, + "<T> T", + "getContextValue", + "return " + FIELD_NAME_DELEGATE_CONTEXT + ".getContextValue(clazz, name);", + true, + newArgument("Class<T>", "clazz"), newArgument(TYPE_STRING, "name") + ); + + /** + * + */ + protected static final JavaMethod SET_CONTEXT_VALUE_NAMED_METHOD = newMethod( + PUBLIC, + "<T> " + TYPE_VOID, + "setContextValue", + FIELD_NAME_DELEGATE_CONTEXT + ".setContextValue(o, name);", + true, + newArgument("T", "o"), newArgument(TYPE_STRING, "name")); + + /** + * + */ + protected static final JavaMethod SET_CONTEXT_VALUE_METHOD = newMethod( + PUBLIC, + "<T> " + TYPE_VOID, + "setContextValue", + FIELD_NAME_DELEGATE_CONTEXT + ".setContextValue(o, null);", + true, + newArgument("T", "o") + ); + + /** + * + */ + protected static final JavaMethod REMOVE_CONTEXT_VALUE_NAMED_METHOD = newMethod( + PUBLIC, + "<T> " + TYPE_VOID, + "removeContextValue", + FIELD_NAME_DELEGATE_CONTEXT + ".removeContextValue(clazz, name);", + true, + newArgument("Class<T>", "clazz"), + newArgument(TYPE_STRING, "name") + ); + + /** + * + */ + protected static final JavaMethod REMOVE_CONTEXT_VALUE_METHOD = newMethod( + PUBLIC, + "<T> " + TYPE_VOID, + "removeContextValue", + FIELD_NAME_DELEGATE_CONTEXT + ".removeContextValue(clazz, null);", + true, + newArgument("Class<T>", "clazz") + ); + + /** + * + */ + protected static final JavaMethod GET_PARENT_CONTAINER_MORE_METHOD = newMethod( + PUBLIC, + "<O extends Container> O", + "getParentContainer", + "return %s.getParentContainer(source, clazz);", + true, + newArgument(TYPE_OBJECT, "source"), + newArgument("Class<O>", "clazz") + ); + + /** + * + */ + protected static final JavaMethod GET_PARENT_CONTAINER_METHOD = newMethod( + PUBLIC, + "<O extends Container> O", + "getParentContainer", + "return %s.getParentContainer(this, clazz);", + true, + newArgument("Class<O>", "clazz") + ); + + /** + * + */ + protected static final JavaMethod GET_OBJECT_BY_ID_METHOD = newMethod( + PUBLIC, TYPE_OBJECT, "getObjectById", + "return " + FIELD_NAME_$OBJECT_MAP + ".get(id);", + true, + newArgument(TYPE_STRING, "id") + ); + + /** + * + */ + protected static final JavaMethod GET_JAXX_OBJECT_DESCRIPTOR_METHOD = newMethod( + PUBLIC | STATIC, + JAXXObjectDescriptor.class.getName(), + METHOD_NAME_$GET_JAXXOBJECT_DESCRIPTOR, + "return %s.decodeCompressedJAXXObjectDescriptor(" + + FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR + ");", + false + ); + + /** + * + */ + protected static final JavaMethod PROCESS_DATA_BINDING_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + METHOD_NAME_PROCESS_DATA_BINDING, + METHOD_NAME_PROCESS_DATA_BINDING + "(" + PARAMETER_NAME_$BINDING + ", false);", + true, + newArgument(TYPE_STRING, PARAMETER_NAME_$BINDING) + ); + + /** + * + */ + protected static final JavaMethod REGISTER_DATA_BINDING_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + METHOD_NAME_REGISTER_DATA_BINDING, + FIELD_NAME_$BINDINGS + ".put(binding.getId(), binding);", + true, + newArgument(JAXXBinding.class.getName(), "binding") + ); + + /** + * + */ + protected static final JavaMethod GET_DATA_BINDINGS_METHOD = newMethod( + PUBLIC, + JAXXBinding.class.getName() + "[]", + "getDataBindings", + "return " + FIELD_NAME_$BINDINGS + ".values().toArray(new %s[" + FIELD_NAME_$BINDINGS + ".size()]);", + true + ); + + /** + * + */ + protected static final JavaMethod GET_DATA_BINDING_METHOD = newMethod( + PUBLIC, + JAXXBinding.class.getName(), + "getDataBinding", + "return " + FIELD_NAME_$BINDINGS + ".get(bindingId);", + true, + newArgument(TYPE_STRING, "bindingId") + ); + + + /** + * + */ + protected static final JavaMethod FIRE_PROPERTY_CHANGE_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + METHOD_NAME_FIRE_PROPERTY_CHANGE, + "super." + METHOD_NAME_FIRE_PROPERTY_CHANGE + "(propertyName, oldValue, newValue);", + true, + newArgument(TYPE_STRING, "propertyName"), + newArgument(TYPE_OBJECT, "oldValue"), + newArgument(TYPE_OBJECT, "newValue") + ); + + /** + * + */ + protected static final JavaMethod FIRE_PROPERTY_CHANGE_NAMED_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + METHOD_NAME_FIRE_PROPERTY_CHANGE, + METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "()." + METHOD_NAME_FIRE_PROPERTY_CHANGE + "(propertyName, oldValue, newValue);", + true, + newArgument(TYPE_STRING, "propertyName"), + newArgument(TYPE_OBJECT, "oldValue"), + newArgument(TYPE_OBJECT, "newValue") + ); + + /** + * + */ + protected static final JavaMethod GET_PROPERTY_CHANGE_SUPPORT_METHOD = newMethod( + 0, + PropertyChangeSupport.class.getName(), + METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT, + "if (" + FIELD_NAME_$PROPERTY_CHANGE_SUPPORT + " == null)\n" + + " " + FIELD_NAME_$PROPERTY_CHANGE_SUPPORT + " = new PropertyChangeSupport(this);\n" + + "return " + FIELD_NAME_$PROPERTY_CHANGE_SUPPORT + ";", + false + ); + + /** + * + */ + protected static final JavaMethod ADD_PROPERTY_CHANGE_SUPPORT_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + "addPropertyChangeListener", + METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "().addPropertyChangeListener(listener);", + true, + newArgument(PropertyChangeListener.class.getName(), "listener") + ); + + /** + * + */ + protected static final JavaMethod ADD_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + "addPropertyChangeListener", + METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "().addPropertyChangeListener(property, listener);", + true, + newArgument(TYPE_STRING, "property"), + newArgument(PropertyChangeListener.class.getName(), "listener") + ); + + /** + * + */ + protected static final JavaMethod REMOVE_PROPERTY_CHANGE_SUPPORT_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + "removePropertyChangeListener", + METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "().removePropertyChangeListener(listener);", + true, + newArgument(PropertyChangeListener.class.getName(), "listener") + ); + + /** + * + */ + protected static final JavaMethod REMOVE_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + "removePropertyChangeListener", + METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "().removePropertyChangeListener(property, listener);", + true, + newArgument(TYPE_STRING, "property"), + newArgument(PropertyChangeListener.class.getName(), "listener") + ); + + public static final String METHOD_NAME$BEFORE_INIT = "beforeInit"; + + private static final String METHOD_NAME$AFTER_INIT = "afterInit"; + + @Override + public boolean accept(JAXXCompiler compiler) { + + // alwyas use the default finalizer + return true; + } + + @Override + public void finalizeCompiler(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) throws ClassNotFoundException { + + String fullClassName = packageName != null ? + packageName + "." + className : className; + if (root == null) { + throw new CompilerException("root tag can not be null"); + } + ClassDescriptor superclass = root.getObjectClass(); + boolean superclassIsJAXXObject = + compiler.isSuperClassAware(JAXXObject.class); + javaFile.setModifiers(PUBLIC); + javaFile.setName(fullClassName); + javaFile.setSimpleName(className); + + javaFile.setSuperClass(JAXXCompiler.getCanonicalName(superclass)); + javaFile.setSuperclassIsJAXXObject(superclassIsJAXXObject); + + javaFile.addInterface(compiler.getExtraInterfaces()); + javaFile.setAbstractClass(compiler.isAbstractClass()); + javaFile.setGenericType(compiler.getGenericType()); + javaFile.setSuperGenericType(compiler.getSuperGenericType()); + + if (!superclassIsJAXXObject) { + javaFile.addInterface(JAXXObject.class.getName()); + } + } + + @Override + public void prepareJavaFile(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) throws ClassNotFoundException { + + // add logger support if required + addLoggerSupport(compiler, javaFile, className); + + // add JAXXObject support if required + addJAXXObjectSupport(compiler, root, javaFile); + + addSimpleField(javaFile, SERIAL_VERSION_UID_FIELD); + + addJAXXObjectDescriptorField(compiler, javaFile); + addMethod(javaFile, GET_JAXX_OBJECT_DESCRIPTOR_METHOD, JAXXUtil.class.getName()); + + addPreviousValuesField(compiler, javaFile, root); + + DataBinding[] bindings = compiler.getBindingHelper().getDataBindings(); + + addInitializerMethod(compiler, javaFile); + addInitialize_01_createComponents(compiler, javaFile); + addInitialize_02_registerDataBindings(compiler, javaFile); + addInitialize_03_finalizeCreateComponents(compiler, javaFile); + addInitialize_04_applyDataBindings(compiler, javaFile); + addInitialize_05_setProperties(compiler, javaFile); + addInitialize_06_finalizeInitialize(compiler, javaFile); + + javaFile.addBodyCode(compiler.getBodyCode().toString()); + + addDataBindings(compiler, javaFile, bindings); + addEventHandlers(compiler, javaFile); + } + + protected void addDataBindings(JAXXCompiler compiler, + JavaFile javaFile, + DataBinding[] bindings) { + + if (bindings.length < 1) { + // no data bindings + return; + } + + // add import on each type of JAXXBinding used + for (JAXXBindingWriter<?> writer : bindingWriters) { + if (writer.isUsed()) { + javaFile.addImport(writer.getType()); + } + } + + // for each binding declare the constant Id + + for (DataBinding binding : bindings) { + + String constantId = binding.getConstantId(); + + // add the data binding constant Id + + compiler.addSimpleField(newField( + (constantId.startsWith("BINDING_$") ? PRIVATE : PUBLIC) | FINAL | STATIC, + TYPE_STRING, + constantId, + false, + TypeManager.getJavaCode(binding.getRealId())) + ); + } + } + + protected void addJAXXObjectSupport(JAXXCompiler compiler, + CompiledObject root, + JavaFile javaFile) { + + String jaxxContextImplementorClass = + compiler.getConfiguration().getJaxxContextClass().getName(); + + boolean superclassIsJAXXObject = javaFile.isSuperclassIsJAXXObject(); + + if (superclassIsJAXXObject) { + + //FIXME tchemit 2011-01-30 : We should not add it (if user want to use it in script it must add the correct import + // Will be removed in version 3.0 with strict imports features + javaFile.addImport(JAXXContext.class); + + } else { + + // add JAXXObject support + addField(javaFile, OBJECT_MAP_FIELD); + addSimpleField(javaFile, BINDING_SOURCES_FIELD); + addSimpleField(javaFile, ACTIVE_BINDINGS_FIELD); + addSimpleField(javaFile, BINDINGS_FIELD); + javaFile.addMethod(GET_OBJECT_BY_ID_METHOD); + addMethod(javaFile, REGISTER_DATA_BINDING_METHOD); + addMethod(javaFile, GET_DATA_BINDINGS_METHOD, JAXXBinding.class.getSimpleName()); + addMethod(javaFile, GET_DATA_BINDING_METHOD, JAXXBinding.class.getSimpleName()); + + javaFile.addMethod(createApplyDataBindingMethod()); + javaFile.addMethod(createProcessDataBindingMethod()); + javaFile.addMethod(createRemoveDataBindingMethod()); + + // JAXXContext + + String type = + javaFile.getImportedType(jaxxContextImplementorClass); + + javaFile.addField(newField( + PROTECTED | FINAL, + JAXXContext.class.getName(), + FIELD_NAME_DELEGATE_CONTEXT, + true, + "new " + type + "()") + ); + + javaFile.addImport(Container.class); + + javaFile.addMethod(SET_CONTEXT_VALUE_METHOD); + javaFile.addMethod(SET_CONTEXT_VALUE_NAMED_METHOD); + javaFile.addMethod(GET_CONTEXT_VALUE_METHOD); + javaFile.addMethod(GET_CONTEXT_VALUE_NAMED_METHOD); + javaFile.addMethod(REMOVE_CONTEXT_VALUE_METHOD); + javaFile.addMethod(REMOVE_CONTEXT_VALUE_NAMED_METHOD); + addMethod(javaFile, GET_PARENT_CONTAINER_METHOD, SwingUtil.class.getName()); + addMethod(javaFile, GET_PARENT_CONTAINER_MORE_METHOD, SwingUtil.class.getName()); + + // PropertyChangeSupport + addPropertyChangeSupport(root, javaFile); + + // DataBinding + javaFile.addMethod(PROCESS_DATA_BINDING_METHOD); + } + } + + protected void addLoggerSupport(JAXXCompiler compiler, JavaFile javaFile, String className) { + if (compiler.getConfiguration().isAddLogger()) { + + javaFile.addSimpleField(newField( + PRIVATE | STATIC | FINAL, + Log.class.getName(), + "log", + false, + "%s.getLog(" + className + ".class)", + LogFactory.class.getName() + ) + ); + } + } + + protected final JAXXBindingWriter<?>[] bindingWriters = new + JAXXBindingWriter[]{new SimpleJAXXObjectBindingWriter(), + new DefaultJAXXBindingWriter() + }; + + /*---------------------------------------------------------------------------------*/ + /*-- Create fields ----------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + protected JavaField addJAXXObjectDescriptorField(JAXXCompiler compiler, + JavaFile javaFile) { + JavaField field; + try { + JAXXObjectDescriptor descriptor = compiler.getJAXXObjectDescriptor(); + String data = Base64Coder.serialize(descriptor, true); + /*ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(new GZIPOutputStream(buffer)); + out.writeObject(descriptor); + out.close(); + // the use of the weird deprecated constructor is deliberate -- we need to store the data as a String + // in the compiled class file, since byte array initialization is horribly inefficient compared to + // String initialization. So we store the bytes in the String, and we quite explicitly want a 1:1 + // mapping between bytes and chars, with the high byte of the char set to zero. We can then safely + // reconstitute the original byte[] at a later date. This is unquestionably an abuse of the String + // type, but if we could efficiently store a byte[] we wouldn't have to do this. + String data = new String(buffer.toByteArray(), 0);*/ + + int sizeLimit = 65000; // constant strings are limited to 64K, and I'm not brave enough to push right up to the limit + if (data.length() < sizeLimit) { + field = newField(PRIVATE | STATIC | FINAL, + TYPE_STRING, + FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR, + false, + TypeManager.getJavaCode(data) + ); + + } else { + StringBuilder initializer = new StringBuilder(); + for (int i = 0; i < data.length(); i += sizeLimit) { + String name = FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR + i; + javaFile.addField(newField( + PRIVATE | STATIC, + TYPE_STRING, + name, + false, + TypeManager.getJavaCode(data.substring(i, Math.min(i + sizeLimit, data.length())))) + ); + if (initializer.length() > 0) { + initializer.append(" + "); + } + initializer.append(TYPE_STRING + ".valueOf("); + initializer.append(name); + initializer.append(")"); + } + field = newField(PRIVATE | STATIC | FINAL, + TYPE_STRING, + FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR, + false, + initializer.toString() + ); + } + } catch (IOException e) { + throw new RuntimeException("Internal error: can't-happen error", e); + } + javaFile.addSimpleField(field); + return field; + } + + protected void addPreviousValuesField(JAXXCompiler compiler, + JavaFile javaFile, CompiledObject root) { + + boolean superclassIsJAXXObject = javaFile.isSuperclassIsJAXXObject(); + + if (compiler.getStylesheet() != null) { + boolean needField = true; + if (superclassIsJAXXObject) { + // check alreay exists on parent + ClassDescriptor superclass = root.getObjectClass(); + if (log.isDebugEnabled()) { + log.debug("superclass : " + superclass); + } + JAXXCompiler parentCompiler = + compiler.getEngine().getJAXXCompiler( + superclass.getName() + ); + + if (parentCompiler != null) { + needField = parentCompiler.getStylesheet() == null; + } else { + try { + superclass.getDeclaredFieldDescriptor( + PREVIOUS_VALUES_FIELD.getName()); + needField = false; + } catch (NoSuchFieldException ex) { + // field not found + } + } + if (needField && log.isDebugEnabled()) { + log.debug("no " + PREVIOUS_VALUES_FIELD.getName() + + " field in super class"); + } + } + if (needField) { + addSimpleField(javaFile, PREVIOUS_VALUES_FIELD); + } + } + } + + /*---------------------------------------------------------------------------------*/ + /*-- Create methods ---------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + protected void addPropertyChangeSupport(CompiledObject root, + JavaFile javaFile) { + ClassDescriptor currentClass = root.getObjectClass(); + MethodDescriptor firePropertyChange = null; + while (firePropertyChange == null && currentClass != null) { + try { + firePropertyChange = currentClass.getDeclaredMethodDescriptor( + METHOD_NAME_FIRE_PROPERTY_CHANGE, + ClassDescriptorHelper.getClassDescriptor(String.class), + ClassDescriptorHelper.getClassDescriptor(Object.class), + ClassDescriptorHelper.getClassDescriptor(Object.class) + ); + + } catch (NoSuchMethodException e) { + currentClass = currentClass.getSuperclass(); + } + } + + int modifiers = firePropertyChange != null ? + firePropertyChange.getModifiers() : 0; + if (isPublic(modifiers)) { + // we have all the support we need + return; + } + if (isProtected(modifiers)) { + + // there is property change support but the firePropertyChange method is protected + javaFile.addMethod(FIRE_PROPERTY_CHANGE_METHOD); + } else { + + addField(javaFile, PROPERTY_CHANGE_SUPPORT_FIELD); + addMethod(javaFile, GET_PROPERTY_CHANGE_SUPPORT_METHOD, + PropertyChangeSupport.class.getName()); + addMethod(javaFile, ADD_PROPERTY_CHANGE_SUPPORT_METHOD); + addMethod(javaFile, ADD_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD); + addMethod(javaFile, REMOVE_PROPERTY_CHANGE_SUPPORT_METHOD); + addMethod(javaFile, REMOVE_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD); + addMethod(javaFile, FIRE_PROPERTY_CHANGE_NAMED_METHOD); + } + } + + protected void addInitialize_01_createComponents(JAXXCompiler compiler, JavaFile javaFile) { + StringBuilder body = new StringBuilder(); + body.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); + String eol = JAXXCompiler.getLineSeparator(); + if (javaFile.isSuperclassIsJAXXObject()) { + body.append(String.format("super.%s();", METHOD_NAME_$INITIALIZE_01_CREATE_COMPONENTS)).append(eol); + } + + CompiledObject root = compiler.getRootObject(); + + String rootId = root.getId(); + body.append(FIELD_NAME_$OBJECT_MAP + ".put(").append(TypeManager.getJavaCode(rootId)).append(", ").append(rootId).append(");").append(eol); + + Iterator<CompiledObject> i = compiler.getObjectCreationOrder(); + boolean lastWasMethodCall = false; + //TODO-TC20091025 should do init of root first ? +// root.getDecorator().createInitializer(compiler, root, root, code, lastWasMethodCall); + while (i.hasNext()) { + CompiledObject object = i.next(); + if (object == root) { + continue; + } + CompiledObjectDecorator decorator = object.getDecorator(); + lastWasMethodCall = decorator.createInitializer(compiler, + root, + object, + body, + lastWasMethodCall + ); + } + root.getDecorator().createInitializer(compiler, + root, + root, + body, + lastWasMethodCall + ); + if (compiler.getInitializer().length() > 0) { + body.append(compiler.getInitializer()); + } + JavaMethod method = newMethod(PROTECTED, + TYPE_VOID, + METHOD_NAME_$INITIALIZE_01_CREATE_COMPONENTS, + body.toString(), + javaFile.isSuperclassIsJAXXObject() + ); + javaFile.addMethod(method); + } + + protected void addInitialize_02_registerDataBindings(JAXXCompiler compiler, JavaFile javaFile) { + StringBuilder body = new StringBuilder(); + body.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); + String eol = JAXXCompiler.getLineSeparator(); + if (javaFile.isSuperclassIsJAXXObject()) { + body.append(String.format("super.%s();", METHOD_NAME_$INITIALIZE_02_REGISTER_DATA_BINDINGS)).append(eol); + } + JavaFileGenerator generator = new JavaFileGenerator(eol, true); + //TODO use optimized writer for simple cases + + for (JAXXBindingWriter<?> writer : bindingWriters) { + writer.reset(); + } + + // add import on each type of JAXXBinding used + + for (JAXXBindingWriter<?> writer : bindingWriters) { + if (writer.isUsed()) { + compiler.getJavaFile().addImport(writer.getType()); + } + } + + DataBinding[] bindings = compiler.getBindingHelper().getDataBindings(); + body.append("// register "); + body.append(bindings.length); + body.append(" data bindings"); + body.append(eol); + + for (DataBinding binding : bindings) { + + for (JAXXBindingWriter<?> writer : bindingWriters) { + if (writer.accept(binding)) { + writer.write(binding, generator, body); + break; + } + } + } + JavaMethod method = newMethod(PROTECTED, + TYPE_VOID, + METHOD_NAME_$INITIALIZE_02_REGISTER_DATA_BINDINGS, + body.toString(), + javaFile.isSuperclassIsJAXXObject() + ); + javaFile.addMethod(method); + } + + protected void addInitialize_03_finalizeCreateComponents(JAXXCompiler compiler, JavaFile javaFile) { + + StringBuilder body = new StringBuilder(); + body.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); + String eol = JAXXCompiler.getLineSeparator(); + if (javaFile.isSuperclassIsJAXXObject()) { + body.append(String.format("super.%s();", METHOD_NAME_$INITIALIZE_03_FINALIZE_CREATE_COMPONENTS)).append(eol); + } + for (CompiledObject object : compiler.getObjects().values()) { + CompiledObjectDecorator decorator = object.getDecorator(); + body.append(decorator.createCompleteSetupMethod(compiler, + object, + javaFile) + ); + } + JavaMethod method = newMethod(PROTECTED, + TYPE_VOID, + METHOD_NAME_$INITIALIZE_03_FINALIZE_CREATE_COMPONENTS, + body.toString(), + javaFile.isSuperclassIsJAXXObject() + ); + javaFile.addMethod(method); + } + + protected void addInitialize_04_applyDataBindings(JAXXCompiler compiler, JavaFile javaFile) { + StringBuilder body = new StringBuilder(); + String eol = JAXXCompiler.getLineSeparator(); + body.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); + if (javaFile.isSuperclassIsJAXXObject()) { + body.append(String.format("super.%s();", METHOD_NAME_$INITIALIZE_04_APPLY_DATA_BINDINGS)).append(eol); + } + DataBinding[] bindings = compiler.getBindingHelper().getDataBindings(); + if (bindings.length > 0) { + + body.append(eol); + body.append("// apply "); + body.append(bindings.length); + body.append(" data bindings"); + body.append(eol); + body.append(JAXXUtil.class.getSimpleName()); + body.append("." + METHOD_NAME_APPLY_DATA_BINDING + "(this, " + FIELD_NAME_$BINDINGS + ".keySet());"); + body.append(eol); + + } + JavaMethod method = newMethod(PROTECTED, + TYPE_VOID, + METHOD_NAME_$INITIALIZE_04_APPLY_DATA_BINDINGS, + body.toString(), + javaFile.isSuperclassIsJAXXObject() + ); + javaFile.addMethod(method); + } + + protected void addInitialize_05_setProperties(JAXXCompiler compiler, JavaFile javaFile) { + StringBuilder body = new StringBuilder(); + String eol = JAXXCompiler.getLineSeparator(); + body.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); + if (javaFile.isSuperclassIsJAXXObject()) { + body.append(String.format("super.%s();", METHOD_NAME_$INITIALIZE_05_SET_PROPERTIES)).append(eol); + } + DataBinding[] bindings = compiler.getBindingHelper().getSimpleBindings(); + if (bindings.length > 0) { + + StringBuilder initCode = new StringBuilder(); + + for (DataBinding binding : bindings) { + + String binding1 = binding.getInitDataBinding(); + if (binding1 != null && !binding1.trim().isEmpty()) { + initCode.append(binding1); + } + } + + if (initCode.length() > 0) { + + body.append(eol); + body.append("// apply "); + body.append(bindings.length); + body.append(" property setters"); + body.append(eol); + body.append(initCode.toString().trim()); + + } + } + + if (compiler.getLateInitializer().length() > 0) { + body.append("// late initializer").append(eol); + body.append(compiler.getLateInitializer()).append(eol); + } + JavaMethod method = newMethod(PROTECTED, + TYPE_VOID, + METHOD_NAME_$INITIALIZE_05_SET_PROPERTIES, + body.toString(), + javaFile.isSuperclassIsJAXXObject() + ); + javaFile.addMethod(method); + } + + protected void addInitialize_06_finalizeInitialize(JAXXCompiler compiler, JavaFile javaFile) { + StringBuilder body = new StringBuilder(); + body.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); + String eol = JAXXCompiler.getLineSeparator(); + if (javaFile.isSuperclassIsJAXXObject()) { + body.append(String.format("super.%s();", METHOD_NAME_$INITIALIZE_06_FINALIZE_INITIALIZE)).append(eol); + } + JavaMethod method = newMethod(PROTECTED, + TYPE_VOID, + METHOD_NAME_$INITIALIZE_06_FINALIZE_INITIALIZE, + body.toString(), + javaFile.isSuperclassIsJAXXObject() + ); + javaFile.addMethod(method); + } + + protected void addEventHandlers(JAXXCompiler compiler, + JavaFile javaFile) { + + for (Map.Entry<String, Map<ClassDescriptor, List<EventHandler>>> e1 : compiler.getEventHandlers().entrySet()) { + + // outer loop is iterating over different objects (well, technically, different Java expressions) + for (Map.Entry<ClassDescriptor, List<EventHandler>> e2 : e1.getValue().entrySet()) { + + // iterate over different types of listeners for this particular object (MouseListener, ComponentListener, etc.) + for (EventHandler handler : e2.getValue()) { + + // iterate over individual event handlers of a single type + String methodName = compiler.getEventHandlerMethodName(handler); + MethodDescriptor listenerMethod = handler.getListenerMethod(); + if (listenerMethod.getParameterTypes().length != 1) { + throw new CompilerException( + "Expected event handler " + + listenerMethod.getName() + " of class " + + handler.getListenerClass() + + " to have exactly one argument" + ); + } + + ClassDescriptor eventType = + listenerMethod.getParameterTypes()[0]; + + JavaArgument argument = + JavaElementFactory.newArgument( + JAXXCompiler.getCanonicalName(eventType), + "event" + ); + + String body = JavaFileGenerator.addDebugLoggerInvocation(compiler, "event"); + body += handler.getJavaCode(); + javaFile.addMethod(JavaElementFactory.newMethod( + PUBLIC, + TYPE_VOID, + methodName, + body, + false, + argument) + ); + } + } + } + } + + public JavaMethod addInitializerMethod(JAXXCompiler compiler, JavaFile javaFile) { + + String eol = JAXXCompiler.getLineSeparator(); + StringBuilder code = new StringBuilder(); + code.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); + code.append(compiler.getRootObject().getId()).append(" = this;").append(eol); + + boolean useHandler = compiler.isUseHandler(); + + if (useHandler) { + String handler = compiler.getUiHandler(); + String handlerType = compiler.getImportedType(handler); + code.append("handler = new ").append(handlerType).append("();").append(eol); + code.append("handler." + METHOD_NAME$BEFORE_INIT + "(this);").append(eol); + } + + if (javaFile.isSuperclassIsJAXXObject()) { + code.append("super." + METHOD_NAME_$INITIALIZE + "();").append(eol); + } else { + code.append(METHOD_NAME_$INITIALIZE_01_CREATE_COMPONENTS + "();"); + code.append(eol); + + code.append(METHOD_NAME_$INITIALIZE_02_REGISTER_DATA_BINDINGS + "();"); + code.append(eol); + + code.append(METHOD_NAME_$INITIALIZE_03_FINALIZE_CREATE_COMPONENTS + "();"); + code.append(eol); + + code.append(METHOD_NAME_$INITIALIZE_04_APPLY_DATA_BINDINGS + "();"); + code.append(eol); + code.append(METHOD_NAME_$INITIALIZE_05_SET_PROPERTIES + "();"); + code.append(eol); + code.append(METHOD_NAME_$INITIALIZE_06_FINALIZE_INITIALIZE + "();"); + code.append(eol); + } + + if (useHandler) { + code.append("handler." + METHOD_NAME$AFTER_INIT + "(this);").append(eol); + } + JavaMethod method = JavaElementFactory.newMethod(PROTECTED, + TYPE_VOID, + METHOD_NAME_$INITIALIZE, + code.toString(), + javaFile.isSuperclassIsJAXXObject() + ); + javaFile.addMethod(method); + return method; + } + + protected JavaMethod createApplyDataBindingMethod() { + StringBuilder buffer = new StringBuilder(); + String eol = JAXXCompiler.getLineSeparator(); + + buffer.append("if (" + FIELD_NAME_$BINDINGS + ".containsKey(" + PARAMETER_NAME_$BINDING + ")) {"); + buffer.append(eol); + buffer.append(" getDataBinding(" + PARAMETER_NAME_$BINDING + ")." + METHOD_NAME_APPLY_DATA_BINDING + "();"); + buffer.append(eol); + buffer.append("}"); + buffer.append(eol); + buffer.append(METHOD_NAME_PROCESS_DATA_BINDING + "(" + PARAMETER_NAME_$BINDING + ");"); + return JavaElementFactory.newMethod( + PUBLIC, + TYPE_VOID, + METHOD_NAME_APPLY_DATA_BINDING, + buffer.toString(), + true, + JavaElementFactory.newArgument(TYPE_STRING, PARAMETER_NAME_$BINDING) + ); + } + + protected JavaMethod createRemoveDataBindingMethod() { + StringBuilder buffer = new StringBuilder(); + String eol = JAXXCompiler.getLineSeparator(); + + buffer.append("if (" + FIELD_NAME_$BINDINGS + ".containsKey(" + PARAMETER_NAME_$BINDING + ")) {"); + buffer.append(eol); + buffer.append(" getDataBinding(" + PARAMETER_NAME_$BINDING + ")." + METHOD_NAME_REMOVE_DATA_BINDING + "();"); + buffer.append(eol); + buffer.append("}"); + return JavaElementFactory.newMethod( + PUBLIC, + TYPE_VOID, + METHOD_NAME_REMOVE_DATA_BINDING, + buffer.toString(), + true, + JavaElementFactory.newArgument(TYPE_STRING, PARAMETER_NAME_$BINDING) + ); + } + + protected JavaMethod createProcessDataBindingMethod() { + StringBuilder code = new StringBuilder(); + String eol = JAXXCompiler.getLineSeparator(); + + // the force parameter forces the update to happen even if it is already in activeBindings. This + // is used on superclass invocations b/c by the time the call gets to the superclass, it is already + // marked active and would otherwise be skipped + + code.append(" if (!$force && " + FIELD_NAME_$ACTIVE_BINDINGS + ".contains(" + PARAMETER_NAME_$BINDING + ")) { "); + code.append(eol); + code.append(" return;"); + code.append(eol); + code.append("}").append(eol); + code.append(FIELD_NAME_$ACTIVE_BINDINGS + ".add(" + PARAMETER_NAME_$BINDING + ");"); + code.append(eol); + code.append("try {").append(eol); + code.append(" if (" + FIELD_NAME_$BINDINGS + ".containsKey(" + PARAMETER_NAME_$BINDING + ")) {"); + code.append(eol); + code.append(" getDataBinding(" + PARAMETER_NAME_$BINDING + ")." + METHOD_NAME_PROCESS_DATA_BINDING + "();"); + code.append(eol); + code.append(" }").append(eol); + code.append("} finally {").append(eol); + code.append(" " + FIELD_NAME_$ACTIVE_BINDINGS + ".remove(" + PARAMETER_NAME_$BINDING + ");"); + code.append(eol); + code.append("}").append(eol); + return JavaElementFactory.newMethod( + PUBLIC, + TYPE_VOID, + METHOD_NAME_PROCESS_DATA_BINDING, + code.toString(), + true, + newArgument(TYPE_STRING, PARAMETER_NAME_$BINDING), + newArgument(TYPE_BOOLEAN, "$force") + ); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/JAXXCompilerFinalizer.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/JAXXCompilerFinalizer.java new file mode 100644 index 0000000..30906e2 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/JAXXCompilerFinalizer.java @@ -0,0 +1,87 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.finalizers; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.java.JavaFile; + +/** + * Contract of any object to interact with a {@link JAXXCompiler} before the + * generation pass. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.0 + */ +public interface JAXXCompilerFinalizer { + + String TYPE_STRING = "String"; + + String TYPE_VOID = "void"; + + String TYPE_BOOLEAN = "boolean"; + + String TYPE_OBJECT = "Object"; + + /** + * Test if the finalizer must be apply on the given {@code compiler}. + * + * @param compiler the compiler + * @return {@code true} if the finalizer must be apply of compiler + */ + boolean accept(JAXXCompiler compiler); + + /** + * Finalize compiler for a given compiler on the finalizer pass before any + * generation. + * + * @param root the root object + * @param compiler the current compiler + * @param javaFile the java file to generate + * @param packageName the package name of the file to generate + * @param className the class name of the file to generate + * @throws Exception if any pb + */ + void finalizeCompiler(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) throws Exception; + + /** + * Prepare java file after any compiler finalizer pass, says the last + * action before generation. + * + * @param root the root object + * @param compiler the current compiler + * @param javaFile the java file to generate + * @param packageName the package name of the file to generate + * @param className the class name of the file to generate + * @throws Exception if any pb + */ + void prepareJavaFile(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) throws Exception; +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/SwingFinalizer.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/SwingFinalizer.java new file mode 100644 index 0000000..f32033e --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/SwingFinalizer.java @@ -0,0 +1,89 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.finalizers; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.java.JavaElementFactory; +import org.nuiton.jaxx.compiler.java.JavaFile; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.runtime.swing.Application; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.SwingUtilities; +import java.lang.reflect.Modifier; + +/** + * @author Tony Chemit - chemit@codelutin.com + * @plexus.component role-hint="swing" role="org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer" + */ +public class SwingFinalizer extends AbstractFinalizer { + + /** Logger. */ + protected static final Log log = LogFactory.getLog(DefaultFinalizer.class); + + @Override + public boolean accept(JAXXCompiler compiler) { + + ClassDescriptor descriptor = + ClassDescriptorHelper.getClassDescriptor(Application.class); + CompiledObject root = compiler.getRootObject(); + return descriptor.isAssignableFrom(root.getObjectClass()); + } + + @Override + public void finalizeCompiler(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) { + } + + @Override + public void prepareJavaFile(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) throws ClassNotFoundException { + + if (compiler.isMainDeclared()) { + + // main method was already defined, can not generate this method. + return; + } + + javaFile.addImport(SwingUtilities.class); + String code = "SwingUtilities.invokeLater(new Runnable() { " + + "public void run() { new " + className + + "().setVisible(true); } });"; + javaFile.addMethod(JavaElementFactory.newMethod( + Modifier.PUBLIC | Modifier.STATIC, + TYPE_VOID, + "main", + code, + false, + JavaElementFactory.newArgument("String[]", "arg"))); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/ValidatorFinalizer.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/ValidatorFinalizer.java new file mode 100644 index 0000000..4e4d8c9 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/finalizers/ValidatorFinalizer.java @@ -0,0 +1,278 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.finalizers; + +import com.google.common.base.Joiner; +import com.google.common.collect.Lists; +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompiledObject.ChildRef; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.java.JavaElement; +import org.nuiton.jaxx.compiler.java.JavaElementFactory; +import org.nuiton.jaxx.compiler.java.JavaField; +import org.nuiton.jaxx.compiler.java.JavaFile; +import org.nuiton.jaxx.compiler.tags.validator.BeanValidatorHandler; +import org.nuiton.jaxx.compiler.tags.validator.BeanValidatorHandler.CompiledBeanValidator; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.validator.JAXXValidator; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.validator.swing.SwingValidator; +import org.nuiton.jaxx.validator.swing.SwingValidatorUtil; +import org.nuiton.jaxx.validator.swing.meta.Validator; +import org.nuiton.jaxx.validator.swing.meta.ValidatorField; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * To finalize validators fields. + * + * @author Tony Chemit - chemit@codelutin.com + * @plexus.component role-hint="validators" role="org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer" + */ +public class ValidatorFinalizer extends AbstractFinalizer { + + /** Logger. */ + static Log log = LogFactory.getLog(ValidatorFinalizer.class); + + protected static final JavaField VALIDATOR_IDS_FIELD = + JavaElementFactory.newField( + Modifier.PROTECTED, + List.class.getName() + "<String>", + "validatorIds", + true, + "new %s<String>()", + ArrayList.class.getName() + ); + + @Override + public boolean accept(JAXXCompiler compiler) { + + //use this finalizer if compiler is validation aware + return BeanValidatorHandler.hasValidator(compiler); + } + + @Override + public void finalizeCompiler(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) { + + for (CompiledObject object : compiler.getObjects().values()) { + List<ChildRef> childs = object.getChilds(); + if (childs == null || childs.isEmpty()) { + continue; + } + for (ChildRef child : childs) { + String javaCode = child.getChildJavaCode(); + + // some validators are defined on this object + boolean found = + BeanValidatorHandler.isComponentUsedByValidator( + compiler, + child.getChild().getId() + ); + + if (found) { +// compiler.setNeedSwingUtil(true); + String type = + compiler.getImportedType(SwingUtil.class); + // box the child component in a JxLayer + child.setChildJavaCode( + type + + ".boxComponentWithJxLayer(" + javaCode + ")"); + } + } + } + String eol = JAXXCompiler.getLineSeparator(); + StringBuilder builder = new StringBuilder(); + // register validators + List<CompiledBeanValidator> validators = + BeanValidatorHandler.getValidators(compiler); +// javaFile.addImport(Validator.class); +// javaFile.addImport(ValidatorField.class); +// javaFile.addImport(SwingValidatorUtil.class); + String validatorUtilPrefix = + compiler.getImportedType(SwingValidatorUtil.class) + + "."; + + compiler.getJavaFile().addMethod(JavaElementFactory.newMethod( + Modifier.PUBLIC, + TYPE_VOID, + "registerValidatorFields", + validatorUtilPrefix + "detectValidatorFields(this);", + true) + ); + builder.append("// register "); + builder.append(validators.size()); + builder.append(" validator(s)"); + builder.append(eol); + + builder.append("validatorIds = "); + builder.append(validatorUtilPrefix).append("detectValidators(this);"); + builder.append(eol); + + builder.append(validatorUtilPrefix).append("installUI(this);"); + builder.append(eol); + compiler.appendLateInitializer(builder.toString()); + + for (CompiledBeanValidator validator : validators) { + + registerValidator(validator, compiler, javaFile); + } + } + + @Override + public void prepareJavaFile(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) throws ClassNotFoundException { + Class<?> validatorClass = SwingValidator.class; + + Class<?> validatorInterface = JAXXValidator.class; + + boolean parentIsValidator = + compiler.isSuperClassAware(validatorInterface); + + if (parentIsValidator) { + + // nothing to generate (use the parent directly) + return; + } + + // add JAXXValidator interface + javaFile.addInterface(JAXXCompiler.getCanonicalName(validatorInterface)); + + // implements JAXXValidator + addField(javaFile, VALIDATOR_IDS_FIELD); + + String type = compiler.getImportedType(validatorClass); + + String initializer = "return (" + type + + "<?>) (validatorIds.contains(validatorId) ? " + + "getObjectById(validatorId) : null);"; + + + javaFile.addMethod(JavaElementFactory.newMethod( + Modifier.PUBLIC, + type + "<?>", + "getValidator", + initializer, + true, + JavaElementFactory.newArgument(TYPE_STRING, "validatorId")) + ); + } + + public void registerValidator(CompiledBeanValidator validator, + JAXXCompiler compiler, + JavaFile javaFile) { + + JavaField validatorField = javaFile.getField(validator.getId()); + + String validatorId = TypeManager.getJavaCode(validator.getId()); + + String type = compiler.getImportedType(Validator.class); + String fieldType = compiler.getImportedType(ValidatorField.class); + + String validatorAnnotation = type + + "( validatorId = " + validatorId + ")"; + validatorField.addAnnotation(validatorAnnotation); +// Map<String, String> fields = validator.getFields(); + + for (String component : validator.getFieldEditors()) { + + Collection<String> propertyNames = validator.getFieldPropertyNames(component); + List<String> keyCodes = + Lists.newArrayListWithCapacity(propertyNames.size()); + for (String propertyName : propertyNames) { + if (!validator.checkBeanProperty(compiler, propertyName)) { + // property not find on bean + continue; + } + String keyCode = TypeManager.getJavaCode(propertyName); + keyCodes.add(keyCode); + } + + if (keyCodes.isEmpty()) { + // no property + continue; + } + String keyCode = Joiner.on(", ").join(keyCodes); + if (keyCodes.size() > 1) { + keyCode = "{ " + keyCode + " }"; + } + +// String keyCode = TypeManager.getJavaCode(propertyName); + String editorCode = TypeManager.getJavaCode(component); + JavaElement editor = javaFile.getField(component); + if (editor == null) { + if (log.isDebugEnabled()) { + String message = "Could not find editor [" + component + + "] for property(ies) [" + propertyNames + + "] for file " + javaFile.getName(); + log.debug(message); + } + + // find in the compiler the object + CompiledObject compiledObject = + compiler.getCompiledObject(component); + + if (compiledObject == null) { + + // this is an error, editor is unknown (this case should + // never happen) + + String errorMessage = + "Could not find editor [" + component + + "] for property(ies) [" + propertyNames + + "] for file " + javaFile.getName(); + + throw new CompilerException(errorMessage); + } + + // now must add a getter in the javaFile + String fqn = JAXXCompiler.getCanonicalName(compiledObject); + + editor = javaFile.addGetterMethod(component, + Modifier.PUBLIC, + fqn, + true, + true + ); + } + + String annotation = fieldType + + "( validatorId = " + validatorId + "," + + " propertyName = " + keyCode + "," + + " editorName = " + editorCode + "" + ")"; + editor.addAnnotation(annotation); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaArgument.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaArgument.java new file mode 100644 index 0000000..986e10b --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaArgument.java @@ -0,0 +1,83 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.java; + +/** + * Represents an argument to a <code>JavaMethod</code>. + * + * @see JavaMethod + */ +public class JavaArgument extends JavaElement { + + private String type; + + private boolean isFinal; + + /** + * Creates a new <code>JavaArgument</code> with the specified name and type. For example, the method <code>main()</code> + * might have a <code>JavaArgument</code> with a name of <code>"arg"</code> and a type of <code>"java.lang.String[]"</code>. + * + * @param type the argument's type, as it would appear in Java source code + * @param name the argument's name + */ + JavaArgument(String type, String name) { + this(type, name, false); + } + + /** + * Creates a new <code>JavaArgument</code> with the specified name, type, and finality. For example, the method <code>main()</code> + * might have a <code>JavaArgument</code> with a name of <code>"arg"</code> and a type of <code>"java.lang.String[]"</code>. The + * <code>isFinal</code> parameter allows the presence of the <code>final</code> keyword on the argument to be controlled. + * + * @param type the argument's type, as it would appear in Java source code + * @param name the argument's name + * @param isFinal <code>true</code> if the argument should be marked final + */ + JavaArgument(String type, String name, boolean isFinal) { + super(0, name); + this.type = type; + this.isFinal = isFinal; + } + + /** + * Returns the argument's type as it would be represented in Java source code. + * + * @return the argument's type + */ + public String getType() { + return type; + } + + /** + * Returns <code>true</code> if the <code>final</code> keyword should appear before the argument. + * + * @return <code>true</code> if the argument is final + */ + public boolean isFinal() { + return isFinal; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaConstructor.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaConstructor.java new file mode 100644 index 0000000..dff5afd --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaConstructor.java @@ -0,0 +1,95 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.java; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; + +/** + * To mirror a {@link Constructor}. + * + * In a constructor we need to keep all parameters types as fqn since when + * a jaxx object inheritates from anohter one, it is painfull (even impossible?) + * to find out from a simple name his fqn. + * + * So when using constructor, always keep fqn types. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.4 + */ +public class JavaConstructor extends JavaElement { + + /** arguments of the method (can be empty) */ + private JavaArgument[] arguments; + + /** exceptions thrown by the method (can be empty) */ + private String[] exceptions; + + /** body of the method (can be empty) */ + private String body; + + /** + * Constructs a new <code>JavaMethod</code> containing the specified body code. The <code>modifiers</code> parameter + * is a bit mask of the constants from {@link Modifier}, and the <code>returnType</code> and + * <code>exceptions</code> of the method should be represented as they would appear in Java source code (<code>null</code> + * for a constructor). The method body is initially empty. + * + * @param modifiers the modifier keywords that should appear as part of the method's declaration + * @param name the method's name + * @param arguments the method's arguments + * @param exceptions a list of exceptions the methods can throw, as they would be represented in Java source code + * @param bodyCode Java source code which should appear in the method body + */ + JavaConstructor(int modifiers, + String name, + JavaArgument[] arguments, + String[] exceptions, + String bodyCode) { + super(modifiers, name); + this.arguments = arguments; + this.exceptions = exceptions; + body = bodyCode == null ? "" : bodyCode; + } + + /** + * Returns a list of the method's arguments. + * + * @return the method's arguments + */ + public JavaArgument[] getArguments() { + return arguments; + } + + /** + * Returns a list of exceptions the method can throw. + * + * @return the method's exceptions + */ + public String[] getExceptions() { + return exceptions; + } + + public String getBody() { + return body; + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaElement.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaElement.java new file mode 100644 index 0000000..65b5c7d --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaElement.java @@ -0,0 +1,129 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.java; + +import org.apache.commons.collections4.CollectionUtils; + +import java.lang.reflect.Modifier; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Pattern; + +/** + * Base Java element + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.0 + */ +public abstract class JavaElement { + + // private String lineSeparator; + private String name; + + private int modifiers; + + /** + * List of annoations. + * + * @since 2.3 + */ + private Set<String> annotations; + + public JavaElement(int modifiers, String name) { + this.modifiers = modifiers; + this.name = name; + } + + public final int getModifiers() { + return modifiers; + } + + public final void setModifiers(int modifiers) { + this.modifiers = modifiers; + } + + public final String getName() { + return name; + } + + public final void setName(String name) { + this.name = name; + } + + public final String getModifiersText() { + if (modifiers == 0) { + return ""; + } else { + return Modifier.toString(modifiers) + ' '; + } + } + + public Set<String> getAnnotations() { + if (annotations == null) { + annotations = new HashSet<>(); + } + return annotations; + } + + public boolean hasAnnotations() { + return CollectionUtils.isNotEmpty(annotations); + } + + public void addAnnotation(String annotation) { + getAnnotations().add(annotation); + } + + public static final Comparator<JavaElement> JavaElementComparator = new Comparator<JavaElement>() { + + final Pattern NAME_PATTERN = Pattern.compile("(.+)([0-9]+)"); + + @Override + public int compare(JavaElement o1, JavaElement o2) { + + String n1 = o1.getName(); + String n2 = o2.getName(); + + //FIXME-tchemit-2012-07-02 (see https://forge.nuiton.org/issues/2154) +// Matcher matcher1 = NAME_PATTERN.matcher(n1); +// Matcher matcher2 = NAME_PATTERN.matcher(n2); +// if (matcher1.matches() && matcher2.matches()) { +// // les deux noms finissent par un nombre +// String p1 = matcher1.group(1); +// String p2 = matcher1.group(2); +// int i = p1.compareTo(p2); +// if (i != 0) { +// // on est sur des noms de prefix différents, donc pas de tri sur les suffixes +// return i; +// } +// // les deux noms doivent être triés sur les suffixes entiers +// int i1 = Integer.valueOf(matcher1.group(2)); +// int i2 = Integer.valueOf(matcher2.group(2)); +// return i1 - i2; +// } + + // les deux noms sont simplement comparé en alpha + return n1.compareTo(n2); + } + }; +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaElementFactory.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaElementFactory.java new file mode 100644 index 0000000..e9b30f6 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaElementFactory.java @@ -0,0 +1,179 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.java; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.StringUtil; + +/** + * Factory of any element in a {@link JavaFile}. + * + * Always pass by this factory to have common behaviour (imports,...) + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.4 + */ +public class JavaElementFactory { + + /** Logger. */ + static private final Log log = LogFactory.getLog(JavaElementFactory.class); + + public static JavaFile newFile(int modifiers, String className) { + return new JavaFile(modifiers, className); + } + + public static JavaArgument newArgument(String type, + String name) { + return newArgument(type, name, false); + } + + public static JavaArgument newArgument(String type, + String name, + boolean isFinal) { + return new JavaArgument(type, name, isFinal); + } + + public static JavaField newField(int modifiers, + String returnType, + String name, + boolean override) { + return newField(modifiers, returnType, name, override, null); + } + + public static JavaField newField(int modifiers, + String returnType, + String name, + boolean override, + String initializer, + String... initializerTypes) { + return new JavaField(modifiers, + returnType, + name, + override, + initializer, + initializerTypes + ); + } + + public static JavaConstructor newConstructor(int modifiers, + String name, + String body, + String[] exceptions, + JavaArgument... arguments) { + return new JavaConstructor(modifiers, + name, + arguments, + exceptions, + body + ); + } + + public static JavaConstructor newConstructor(int modifiers, + String name, + String body, + JavaArgument... arguments) { + return newConstructor(modifiers, + name, + body, + StringUtil.EMPTY_STRING_ARRAY, + arguments + ); + } + + public static JavaMethod newMethod(int modifiers, + String returnType, + String name, + String body, + boolean override, + String[] exceptions, + JavaArgument... arguments) { + if (log.isDebugEnabled()) { + log.debug(name + " returns : " + returnType); + } + return new JavaMethod(modifiers, + returnType, + name, + arguments, + exceptions, + body, + override + ); + } + + public static JavaMethod newMethod(int modifiers, + String returnType, + String name, + String body, + boolean override, + JavaArgument... arguments) { + return newMethod(modifiers, + returnType, + name, + body, + override, + StringUtil.EMPTY_STRING_ARRAY, + arguments + ); + } + + public static JavaField cloneField(JavaField field) { + return newField( + field.getModifiers(), + field.getType(), + field.getName(), + field.isOverride(), + field.getInitializer(), + field.getInitializerTypes()); + } + + public static JavaMethod cloneMethod(JavaMethod method) { + + String[] incomingExceptions = method.getExceptions(); + String[] exceptions = new String[incomingExceptions.length]; + System.arraycopy(incomingExceptions, 0, exceptions, 0, exceptions.length); + + JavaArgument[] oldArguments = method.getArguments(); + int nbArguments = oldArguments.length; + JavaArgument[] arguments = new JavaArgument[nbArguments]; + for (int i = 0; i < nbArguments; i++) { + JavaArgument argument = oldArguments[i]; + arguments[i] = cloneArgument(argument); + } + return newMethod( + method.getModifiers(), + method.getReturnType(), + method.getName(), + method.getBody(), + method.isOverride(), + exceptions, + arguments); + } + + public static JavaArgument cloneArgument(JavaArgument argument) { + return newArgument( + argument.getType(), + argument.getName(), + argument.isFinal() + ); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaField.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaField.java new file mode 100644 index 0000000..c8bc810 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaField.java @@ -0,0 +1,294 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.java; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; + +/** + * Represents a field in a Java source file being generated for output. <code>JavaFields</code> are created + * and added to a {@link JavaFile}, which can then output Java source code. + */ +public class JavaField extends JavaElement implements Comparable<JavaField> { + + /** type of field (fqn) */ + private String type; + + /** initializer of field (can be null) */ + private String initializer; + + /** + * Types to apply to the initializer to try use simple type names. + * + * @since 2.4 + */ + private String[] initializerTypes; + + + /** flag to known where a field overrides a super-field */ + private boolean override; + + /** + * Constructs a new <code>JavaField</code>. The <code>modifiers</code> parameter is a bit mask of the + * constants from {@link Modifier}, and the <code>type</code> of the field should be + * represented as it would appear in Java source code. + * + * @param modifiers the modifier keywords that should appear as part of the field's declaration + * @param type the type of the field as it would appear in Java source code + * @param name the field's name + * @param override flag to add @Override annotation on getter and setter + */ + JavaField(int modifiers, + String type, + String name, + boolean override) { + this(modifiers, type, name, override, null); + } + + /** + * Constructs a new <code>JavaField</code>. The <code>modifiers</code> parameter is a bit mask of the + * constants from <code>java.lang.reflect.Modifier</code>, and the <code>type</code> of the field should be + * represented as it would appear in Java source code. The <code>initializer</code> is the initial + * value of the field as it would appear in Java source code, or <code>null</code> to leave it at the + * default value. + * + * @param modifiers the modifier keywords that should appear as part of the field's declaration + * @param type the type of the field as it would appear in Java source code + * @param name the field's name + * @param override {@code true} if method should be marked as overriden + * @param initializer the initial value of the field, as it would appear in Java source code + * @param initializerTypes initializer types to use + */ + JavaField(int modifiers, + String type, + String name, + boolean override, + String initializer, + String... initializerTypes) { + super(modifiers, name); + this.type = type; + this.initializer = initializer; + this.initializerTypes = initializerTypes; + this.override = override; + } + + /** + * Returns the field's type, as it would be represented in Java source code. + * + * @return the field's type + */ + public String getType() { + return type; + } + + public boolean isOverride() { + return override; + } + + public String getInitializer() { + return initializer; + } + + public String[] getInitializerTypes() { + return initializerTypes; + } + + public boolean hasInitializerTypes() { + return initializerTypes != null && initializerTypes.length > 0; + } + + @Override + public int compareTo(JavaField o) { + return JavaElementComparator.compare(this, o); + } + + @Override + public String toString() { + return super.toString() + " " + getName() + ", type:" + + getType() + ", modifiers:" + Modifier.toString(getModifiers()); + } + + public void setType(String type) { + this.type = type; + } + + public void setInitializer(String initializer) { + this.initializer = initializer; + } + + public enum FieldOrder { + + staticsBean(Modifier.STATIC | Modifier.PUBLIC, + "Constants for all javaBean properties") { + @Override + public boolean accept(JavaField field) { + return field.getName().startsWith("PROPERTY_"); + } + }, + + staticsPublicBindings(Modifier.STATIC | Modifier.PUBLIC, + "Constants for all public bindings") { + @Override + public boolean accept(JavaField field) { + return field.getName().startsWith("BINDING_") && + Modifier.isPublic(field.getModifiers()); + } + }, + + staticsPrivateBindings(Modifier.STATIC | Modifier.PRIVATE, + "Constants for all none public bindings") { + @Override + public boolean accept(JavaField field) { + return field.getName().startsWith("BINDING_$") && + Modifier.isPrivate(field.getModifiers()); + } + }, + + staticsOthers(Modifier.STATIC, "Other static fields"), + + internalFields(Modifier.PROTECTED | Modifier.PRIVATE, + "Internal states") { + + private final List<String> fields = Arrays.asList( + "delegateContext", + "$previousValues", + "$bindingSources", + "$objectMap", + "$activeBindings", + "$bindings", + "$propertyChangeSupport"); + + @Override + public boolean accept(JavaField field) { + return fields.contains(field.getName()); + } + }, + publicFields(Modifier.PUBLIC, "Public components"), + protectedFields(Modifier.PROTECTED, "Protected components"), + privateFields(Modifier.PRIVATE, "Private components"), + otherFields(0, "Other fields") { + @Override + public boolean accept(JavaField field) { + return true; + } + }; + + private final String header; + + private int modifier; + + FieldOrder(int modifier, String header) { + this.header = JavaFileGenerator.getHeader(header); + this.modifier = modifier; + } + + public String getHeader() { + return header; + } + + public boolean accept(JavaField field) { + return true; + } + + public boolean accept(int mod) { + return (mod & modifier) != 0; + } + + public boolean accept(int mod, JavaField method) { + return accept(mod) && accept(method); + } + + public static FieldOrder valueOf(JavaField method, int scope) { + for (FieldOrder o : values()) { + if (o.accept(scope, method)) { + return o; + } + } + throw new IllegalArgumentException( + "could not find a " + FieldOrder.class + + " for method " + method); + } + } + + public static EnumMap<FieldOrder, List<JavaField>> getSortedFields(List<JavaField> fields) { + + EnumMap<FieldOrder, List<JavaField>> result = + new EnumMap<>(FieldOrder.class); + for (FieldOrder fieldOrder : FieldOrder.values()) { + result.put(fieldOrder, new ArrayList<JavaField>()); + } + + EnumSet<FieldOrder> allConstants = EnumSet.allOf(FieldOrder.class); + List<JavaField> allFields = new ArrayList<>(fields); + int[] scopes = new int[]{Modifier.STATIC, + Modifier.PUBLIC, + Modifier.PROTECTED, + Modifier.PRIVATE + }; + for (int scope : scopes) { + EnumSet<FieldOrder> constants = + getFieldOrderScope(allConstants, scope); + + Iterator<JavaField> itMethods = allFields.iterator(); + while (itMethods.hasNext()) { + JavaField method = itMethods.next(); + for (FieldOrder constant : constants) { + if (constant.accept(method.getModifiers(), method)) { + result.get(constant).add(method); + itMethods.remove(); + break; + } + } + } + constants.clear(); + } + + if (!allFields.isEmpty()) { + + // probably package locale fields + result.get(FieldOrder.otherFields).addAll(allFields); + } + + for (FieldOrder fieldOrder : FieldOrder.values()) { + // sort fields + Collections.sort(result.get(fieldOrder)); + } + return result; + } + + public static EnumSet<FieldOrder> getFieldOrderScope(EnumSet<FieldOrder> allConstants, int scope) { + EnumSet<FieldOrder> constants = EnumSet.noneOf(FieldOrder.class); + for (FieldOrder order : allConstants) { + if (order.accept(scope)) { + constants.add(order); + } + } + return constants; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaFile.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaFile.java new file mode 100644 index 0000000..6f23ba5 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaFile.java @@ -0,0 +1,518 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.java; + +import org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.eugene.java.extension.ImportsManager; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * A Java source file being generated for output. Once the class is completely initialized, use the + * {@link #toString} method to generate source code for it. + */ +public class JavaFile extends JavaElement { + + /** Logger. */ + static Log log = LogFactory.getLog(JavaFile.class); + + protected static final String GETTER_PATTERN = "return %1$s;"; + + protected static final String BOOLEAN_GETTER_PATTERN = "return %1$s !=null && %1$s;"; + + protected static final String SETTER_PATTERN = "%1$s oldValue = this.%2$s;\nthis.%2$s = %2$s;\nfirePropertyChange(%3$s, oldValue, %2$s);"; + + private Set<String> imports = new HashSet<>(); + + private List<JavaField> fields = new ArrayList<>(); + + private List<JavaMethod> methods = new ArrayList<>(); + + private List<JavaConstructor> constructors = new ArrayList<>(); + + private List<JavaFile> innerClasses = new ArrayList<>(); + + private String superClass; + + private List<String> interfaces; + + private StringBuilder rawBodyCode = new StringBuilder(); + + private boolean superclassIsJAXXObject; + + private boolean abstractClass; + + private String genericType; + + private String superGenericType; + + private final ImportsManager importManager; + + private String simpleName; + + JavaFile(int modifiers, String className) { + super(modifiers, className); + importManager = new ImportsManager(); + // add the fqn before all in the import manager to deal with alias classes + importManager.addImport(className); + } + + /** @deprecated since 2.4, never be used */ + @Deprecated + JavaFile() { + this(0, ""); + } + + /** + * @param modifiers + * @param className + * @param superClass + * @deprecated since 2.4, never be used + */ + @Deprecated + JavaFile(int modifiers, String className, String superClass) { + this(modifiers, className, superClass, null); + } + + /** + * @param modifiers + * @param className + * @param superClass + * @param interfaces + * @deprecated since 2.4, never be used + */ + @Deprecated + JavaFile(int modifiers, + String className, + String superClass, + List<String> interfaces) { + this(modifiers, className); + setSuperClass(superClass); + if (CollectionUtils.isNotEmpty(interfaces)) { + addInterface(interfaces.toArray(new String[interfaces.size()])); + } + } + + public String getPackageName() { + String name = getName(); + + String packageName; + if (name.contains(".")) { + packageName = name.substring(0, name.lastIndexOf(".")); + } else { + packageName = null; + } + return packageName; + } + + public ImportsManager getImportManager() { + return importManager; + } + + public String getImportedType(Class<?> type) { + return getImportManager().getType(type); + } + + public String getImportedType(String type) { + return getImportManager().getType(type); + } + + public String[] getImports() { + List<String> result = new ArrayList<>(imports); + Collections.sort(result); + return result.toArray(new String[result.size()]); + } + + public List<String> getImportsList() { + List<String> result = new ArrayList<>(imports); + Collections.sort(result); + return result; + } + + public String getSuperClass() { + return superClass; + } + + public List<String> getInterfaces() { + if (interfaces == null) { + interfaces = new ArrayList<>(); + } + return interfaces; + } + + public List<JavaMethod> getMethods() { + return methods; + } + + public List<JavaField> getFields() { + return fields; + } + + public boolean isAbstractClass() { + return abstractClass; + } + + public String getGenericType() { + return genericType; + } + + public List<JavaFile> getInnerClasses() { + return innerClasses; + } + + public StringBuilder getRawBodyCode() { + return rawBodyCode; + } + + public String getSuperGenericType() { + return superGenericType; + } + + public boolean isSuperclassIsJAXXObject() { + return superclassIsJAXXObject; + } + + public String getSimpleName() { + return simpleName; + } + + public JavaField getField(String componentId) { + for (JavaField field : fields) { + if (componentId.equals(field.getName())) { + return field; + } + } + return null; + } + + public void addImport(String importString) { + try { + importManager.addImport(importString); + } catch (Exception e) { + log.error("Could not determine simple name of import " + importString); + } + } + + public void addImport(Class<?> importString) { + addImport(importString.getName()); + } + + public void setImports(Collection<String> imports) { + this.imports = new HashSet<>(imports); + } + + public void setGenericType(String genericType) { + this.genericType = genericType; + } + + public void setSuperClass(String superClass) { + this.superClass = superClass; + } + + public void addInterface(String... canonicalNames) { + if (canonicalNames == null) { + return; + } + for (String canonicalName : canonicalNames) { + if (interfaces == null || !interfaces.contains(canonicalName)) { + getInterfaces().add(canonicalName); + } + } + } + + public void setInterfaces(List<String> interfaces) { + List<String> simpleInterfaces = new ArrayList<>(); + for (String anInterface : interfaces) { + try { + anInterface = importManager.getType(anInterface); + } catch (Exception e) { + log.error("Could not determine simple name of interface " + + anInterface); + } + simpleInterfaces.add(anInterface); + } + this.interfaces = simpleInterfaces; + } + + public void addConstructor(JavaConstructor constructor) { + constructors.add(constructor); + } + + public void addMethod(JavaMethod method) { + String returnType = method.getReturnType(); + try { + String type = importManager.getReturnType(returnType); + method.setReturnType(type); + } catch (Exception e) { + log.error("Could not determine simple name of return type " + + returnType + " for method " + method.getName()); + } + for (JavaArgument argument : method.getArguments()) { + String argumentType = argument.getType(); + try { + String type = importManager.getType(argumentType); + argument.setType(type); + } catch (Exception e) { + log.error("Could not determine simple name of argument type " + + argumentType + " of argument " + argument.getName() + + " for method " + method.getName()); + } + } + + String[] exceptions = method.getExceptions(); + for (int i = 0, length = exceptions.length; i < length; i++) { + String exception = exceptions[i]; + try { + String exceptionSimple = importManager.getType(exception); + exceptions[i] = exceptionSimple; + } catch (Exception e) { + log.error("Could not determine simple name of exception " + + exception + " for method " + method.getName()); + } + + } + + // this is a mreal method + methods.add(method); + } + + public void addField(JavaField field) { + + addField(field, false); + } + + public JavaMethod addGetterMethod(String id, + int modifiers, + String type, + boolean overridde, + boolean useOverride) { + + String capitalizedName = StringUtils.capitalize(id); + String methodName = "get" + capitalizedName; + String bodyCode; + if (useOverride) { + bodyCode = "super." + methodName + "()"; + } else { + bodyCode = id; + } + String content = String.format(GETTER_PATTERN, bodyCode); + JavaMethod method = JavaElementFactory.newMethod(modifiers, + type, + methodName, + content, + overridde + ); + addMethod(method); + return method; + } + + public JavaMethod addOverrideGetterMethod(String id, + int modifiers, + String type, + boolean useOverride) { + + String capitalizedName = StringUtils.capitalize(id); + String methodName = "get" + capitalizedName; + String bodyCode; + if (useOverride) { + bodyCode = "super." + methodName + "()"; + } else { + bodyCode = id; + } + bodyCode = "(" + type + ")" + bodyCode; + String content = String.format(GETTER_PATTERN, bodyCode); + JavaMethod method = JavaElementFactory.newMethod(modifiers, + type, + methodName, + content, + true + ); + addMethod(method); + return method; + } + + public void addField(JavaField field, boolean javaBean) { + addSimpleField(field); + String id = field.getName(); + String capitalizedName = StringUtils.capitalize(id); + + // add accessor method + int modifiers = Modifier.isProtected(field.getModifiers()) ? + Modifier.PUBLIC : Modifier.PROTECTED; + + addGetterMethod(id, + modifiers, + field.getType(), + field.isOverride(), + false + ); + + if (javaBean) { + // add full javabean support accessor + mutator + constant with + // name of property to make it easier to use + // compute the property constant + String constantId = TypeManager.convertVariableNameToConstantName( + "property" + capitalizedName); + addSimpleField(JavaElementFactory.newField( + Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL, + JAXXCompilerFinalizer.TYPE_STRING, + constantId, false, "\"" + id + "\"") + ); + + if (Boolean.class.getSimpleName().equals(field.getType())) { + String content = String.format(BOOLEAN_GETTER_PATTERN, id); + JavaMethod method = JavaElementFactory.newMethod( + Modifier.PUBLIC, + field.getType(), + "is" + capitalizedName, + content, + field.isOverride() + ); + addMethod(method); + } + String content = String.format(SETTER_PATTERN, + field.getType(), + id, + constantId + ); + JavaArgument arg = JavaElementFactory.newArgument(field.getType(), + id); + JavaMethod method = JavaElementFactory.newMethod( + Modifier.PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + "set" + capitalizedName, + content, + field.isOverride(), + arg); + addMethod(method); + } + } + + public void addSimpleField(JavaField field) { + if (log.isDebugEnabled()) { + log.debug("[" + getName() + "] Add field " + field.getName()); + } + String fieldType = field.getType(); + try { + String type = importManager.getType(fieldType); + field.setType(type); + } catch (Exception e) { + log.error("Could not determine simple name of field [" + + field.getName() + "] type " + fieldType); + } + if (field.hasInitializerTypes()) { + String code = simplifyCode(field.getInitializer(), + field.getInitializerTypes()); + if (log.isDebugEnabled()) { + log.debug("Use simplify text : " + code); + } + field.setInitializer(code); + } + fields.add(field); + } + + public void setSuperclassIsJAXXObject(boolean superclassIsJAXXObject) { + this.superclassIsJAXXObject = superclassIsJAXXObject; + } + + public void setAbstractClass(boolean abstractClass) { + this.abstractClass = abstractClass; + } + + public void setSuperGenericType(String superGenericType) { + this.superGenericType = superGenericType; + } + + public void addBodyCode(String bodyCode) { + rawBodyCode.append(bodyCode); + } + + /** + * Try to use a simple type fro the given {@code type} and apply it on the + * given {@code pattern}. + * + * Example : + * <pre> + * type = java.io.File, pattern = new %s(""); + * returns : new File("") or new java.io.File("") if importManager can + * not import java.io.File + * </pre> + * + * @param types the types to simplify + * @param pattern the pattern where to apply simple types + * @return the input pattern with most simplest types + * @since 2.4 + */ + public String simplifyCode(String pattern, + String... types) { + String[] simpleTypes = new String[types.length]; + for (int i = 0; i < types.length; i++) { + String type = types[i]; + String simpleType = importManager.getType(type); + simpleTypes[i] = simpleType; + } + return String.format(pattern, (Object[]) simpleTypes); + } + + public void clear() { + importManager.clearImports(); + if (interfaces != null) { + interfaces.clear(); + interfaces = null; + } + if (methods != null) { + methods.clear(); + methods = null; + } + if (constructors != null) { + constructors.clear(); + constructors = null; + } + if (fields != null) { + fields.clear(); + fields = null; + } + if (imports != null) { + imports.clear(); + } + } + + public List<JavaConstructor> getConstructors() { + return constructors; + } + + public void setSimpleName(String simpleName) { + this.simpleName = simpleName; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaFileGenerator.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaFileGenerator.java new file mode 100644 index 0000000..5da12fc --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaFileGenerator.java @@ -0,0 +1,452 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.java; + +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; +import java.util.Map.Entry; + +/** + * Java file generator. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.0 + */ +public class JavaFileGenerator { + + /** Logger. */ + static private final Log log = LogFactory.getLog(JavaFileGenerator.class); + + public static String getHeader(String header) { + String all = "/*-----------------------------------------------------------------------*/"; + int size = header.length(); + if (size % 2 == 0) { + size++; + header = header + " "; + } + int semi = (all.length() - size) / 2 - 5; + char[] prefix = new char[semi]; + Arrays.fill(prefix, '-'); + + String eol = JAXXCompiler.getLineSeparator(); + + return all + eol + "/*--" + new String(prefix) + + " " + header + " " + new String(prefix) + "--*/" + eol + all + + eol; + } + + /** End of line */ + protected final String eol; + + /** verbose flag when generates */ + protected final boolean verbose; + + /** current prefix indent size */ + protected int indentationLevel; + + public JavaFileGenerator(String eol, boolean verbose) { + this.eol = eol; + this.verbose = verbose && log.isDebugEnabled(); + } + + public static String addDebugLoggerInvocation(JAXXCompiler compiler, + String call) { + String eol = JAXXCompiler.getLineSeparator(); + StringBuilder builder = new StringBuilder(); + if (!compiler.getConfiguration().isAddLogger()) { + return ""; + } else { + builder.append("if (log.isDebugEnabled()) {"); + builder.append(eol); + builder.append(" log.debug(").append(call).append(");"); + builder.append(eol); + builder.append("}"); + builder.append(eol); + } + return builder.toString(); + } + + public String generateImport(String anImport) { + return "import " + anImport + ';' + eol; + } + + public void generateFile(JavaFile f, PrintWriter result) { + String name = f.getName(); + if (verbose) { + log.info(name); + } + indentationLevel = 0; + String packageName = f.getPackageName(); +// if (name.contains(".")) { + if (packageName != null) { +// packageName = name.substring(0, name.lastIndexOf(".")); + result.append("package "); + result.append(packageName); + result.append(";"); + result.append(eol).append(eol); + } + + generateImports(f, result); + + result.append(generateClass(f)); + } + + public void generateImports(JavaFile f, PrintWriter result) { + + List<String> imports = f.getImportsList(); + + boolean addImports = CollectionUtils.isNotEmpty(imports); + for (String anImport : imports) { + result.append(generateImport(anImport)); + } + + if (addImports) { + result.append(eol); + } + } + + public String generateClass(JavaFile f) { + if (verbose) { + log.info(f.getName()); + } + + StringBuilder result = new StringBuilder(); + String genericType = f.getGenericType(); + + result.append(f.getModifiersText()); + if (f.isAbstractClass()) { + result.append("abstract "); + } + result.append("class "); + result.append(f.getName().substring(f.getName().lastIndexOf(".") + 1)); + if (genericType != null) { + result.append('<').append(genericType).append('>'); + } + result.append(" extends "); + result.append(f.getSuperClass()); + if (f.getSuperGenericType() != null) { + result.append('<').append(f.getSuperGenericType()).append('>'); + } + List<String> interfaces = f.getInterfaces(); + + if (interfaces != null && !interfaces.isEmpty()) { + result.append(" implements ").append(interfaces.get(0)); + for (int i = 1; i < interfaces.size(); i++) { + result.append(", ").append(interfaces.get(i)); + } + } + result.append(" {").append(eol); + + // generate fields + + List<JavaField> fields = f.getFields(); + + if (!fields.isEmpty()) { + + EnumMap<JavaField.FieldOrder, List<JavaField>> map = + JavaField.getSortedFields(fields); + for (Entry<JavaField.FieldOrder, List<JavaField>> entry : + map.entrySet()) { + + List<JavaField> list = entry.getValue(); + + // sort fields + Collections.sort(list); + + if (!list.isEmpty()) { + + // add field group header + result.append(eol); + result.append( + addIndentation(entry.getKey().getHeader(), 4, eol)); + result.append(eol); + result.append(eol); + + // add all fields of group + for (JavaField method : list) { + String txt = generateField(method); + result.append(addIndentation(txt, 4, eol)).append(eol); + } + } + list.clear(); + } + map.clear(); + result.append(eol); + } + + // generate raw body + + StringBuilder rawBodyCode = f.getRawBodyCode(); + + if (rawBodyCode.length() > 0) { + result.append(addIndentation( + getHeader("Raw body code from script"), 4, eol)); + result.append(eol); + String s = rawBodyCode.toString(); + if (!s.startsWith(eol)) { + result.append(eol); + } + result.append(addIndentation(s, 4, eol)).append(eol).append(eol); + } + + // generate inner classes + + List<JavaFile> innerClasses = f.getInnerClasses(); + for (JavaFile innerClass : innerClasses) { + indentationLevel += 4; + try { + String txt = generateClass(innerClass); + result.append(addIndentation(txt, 4, eol)); + result.append(eol); + result.append(eol); + } finally { + indentationLevel -= 4; + } + } + + + // add constructors : + + result.append(addIndentation(JavaMethod.MethodOrder.constructors.getHeader(), 4, eol)); + result.append(eol); + result.append(eol); + + // add all constructors + for (JavaConstructor method : f.getConstructors()) { + String txt = generateConstructor(method); + result.append(addIndentation(txt, 4, eol)); + result.append(eol); + result.append(eol); + } + + // generate methods + EnumMap<JavaMethod.MethodOrder, List<JavaMethod>> map = + JavaMethod.getSortedMethods(f.getMethods()); + + for (Entry<JavaMethod.MethodOrder, List<JavaMethod>> entry : map.entrySet()) { + List<JavaMethod> list = entry.getValue(); + if (!list.isEmpty()) { + + // sort methods + Collections.sort(list); + + // add method group header + result.append(addIndentation(entry.getKey().getHeader(), 4, eol)); + result.append(eol); + result.append(eol); + + // add all methods of group + for (JavaMethod method : list) { + String txt = generateMethod(method); + result.append(addIndentation(txt, 4, eol)); + result.append(eol); + result.append(eol); + } + } + list.clear(); + } + map.clear(); + result.append("}"); + return result.toString(); + } + + public String generateField(JavaField f) { + if (verbose) { + if (log.isDebugEnabled()) { + log.debug(f.getName()); + } + } + StringBuilder result = new StringBuilder(); + generateAnnotations(f, result, eol); + result.append(f.getModifiersText()); + result.append(f.getType()).append(' ').append(f.getName()); + if (f.getInitializer() != null) { + result.append(" = ").append(f.getInitializer()); + } + result.append(';').append(eol); + return result.toString(); + } + + protected void generateAnnotations(JavaElement element, + StringBuilder result, + String separator) { + if (element.hasAnnotations()) { + for (String annotation : element.getAnnotations()) { + if (!annotation.startsWith("@")) { + result.append("@"); + } + result.append(annotation).append(separator); + } + } + } + + public String generateConstructor(JavaConstructor m) { + if (verbose) { + log.info(m.getName()); + } + + StringBuilder result = new StringBuilder(); + + generateAnnotations(m, result, eol); + result.append(m.getModifiersText()); + result.append(m.getName()); + result.append('('); + JavaArgument[] arguments = m.getArguments(); + + // adding arguments + + if (arguments != null && arguments.length > 0) { + result.append(generateArgument(arguments[0])); + for (int i = 1; i < arguments.length; i++) { + result.append(", ").append(generateArgument(arguments[i])); + } + } + result.append(")"); + + // adding exceptions + + String[] exceptions = m.getExceptions(); + if (exceptions != null && exceptions.length > 0) { + result.append(" throws ").append(exceptions[0]); + for (int i = 1; i < exceptions.length; i++) { + result.append(", ").append(exceptions[i]); + } + } + result.append(" {"); + result.append(eol); + + // adding body + + String body = m.getBody(); + + if (body != null) { + String formattedBodyCode = addIndentation(body.trim(), 4, eol); + if (formattedBodyCode.length() > 0) { + result.append(formattedBodyCode).append(eol); + } + } + result.append("}"); + return result.toString(); + + } + + public String generateMethod(JavaMethod m) { + if (verbose) { + log.info(m.getName()); + } + + StringBuilder result = new StringBuilder(); + if (m.isOverride()) { + m.addAnnotation(Override.class.getSimpleName()); + } + generateAnnotations(m, result, eol); + result.append(m.getModifiersText()); + if (m.getReturnType() != null) { + result.append(m.getReturnType()); + result.append(' '); + } + result.append(m.getName()); + result.append('('); + JavaArgument[] arguments = m.getArguments(); + + // adding arguments + + if (arguments != null && arguments.length > 0) { + result.append(generateArgument(arguments[0])); + for (int i = 1; i < arguments.length; i++) { + result.append(", ").append(generateArgument(arguments[i])); + } + } + result.append(")"); + + // adding exceptions + + String[] exceptions = m.getExceptions(); + if (exceptions != null && exceptions.length > 0) { + result.append(" throws ").append(exceptions[0]); + for (int i = 1; i < exceptions.length; i++) { + result.append(", ").append(exceptions[i]); + } + } + result.append(" {"); + result.append(eol); + + // adding body + + String body = m.getBody(); + + if (body != null) { + String formattedBodyCode = addIndentation(body.trim(), 4, eol); + if (formattedBodyCode.length() > 0) { + result.append(formattedBodyCode).append(eol); + } + } + result.append("}"); + return result.toString(); + + } + + public String generateArgument(JavaArgument argument) { + String result = argument.getType() + ' ' + argument.getName(); + return argument.isFinal() ? "final " + result : result; + } + + public String addIndentation(String source, + int indentation, + String lineSeparator) { + return indent(source, + indentationLevel + indentation, + false, + lineSeparator + ); + } + + public static String indent(String source, + int indentation, + boolean trim, + String lineSeparator) { + if (trim) { + source = source.trim(); + } + char[] spaces = new char[indentation]; + Arrays.fill(spaces, ' '); + StringBuilder result = new StringBuilder(); + String[] lines = source.split(lineSeparator + "|\n"); + for (int i = 0; i < lines.length; i++) { + if (i > 0) { + result.append(lineSeparator); + } + result.append(spaces); + result.append(trim ? lines[i].trim() : lines[i]); + } + return result.toString(); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaMethod.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaMethod.java new file mode 100644 index 0000000..cf2c7e6 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/JavaMethod.java @@ -0,0 +1,355 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.java; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; + +/** + * Represents a method in a Java source file being generated for output. <code>JavaMethods</code> are created + * and added to a {@link JavaFile}, which can then output Java source code. In addition to normal methods, a + * <code>JavaMethod</code> can represent a constructor -- constructors should be named after their containing + * classes and have a return type of <code>null</code>. + */ +public class JavaMethod extends JavaElement implements Comparable<JavaMethod> { + + /** return type of the method (null for constructors) */ + private String returnType; + + /** arguments of the method (can be empty) */ + private JavaArgument[] arguments; + + /** exceptions thrown by the method (can be empty) */ + private String[] exceptions; + + /** body of the method (can be empty) */ + private String body; + + /** flag to known if the method overrids a super-method */ + private boolean override; + + /** + * Constructs a new <code>JavaMethod</code> containing the specified body code. The <code>modifiers</code> parameter + * is a bit mask of the constants from {@link Modifier}, and the <code>returnType</code> and + * <code>exceptions</code> of the method should be represented as they would appear in Java source code (<code>null</code> + * for a constructor). The method body is initially empty. + * + * @param modifiers the modifier keywords that should appear as part of the method's declaration + * @param returnType the return type of the method as it would appear in Java source code + * @param name the method's name + * @param arguments the method's arguments + * @param exceptions a list of exceptions the methods can throw, as they would be represented in Java source code + * @param bodyCode Java source code which should appear in the method body + * @param override flag with {@code true} value when the method overrides (or implements) a super class method + */ + JavaMethod(int modifiers, + String returnType, + String name, + JavaArgument[] arguments, + String[] exceptions, + String bodyCode, + boolean override) { + super(modifiers, name); + this.returnType = returnType; + this.override = override; + this.arguments = arguments; + this.exceptions = exceptions; + body = bodyCode == null ? "" : bodyCode; + } + + /** + * Returns the method's return type, as it would be represented + * in Java source code. + * + * @return the method's return type + */ + public String getReturnType() { + return returnType; + } + + /** + * Returns a list of the method's arguments. + * + * @return the method's arguments + */ + public JavaArgument[] getArguments() { + return arguments; + } + + /** + * Returns a list of exceptions the method can throw. + * + * @return the method's exceptions + */ + public String[] getExceptions() { + return exceptions; + } + + public boolean isOverride() { + return override; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + @Override + public int compareTo(JavaMethod o) { + return JavaElementComparator.compare(this, o); + } + + public void setReturnType(String returnType) { + this.returnType = returnType; + } + + public enum MethodOrder { + + statics(Modifier.STATIC, "Statics methods"), + + constructors(Modifier.PUBLIC, "Constructors") { + @Override + public boolean accept(JavaMethod method) { + return method.returnType == null; + } + }, + JAXXObject(Modifier.PUBLIC, "JAXXObject implementation") { + + private final List<String> methods = Arrays.asList( + "applyDataBinding", + "firePropertyChange", + "getObjectById", + "get$objectMap", + "processDataBinding", + "removeDataBinding", + "registerDataBinding", + "getDataBindings", + "getDataBinding"); + + @Override + public boolean accept(JavaMethod method) { + return methods.contains(method.getName()); + } + }, + JAXXContext(Modifier.PUBLIC, "JAXXContext implementation") { + + private final List<String> methods = Arrays.asList( + "getContextValue", + "getDelegateContext", + "getParentContainer", + "removeContextValue", + "setContextValue"); + + @Override + public boolean accept(JavaMethod method) { + return methods.contains(method.getName()); + } + }, + JAXXValidation(Modifier.PUBLIC, "JAXXValidator implementation") { + + private final List<String> methods = + Arrays.asList("getValidator", "getValidatorIds", "registerValidatorFields"); + + @Override + public boolean accept(JavaMethod method) { + boolean contains = methods.contains(method.getName()); + if (contains && method.getName().equals("getValidator")) { + // only accept the method getValidator(String) and not anything else... + // since user can have a validator field which is a validator, but not part of the + // JAXXValidatator contract + return method.getArguments().length == 1; + } + return contains; + } + }, + events(Modifier.PUBLIC, "Event methods") { + @Override + public boolean accept(JavaMethod method) { + return method.getName().startsWith("do") && + method.getName().contains("__"); + } + }, + publicGetters(Modifier.PUBLIC, "Public acessor methods") { + @Override + public boolean accept(JavaMethod method) { + return method.getName().startsWith("get") || + method.getName().startsWith("is"); + } + }, + publicSetters(Modifier.PUBLIC, "Public mutator methods") { + @Override + public boolean accept(JavaMethod method) { + return method.getName().startsWith("set"); + } + }, + otherPublic(Modifier.PUBLIC, "Other methods") { + @Override + public boolean accept(int mod) { + return super.accept(mod) && !Modifier.isStatic(mod); + } + }, + protectedGetters(Modifier.PROTECTED, "Protected acessors methods") { + @Override + public boolean accept(JavaMethod method) { + return method.getName().startsWith("get") || + method.getName().startsWith("is"); + } + }, + createMethod(Modifier.PROTECTED | Modifier.PRIVATE, + "Components creation methods") { + @Override + public boolean accept(JavaMethod method) { + return method.getName().startsWith("create") || + method.getName().startsWith("add"); + } + }, + internalMethod(Modifier.PROTECTED, "Internal jaxx methods") { + private final List<String> methods = Arrays.asList( + "$initialize", + "$initialize_01_createComponents", + "$initialize_02_registerDataBindings", + "$initialize_03_finalizeCreateComponents", + "$initialize_04_applyDataBindings", + "$initialize_05_setProperties", + "$initialize_06_finalizeInitialize"); + + @Override + public boolean accept(JavaMethod method) { + return methods.contains(method.getName()); + } + }, + protecteds(Modifier.PROTECTED, "Other protected methods") { + }, + packageLocal(0, "Package methods") { + @Override + public boolean accept(int mod) { + return !Modifier.isStatic(mod) && + !Modifier.isPublic(mod) && + !Modifier.isProtected(mod); + } + }, + privates(Modifier.PRIVATE, "Other private methods"); + + private final String header; + + private int modifier; + + MethodOrder(int modifier, String header) { + this.header = JavaFileGenerator.getHeader(header); + this.modifier = modifier; + } + + public String getHeader() { + return header; + } + + public boolean accept(JavaMethod method) { + return true; + } + + public boolean accept(int mod) { + return (mod & modifier) != 0; + } + + public boolean accept(int mod, JavaMethod method) { + return accept(mod) && accept(method); + } + + public static MethodOrder valueOf(JavaMethod method, int scope) { + for (MethodOrder o : values()) { + if (o.accept(scope, method)) { + return o; + } + } + throw new IllegalArgumentException( + "could not find a " + MethodOrder.class + + " for method " + method); + } + } + + public static EnumMap<MethodOrder, List<JavaMethod>> getSortedMethods(List<JavaMethod> methods) { + + EnumMap<MethodOrder, List<JavaMethod>> result = + new EnumMap<>(MethodOrder.class); + for (MethodOrder methodOrder : MethodOrder.values()) { + result.put(methodOrder, new ArrayList<JavaMethod>()); + } + + EnumSet<MethodOrder> allConstants = EnumSet.allOf(MethodOrder.class); + List<JavaMethod> allMethods = new ArrayList<>(methods); + int[] scopes = new int[]{Modifier.STATIC, + Modifier.PUBLIC, + Modifier.PROTECTED, + Modifier.PRIVATE + }; + for (int scope : scopes) { + EnumSet<MethodOrder> constants = + getMethodOrderScope(allConstants, scope); + + Iterator<JavaMethod> itMethods = allMethods.iterator(); + while (itMethods.hasNext()) { + JavaMethod method = itMethods.next(); + for (MethodOrder constant : constants) { + if (constant.accept(method.getModifiers(), method)) { + result.get(constant).add(method); + itMethods.remove(); + break; + } + } + } + constants.clear(); + } + + if (!allMethods.isEmpty()) { + throw new IllegalArgumentException( + "could not find a " + MethodOrder.class + + " for method " + allMethods); + } + + for (MethodOrder methodOrder : MethodOrder.values()) { + // sort methods + Collections.sort(result.get(methodOrder)); + } + return result; + } + + public static EnumSet<MethodOrder> getMethodOrderScope(EnumSet<MethodOrder> allConstants, int scope) { + EnumSet<MethodOrder> constants = EnumSet.noneOf(MethodOrder.class); + for (MethodOrder order : allConstants) { + if (order.accept(scope)) { + constants.add(order); + } + } + return constants; + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JJTJavaParserState.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JJTJavaParserState.java new file mode 100644 index 0000000..d4ddc70 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JJTJavaParserState.java @@ -0,0 +1,148 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. .\JJTJavaParserState.java */ + + +package org.nuiton.jaxx.compiler.java.parser; + +class JJTJavaParserState { + private java.util.Stack<Node> nodes; + + private java.util.Stack<Integer> marks; + + private int sp; // number of nodes on stack + + private int mk; // current mark + + private boolean node_created; + + JJTJavaParserState() { + nodes = new java.util.Stack<>(); + marks = new java.util.Stack<>(); + sp = 0; + mk = 0; + } + + /* Determines whether the current node was actually closed and + pushed. This should only be called in the final user action of a + node scope. */ + boolean nodeCreated() { + return node_created; + } + + /* Call this to reinitialize the node stack. It is called +automatically by the parser's ReInit() method. */ + void reset() { + nodes.removeAllElements(); + marks.removeAllElements(); + sp = 0; + mk = 0; + } + + /* Returns the root node of the AST. It only makes sense to call +this after a successful parse. */ + Node rootNode() { + return nodes.elementAt(0); + } + + /* Pushes a node on to the stack. */ + void pushNode(Node n) { + nodes.push(n); + ++sp; + } + + /* Returns the node on the top of the stack, and remove it from the + stack. */ + Node popNode() { + if (--sp < mk) { + mk = marks.pop(); + } + return nodes.pop(); + } + + /* Returns the node currently on the top of the stack. */ + Node peekNode() { + return nodes.peek(); + } + + /* Returns the number of children on the stack in the current node + scope. */ + int nodeArity() { + return sp - mk; + } + + + void clearNodeScope(Node n) { + while (sp > mk) { + popNode(); + } + mk = marks.pop(); + } + + + void openNodeScope(Node n) { + marks.push(mk); + mk = sp; + n.jjtOpen(); + } + + + /* A definite node is constructed from a specified number of +children. That number of nodes are popped from the stack and +made the children of the definite node. Then the definite node +is pushed on to the stack. */ + void closeNodeScope(Node n, int num) { + mk = marks.pop(); + while (num-- > 0) { + Node c = popNode(); + c.jjtSetParent(n); + n.jjtAddChild(c, num); + } + n.jjtClose(); + pushNode(n); + node_created = true; + } + + + /* A conditional node is constructed if its condition is true. All +the nodes that have been pushed since the node was opened are +made children of the the conditional node, which is then pushed +on to the stack. If the condition is false the node is not +constructed and they are left on the stack. */ + void closeNodeScope(Node n, boolean condition) { + if (condition) { + int a = nodeArity(); + mk = marks.pop(); + while (a-- > 0) { + Node c = popNode(); + c.jjtSetParent(n); + n.jjtAddChild(c, a); + } + n.jjtClose(); + pushNode(n); + node_created = true; + } else { + mk = marks.pop(); + node_created = false; + } + } +} diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Java1.5.jj b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/Java1.5.jj similarity index 100% rename from jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Java1.5.jj rename to jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/Java1.5.jj diff --git a/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Java1.5.jjt b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/Java1.5.jjt similarity index 100% rename from jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Java1.5.jjt rename to jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/Java1.5.jjt diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaCharStream.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaCharStream.java new file mode 100644 index 0000000..2a20b54 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaCharStream.java @@ -0,0 +1,560 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. JavaCharStream.java Version 4.0 */ + +package org.nuiton.jaxx.compiler.java.parser; + +/** + * An implementation of interface CharStream, where the stream is assumed to + * contain only ASCII characters (with java-like unicode escape processing). + */ + +public class JavaCharStream { + public static final boolean staticFlag = false; + + static int hexval(char c) throws java.io.IOException { + switch (c) { + case '0': + return 0; + case '1': + return 1; + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + + case 'a': + case 'A': + return 10; + case 'b': + case 'B': + return 11; + case 'c': + case 'C': + return 12; + case 'd': + case 'D': + return 13; + case 'e': + case 'E': + return 14; + case 'f': + case 'F': + return 15; + } + + throw new java.io.IOException(); // Should never come here + } + + public int bufpos = -1; + + int bufsize; + + int available; + + int tokenBegin; + + protected int bufline[]; + + protected int bufcolumn[]; + + protected int column = 0; + + protected int line = 1; + + protected boolean prevCharIsCR = false; + + protected boolean prevCharIsLF = false; + + protected java.io.Reader inputStream; + + protected char[] nextCharBuf; + + protected char[] buffer; + + protected int maxNextCharInd = 0; + + protected int nextCharInd = -1; + + protected int inBuf = 0; + + protected int tabSize = 8; + + protected void setTabSize(int i) { + tabSize = i; + } + + protected int getTabSize(int i) { + return tabSize; + } + + protected void ExpandBuff(boolean wrapAround) { + char[] newbuffer = new char[bufsize + 2048]; + int newbufline[] = new int[bufsize + 2048]; + int newbufcolumn[] = new int[bufsize + 2048]; + + try { + if (wrapAround) { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + System.arraycopy(buffer, 0, newbuffer, + bufsize - tokenBegin, bufpos); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); + bufcolumn = newbufcolumn; + + bufpos += (bufsize - tokenBegin); + } else { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + bufcolumn = newbufcolumn; + + bufpos -= tokenBegin; + } + } catch (Throwable t) { + throw new Error(t.getMessage()); + } + + available = (bufsize += 2048); + tokenBegin = 0; + } + + protected void FillBuff() throws java.io.IOException { + int i; + if (maxNextCharInd == 4096) + maxNextCharInd = nextCharInd = 0; + + try { + if ((i = inputStream.read(nextCharBuf, maxNextCharInd, + 4096 - maxNextCharInd)) == -1) { + inputStream.close(); + throw new java.io.IOException(); + } else { + maxNextCharInd += i; + } + } catch (java.io.IOException e) { + if (bufpos != 0) { + --bufpos; + backup(0); + } else { + bufline[bufpos] = line; + bufcolumn[bufpos] = column; + } + throw e; + } + } + + protected char ReadByte() throws java.io.IOException { + if (++nextCharInd >= maxNextCharInd) + FillBuff(); + + return nextCharBuf[nextCharInd]; + } + + public char BeginToken() throws java.io.IOException { + if (inBuf > 0) { + --inBuf; + + if (++bufpos == bufsize) { + bufpos = 0; + } + + tokenBegin = bufpos; + return buffer[bufpos]; + } + + tokenBegin = 0; + bufpos = -1; + + return readChar(); + } + + protected void AdjustBuffSize() { + if (available == bufsize) { + if (tokenBegin > 2048) { + bufpos = 0; + available = tokenBegin; + } else + ExpandBuff(false); + } else if (available > tokenBegin) + available = bufsize; + else if ((tokenBegin - available) < 2048) + ExpandBuff(true); + else + available = tokenBegin; + } + + protected void UpdateLineColumn(char c) { + column++; + + if (prevCharIsLF) { + prevCharIsLF = false; + line += (column = 1); + } else if (prevCharIsCR) { + prevCharIsCR = false; + if (c == '\n') { + prevCharIsLF = true; + } else + line += (column = 1); + } + + switch (c) { + case '\r': + prevCharIsCR = true; + break; + case '\n': + prevCharIsLF = true; + break; + case '\t': + column--; + column += (tabSize - (column % tabSize)); + break; + default: + break; + } + + bufline[bufpos] = line; + bufcolumn[bufpos] = column; + } + + public char readChar() throws java.io.IOException { + if (inBuf > 0) { + --inBuf; + + if (++bufpos == bufsize) + bufpos = 0; + + return buffer[bufpos]; + } + + char c; + + if (++bufpos == available) + AdjustBuffSize(); + + if ((buffer[bufpos] = c = ReadByte()) == '\\') { + UpdateLineColumn(c); + + int backSlashCnt = 1; + + for (; ; ) // Read all the backslashes + { + if (++bufpos == available) + AdjustBuffSize(); + + try { + if ((buffer[bufpos] = c = ReadByte()) != '\\') { + UpdateLineColumn(c); + // found a non-backslash char. + if ((c == 'u') && ((backSlashCnt & 1) == 1)) { + if (--bufpos < 0) + bufpos = bufsize - 1; + + break; + } + + backup(backSlashCnt); + return '\\'; + } + } catch (java.io.IOException e) { + if (backSlashCnt > 1) + backup(backSlashCnt); + + return '\\'; + } + + UpdateLineColumn(c); + backSlashCnt++; + } + + // Here, we have seen an odd number of backslash's followed by a 'u' + try { + while ((c = ReadByte()) == 'u') + ++column; + + buffer[bufpos] = c = (char) (hexval(c) << 12 | + hexval(ReadByte()) << 8 | + hexval(ReadByte()) << 4 | + hexval(ReadByte())); + + column += 4; + } catch (java.io.IOException e) { + throw new Error("Invalid escape character at line " + line + + " column " + column + "."); + } + + if (backSlashCnt == 1) + return c; + else { + backup(backSlashCnt - 1); + return '\\'; + } + } else { + UpdateLineColumn(c); + return (c); + } + } + + /** + * @return column index + * @see #getEndColumn + * @deprecated + */ + + public int getColumn() { + return bufcolumn[bufpos]; + } + + /** + * @return line type ??? + * @see #getEndLine + * @deprecated + */ + + public int getLine() { + return bufline[bufpos]; + } + + public int getEndColumn() { + return bufcolumn[bufpos]; + } + + public int getEndLine() { + return bufline[bufpos]; + } + + public int getBeginColumn() { + return bufcolumn[tokenBegin]; + } + + public int getBeginLine() { + return bufline[tokenBegin]; + } + + public void backup(int amount) { + + inBuf += amount; + if ((bufpos -= amount) < 0) + bufpos += bufsize; + } + + public JavaCharStream(java.io.Reader dstream, + int startline, int startcolumn, int buffersize) { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + nextCharBuf = new char[4096]; + } + + public JavaCharStream(java.io.Reader dstream, + int startline, int startcolumn) { + this(dstream, startline, startcolumn, 4096); + } + + public JavaCharStream(java.io.Reader dstream) { + this(dstream, 1, 1, 4096); + } + + public void ReInit(java.io.Reader dstream, + int startline, int startcolumn, int buffersize) { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + if (buffer == null || buffersize != buffer.length) { + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + nextCharBuf = new char[4096]; + } + prevCharIsLF = prevCharIsCR = false; + tokenBegin = inBuf = maxNextCharInd = 0; + nextCharInd = bufpos = -1; + } + + public void ReInit(java.io.Reader dstream, + int startline, int startcolumn) { + ReInit(dstream, startline, startcolumn, 4096); + } + + public void ReInit(java.io.Reader dstream) { + ReInit(dstream, 1, 1, 4096); + } + + public JavaCharStream(java.io.InputStream dstream, String encoding, int startline, + int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { + this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + public JavaCharStream(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) { + this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096); + } + + public JavaCharStream(java.io.InputStream dstream, String encoding, int startline, + int startcolumn) throws java.io.UnsupportedEncodingException { + this(dstream, encoding, startline, startcolumn, 4096); + } + + public JavaCharStream(java.io.InputStream dstream, int startline, + int startcolumn) { + this(dstream, startline, startcolumn, 4096); + } + + public JavaCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { + this(dstream, encoding, 1, 1, 4096); + } + + public JavaCharStream(java.io.InputStream dstream) { + this(dstream, 1, 1, 4096); + } + + public void ReInit(java.io.InputStream dstream, String encoding, int startline, + int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { + ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) { + ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); + } + + public void ReInit(java.io.InputStream dstream, String encoding, int startline, + int startcolumn) throws java.io.UnsupportedEncodingException { + ReInit(dstream, encoding, startline, startcolumn, 4096); + } + + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn) { + ReInit(dstream, startline, startcolumn, 4096); + } + + public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { + ReInit(dstream, encoding, 1, 1, 4096); + } + + public void ReInit(java.io.InputStream dstream) { + ReInit(dstream, 1, 1, 4096); + } + + public String GetImage() { + if (bufpos >= tokenBegin) + return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); + else + return new String(buffer, tokenBegin, bufsize - tokenBegin) + + new String(buffer, 0, bufpos + 1); + } + + public char[] GetSuffix(int len) { + char[] ret = new char[len]; + + if ((bufpos + 1) >= len) + System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); + else { + System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, + len - bufpos - 1); + System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); + } + + return ret; + } + + public void Done() { + nextCharBuf = null; + buffer = null; + bufline = null; + bufcolumn = null; + } + + /** + * Method to adjust line and column numbers for the start of a token. + * + * @param newLine line number ? + * @param newCol column number ? + */ + public void adjustBeginLineColumn(int newLine, int newCol) { + int start = tokenBegin; + int len; + + if (bufpos >= tokenBegin) { + len = bufpos - tokenBegin + inBuf + 1; + } else { + len = bufsize - tokenBegin + bufpos + 1 + inBuf; + } + + int i = 0, j = 0, k; + int nextColDiff, columnDiff = 0; + + while (i < len && + bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) { + bufline[j] = newLine; + nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; + bufcolumn[j] = newCol + columnDiff; + columnDiff = nextColDiff; + i++; + } + + if (i < len) { + bufline[j] = newLine++; + bufcolumn[j] = newCol + columnDiff; + + while (i++ < len) { + if (bufline[j = start % bufsize] != bufline[++start % bufsize]) + bufline[j] = newLine++; + else + bufline[j] = newLine; + } + } + + line = bufline[j]; + column = bufcolumn[j]; + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaParser.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaParser.java new file mode 100644 index 0000000..2507f6a --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaParser.java @@ -0,0 +1,10117 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree&JavaCC: Do not edit this line. JavaParser.java */ + +package org.nuiton.jaxx.compiler.java.parser; + +import java.io.File; +import java.io.FileInputStream; + +/** + * Grammar to parse Java version 1.5 + * + * @author Sreenivasa Viswanadha - Simplified and enhanced for 1.5 + */ +public class JavaParser/*@bgen(jjtree)*/ implements JavaParserTreeConstants, JavaParserConstants {/*@bgen(jjtree)*/ + + protected JJTJavaParserState jjtree = new JJTJavaParserState(); + + /** Class to hold modifiers. */ + static public final class ModifierSet { + /* Definitions of the bits in the modifiers field. */ + public static final int PUBLIC = 0x0001; + + public static final int PROTECTED = 0x0002; + + public static final int PRIVATE = 0x0004; + + public static final int ABSTRACT = 0x0008; + + public static final int STATIC = 0x0010; + + public static final int FINAL = 0x0020; + + public static final int SYNCHRONIZED = 0x0040; + + public static final int NATIVE = 0x0080; + + public static final int TRANSIENT = 0x0100; + + public static final int VOLATILE = 0x0200; + + public static final int STRICTFP = 0x1000; + + /** + * A set of accessors that indicate whether the specified modifier + * is in the set. + */ + + public boolean isPublic(int modifiers) { + return (modifiers & PUBLIC) != 0; + } + + public boolean isProtected(int modifiers) { + return (modifiers & PROTECTED) != 0; + } + + public boolean isPrivate(int modifiers) { + return (modifiers & PRIVATE) != 0; + } + + public boolean isStatic(int modifiers) { + return (modifiers & STATIC) != 0; + } + + public boolean isAbstract(int modifiers) { + return (modifiers & ABSTRACT) != 0; + } + + public boolean isFinal(int modifiers) { + return (modifiers & FINAL) != 0; + } + + public boolean isNative(int modifiers) { + return (modifiers & NATIVE) != 0; + } + + public boolean isStrictfp(int modifiers) { + return (modifiers & STRICTFP) != 0; + } + + public boolean isSynchronized(int modifiers) { + return (modifiers & SYNCHRONIZED) != 0; + } + + public boolean isTransient(int modifiers) { + return (modifiers & TRANSIENT) != 0; + } + + public boolean isVolatile(int modifiers) { + return (modifiers & VOLATILE) != 0; + } + + /** Removes the given modifier. */ + static int removeModifier(int modifiers, int mod) { + return modifiers & ~mod; + } + } + + public JavaParser(String fileName) { + this(fileName, false); + } + + public JavaParser(String fileName, boolean parseMethodBody) { + this(System.in, parseMethodBody); + try { + ReInit(new FileInputStream(new File(fileName))); + } catch (Exception e) { + e.printStackTrace(); + } + } + + void jjtreeOpenNodeScope(Node n) { + ((SimpleNode) n).firstToken = getToken(1); + } + + void jjtreeCloseNodeScope(Node n) { + ((SimpleNode) n).lastToken = getToken(0); + } + + public SimpleNode popNode() { + if (jjtree.nodeArity() > 0) // number of child nodes + return (SimpleNode) jjtree.popNode(); + else + return null; + } + + public static void main(String args[]) { + JavaParser parser; + if (args.length == 0) { + System.out.println("Java Parser Version 1.1: Reading from standard input . . ."); + parser = new JavaParser(System.in, true); + } else if (args.length == 1) { + System.out.println("Java Parser Version 1.1: Reading from file " + args[0] + " . . ."); + try { + parser = new JavaParser(new java.io.FileInputStream(args[0]), true); + } catch (java.io.FileNotFoundException e) { + System.out.println("Java Parser Version 1.1: File " + args[0] + " not found."); + return; + } + } else { + System.out.println("Java Parser Version 1.1: Usage is one of:"); + System.out.println(" java JavaParser < inputfile"); + System.out.println("OR"); + System.out.println(" java JavaParser inputfile"); + return; + } + try { + parser.CompilationUnit(); + System.out.println("Java Parser Version 1.1: Java program parsed successfully."); + } catch (ParseException e) { + System.out.println(e.getMessage()); + System.out.println("Java Parser Version 1.1: Encountered errors during parse."); + } + } + + final public boolean Line() throws ParseException { + /*@bgen(jjtree) Line */ + SimpleNode jjtn000 = new SimpleNode(JJTLINE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + int modifiers; + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 0: + jj_consume_token(0); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return true; + } + break; + default: + if (jj_2_1(2147483647)) { + BlockStatement(); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return false; + } + } else if (jj_2_2(2147483647)) { + ClassOrInterfaceBodyDeclaration(false); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return false; + } + } else if (jj_2_3(2147483647)) { + ClassOrInterfaceBodyDeclaration(false); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return false; + } + } else if (jj_2_4(2147483647)) { + Expression(); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return false; + } + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IMPORT: + ImportDeclaration(); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return false; + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + throw new Error("Missing return statement in function"); + } + + /** + * ************************************** + * THE JAVA LANGUAGE GRAMMAR STARTS HERE * + * *************************************** + */ + +/* + * Program structuring syntax follows. + */ + final public void CompilationUnit() throws ParseException { + /*@bgen(jjtree) CompilationUnit */ + SimpleNode jjtn000 = new SimpleNode(JJTCOMPILATIONUNIT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_5(2147483647)) { + PackageDeclaration(); + } else { + ; + } + label_1: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IMPORT: + ; + break; + default: + break label_1; + } + ImportDeclaration(); + } + label_2: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case CLASS: + case ENUM: + case FINAL: + case INTERFACE: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOLATILE: + case SEMICOLON: + case AT: + ; + break; + default: + break label_2; + } + TypeDeclaration(); + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 123: + jj_consume_token(123); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case STUFF_TO_IGNORE: + jj_consume_token(STUFF_TO_IGNORE); + break; + default: + ; + } + jj_consume_token(0); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PackageDeclaration() throws ParseException { + /*@bgen(jjtree) PackageDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTPACKAGEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Modifiers(); + jj_consume_token(PACKAGE); + Name(); + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ImportDeclaration() throws ParseException { + /*@bgen(jjtree) ImportDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTIMPORTDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IMPORT); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case STATIC: + jj_consume_token(STATIC); + break; + default: + ; + } + Name(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case DOT: + jj_consume_token(DOT); + jj_consume_token(STAR); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* + * Modifiers. We match all modifiers in a single rule to reduce the chances of + * syntax errors for simple modifier mistakes. It will also enable us to give + * better error messages. + */ + final public int Modifiers() throws ParseException { + /*@bgen(jjtree) Modifiers */ + SimpleNode jjtn000 = new SimpleNode(JJTMODIFIERS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + int modifiers = 0; + try { + label_3: + while (true) { + if (jj_2_6(2)) { + ; + } else { + break label_3; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PUBLIC: + jj_consume_token(PUBLIC); + modifiers |= ModifierSet.PUBLIC; + break; + case STATIC: + jj_consume_token(STATIC); + modifiers |= ModifierSet.STATIC; + break; + case PROTECTED: + jj_consume_token(PROTECTED); + modifiers |= ModifierSet.PROTECTED; + break; + case PRIVATE: + jj_consume_token(PRIVATE); + modifiers |= ModifierSet.PRIVATE; + break; + case FINAL: + jj_consume_token(FINAL); + modifiers |= ModifierSet.FINAL; + break; + case ABSTRACT: + jj_consume_token(ABSTRACT); + modifiers |= ModifierSet.ABSTRACT; + break; + case SYNCHRONIZED: + jj_consume_token(SYNCHRONIZED); + modifiers |= ModifierSet.SYNCHRONIZED; + break; + case NATIVE: + jj_consume_token(NATIVE); + modifiers |= ModifierSet.NATIVE; + break; + case TRANSIENT: + jj_consume_token(TRANSIENT); + modifiers |= ModifierSet.TRANSIENT; + break; + case VOLATILE: + jj_consume_token(VOLATILE); + modifiers |= ModifierSet.VOLATILE; + break; + case STRICTFP: + jj_consume_token(STRICTFP); + modifiers |= ModifierSet.STRICTFP; + break; + case AT: + Annotation(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return modifiers; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + throw new Error("Missing return statement in function"); + } + + /* + * Declaration syntax follows. + */ + final public void TypeDeclaration() throws ParseException { + /*@bgen(jjtree) TypeDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + int modifiers; + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case SEMICOLON: + jj_consume_token(SEMICOLON); + break; + case ABSTRACT: + case CLASS: + case ENUM: + case FINAL: + case INTERFACE: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOLATILE: + case AT: + modifiers = Modifiers(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case CLASS: + case INTERFACE: + ClassOrInterfaceDeclaration(modifiers); + break; + case ENUM: + EnumDeclaration(modifiers); + break; + case AT: + AnnotationTypeDeclaration(modifiers); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ClassOrInterfaceDeclaration(int modifiers) throws ParseException { + /*@bgen(jjtree) ClassOrInterfaceDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + boolean isInterface = false; + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case CLASS: + jj_consume_token(CLASS); + break; + case INTERFACE: + jj_consume_token(INTERFACE); + isInterface = true; + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + jj_consume_token(IDENTIFIER); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LT: + TypeParameters(); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case EXTENDS: + ExtendsList(isInterface); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IMPLEMENTS: + ImplementsList(isInterface); + break; + default: + ; + } + ClassOrInterfaceBody(isInterface); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ExtendsList(boolean isInterface) throws ParseException { + /*@bgen(jjtree) ExtendsList */ + SimpleNode jjtn000 = new SimpleNode(JJTEXTENDSLIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + boolean extendsMoreThanOne = false; + try { + jj_consume_token(EXTENDS); + ClassOrInterfaceType(); + label_4: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_4; + } + jj_consume_token(COMMA); + ClassOrInterfaceType(); + extendsMoreThanOne = true; + } + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + if (extendsMoreThanOne && !isInterface) { + if (true) + throw new ParseException("A class cannot extend more than one other class"); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ImplementsList(boolean isInterface) throws ParseException { + /*@bgen(jjtree) ImplementsList */ + SimpleNode jjtn000 = new SimpleNode(JJTIMPLEMENTSLIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IMPLEMENTS); + ClassOrInterfaceType(); + label_5: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_5; + } + jj_consume_token(COMMA); + ClassOrInterfaceType(); + } + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + if (isInterface) { + if (true) + throw new ParseException("An interface cannot implement other interfaces"); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void EnumDeclaration(int modifiers) throws ParseException { + /*@bgen(jjtree) EnumDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTENUMDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(ENUM); + jj_consume_token(IDENTIFIER); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IMPLEMENTS: + ImplementsList(false); + break; + default: + ; + } + EnumBody(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void EnumBody() throws ParseException { + /*@bgen(jjtree) EnumBody */ + SimpleNode jjtn000 = new SimpleNode(JJTENUMBODY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LBRACE); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case FINAL: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOLATILE: + case IDENTIFIER: + case AT: + EnumConstant(); + label_6: + while (true) { + if (jj_2_7(2)) { + ; + } else { + break label_6; + } + jj_consume_token(COMMA); + EnumConstant(); + } + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + jj_consume_token(COMMA); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case SEMICOLON: + jj_consume_token(SEMICOLON); + label_7: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case CLASS: + case DOUBLE: + case ENUM: + case FINAL: + case FLOAT: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOID: + case VOLATILE: + case IDENTIFIER: + case LBRACE: + case SEMICOLON: + case AT: + case LT: + ; + break; + default: + break label_7; + } + ClassOrInterfaceBodyDeclaration(false); + } + break; + default: + ; + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void EnumConstant() throws ParseException { + /*@bgen(jjtree) EnumConstant */ + SimpleNode jjtn000 = new SimpleNode(JJTENUMCONSTANT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Modifiers(); + jj_consume_token(IDENTIFIER); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LPAREN: + Arguments(); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACE: + ClassOrInterfaceBody(false); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void TypeParameters() throws ParseException { + /*@bgen(jjtree) TypeParameters */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEPARAMETERS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LT); + TypeParameter(); + label_8: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_8; + } + jj_consume_token(COMMA); + TypeParameter(); + } + jj_consume_token(GT); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void TypeParameter() throws ParseException { + /*@bgen(jjtree) TypeParameter */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEPARAMETER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case EXTENDS: + TypeBound(); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void TypeBound() throws ParseException { + /*@bgen(jjtree) TypeBound */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEBOUND); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(EXTENDS); + ClassOrInterfaceType(); + label_9: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BIT_AND: + ; + break; + default: + break label_9; + } + jj_consume_token(BIT_AND); + ClassOrInterfaceType(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ClassOrInterfaceBody(boolean isInterface) throws ParseException { + /*@bgen(jjtree) ClassOrInterfaceBody */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACEBODY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LBRACE); + label_10: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case CLASS: + case DOUBLE: + case ENUM: + case FINAL: + case FLOAT: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOID: + case VOLATILE: + case IDENTIFIER: + case LBRACE: + case SEMICOLON: + case AT: + case LT: + ; + break; + default: + break label_10; + } + ClassOrInterfaceBodyDeclaration(isInterface); + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ClassOrInterfaceBodyDeclaration(boolean isInterface) throws ParseException { + /*@bgen(jjtree) ClassOrInterfaceBodyDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACEBODYDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + boolean isNestedInterface = false; + int modifiers; + try { + if (jj_2_10(2)) { + Initializer(); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + if (isInterface) { + if (true) + throw new ParseException("An interface cannot have initializers"); + } + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case CLASS: + case DOUBLE: + case ENUM: + case FINAL: + case FLOAT: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOID: + case VOLATILE: + case IDENTIFIER: + case AT: + case LT: + modifiers = Modifiers(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case CLASS: + case INTERFACE: + ClassOrInterfaceDeclaration(modifiers); + break; + case ENUM: + EnumDeclaration(modifiers); + break; + default: + if (jj_2_8(2147483647)) { + ConstructorDeclaration(); + } else if (jj_2_9(2147483647)) { + FieldDeclaration(modifiers); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + case VOID: + case IDENTIFIER: + case LT: + MethodDeclaration(modifiers); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } + break; + case SEMICOLON: + jj_consume_token(SEMICOLON); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void FieldDeclaration(int modifiers) throws ParseException { + /*@bgen(jjtree) FieldDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTFIELDDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Type(); + VariableDeclarator(); + label_11: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_11; + } + jj_consume_token(COMMA); + VariableDeclarator(); + } + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void VariableDeclarator() throws ParseException { + /*@bgen(jjtree) VariableDeclarator */ + SimpleNode jjtn000 = new SimpleNode(JJTVARIABLEDECLARATOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + VariableDeclaratorId(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ASSIGN: + jj_consume_token(ASSIGN); + VariableInitializer(); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void VariableDeclaratorId() throws ParseException { + /*@bgen(jjtree) VariableDeclaratorId */ + SimpleNode jjtn000 = new SimpleNode(JJTVARIABLEDECLARATORID); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + label_12: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACKET: + ; + break; + default: + break label_12; + } + jj_consume_token(LBRACKET); + jj_consume_token(RBRACKET); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void VariableInitializer() throws ParseException { + /*@bgen(jjtree) VariableInitializer */ + SimpleNode jjtn000 = new SimpleNode(JJTVARIABLEINITIALIZER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACE: + ArrayInitializer(); + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case BANG: + case TILDE: + case INCR: + case DECR: + case PLUS: + case MINUS: + Expression(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ArrayInitializer() throws ParseException { + /*@bgen(jjtree) ArrayInitializer */ + SimpleNode jjtn000 = new SimpleNode(JJTARRAYINITIALIZER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LBRACE); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case LBRACE: + case BANG: + case TILDE: + case INCR: + case DECR: + case PLUS: + case MINUS: + VariableInitializer(); + label_13: + while (true) { + if (jj_2_11(2)) { + ; + } else { + break label_13; + } + jj_consume_token(COMMA); + VariableInitializer(); + } + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + jj_consume_token(COMMA); + break; + default: + ; + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MethodDeclaration(int modifiers) throws ParseException { + /*@bgen(jjtree) MethodDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTMETHODDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LT: + TypeParameters(); + break; + default: + ; + } + ResultType(); + MethodDeclarator(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case THROWS: + jj_consume_token(THROWS); + NameList(); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACE: + + if (parseMethodBody) { + + Block(); + + } else { + + // We do not want to parse inside a method implementation, we just need to get method prototypes + // See https://forge.nuiton.org/issues/3667 + + int nbBlocks = 0; + do { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACE: + nbBlocks++; + break; + case RBRACE: + nbBlocks--; + break; + } + jj_consume_token(jj_ntk); + } while (nbBlocks > 0); + + } + break; + case SEMICOLON: + jj_consume_token(SEMICOLON); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MethodDeclarator() throws ParseException { + /*@bgen(jjtree) MethodDeclarator */ + SimpleNode jjtn000 = new SimpleNode(JJTMETHODDECLARATOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + FormalParameters(); + label_14: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACKET: + ; + break; + default: + break label_14; + } + jj_consume_token(LBRACKET); + jj_consume_token(RBRACKET); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void FormalParameters() throws ParseException { + /*@bgen(jjtree) FormalParameters */ + SimpleNode jjtn000 = new SimpleNode(JJTFORMALPARAMETERS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LPAREN); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FINAL: + case FLOAT: + case INT: + case LONG: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOLATILE: + case IDENTIFIER: + case AT: + FormalParameter(); + label_15: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_15; + } + jj_consume_token(COMMA); + FormalParameter(); + } + break; + default: + ; + } + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void FormalParameter() throws ParseException { + /*@bgen(jjtree) FormalParameter */ + SimpleNode jjtn000 = new SimpleNode(JJTFORMALPARAMETER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Modifiers(); + Type(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ELLIPSIS: + jj_consume_token(ELLIPSIS); + break; + default: + ; + } + VariableDeclaratorId(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ConstructorDeclaration() throws ParseException { + /*@bgen(jjtree) ConstructorDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTCONSTRUCTORDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LT: + TypeParameters(); + break; + default: + ; + } + jj_consume_token(IDENTIFIER); + FormalParameters(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case THROWS: + jj_consume_token(THROWS); + NameList(); + break; + default: + ; + } + jj_consume_token(LBRACE); + if (jj_2_12(2147483647)) { + ExplicitConstructorInvocation(); + } else { + ; + } + + // >>> -------------------------- Only keep one node with text for constructor body + + StringBuilder constructoRawBody = new StringBuilder(); + // We do not care about what is inside the constructor, let's allow java 8 lambdas! + int lbraceNb = 1;// 1 left brace consumed + // while all the left braces have not been closed + SimpleNode jjtBody = new SimpleNode(JJTSTATEMENT); + jjtree.openNodeScope(jjtBody); + jjtreeOpenNodeScope(jjtBody); + + while (lbraceNb > 0) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACE: // new left brace opened + lbraceNb++; + break; + case RBRACE: // left brace closed + lbraceNb--; + break; + default: + break; + } + Token token = jj_consume_token(jj_ntk); + if (lbraceNb > 0) { + if (token.specialToken !=null) { + constructoRawBody.append(token.specialToken); + } + constructoRawBody.append(token.image); + } + } + Token bodyToken = new Token(); + bodyToken.image = constructoRawBody.toString(); + jjtBody.firstToken = bodyToken; + + jjtree.closeNodeScope(jjtBody, true); + jjtreeCloseNodeScope(jjtBody); + + // <<< -------------------------- Only keep one node with text for constructor body + + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ExplicitConstructorInvocation() throws ParseException { + /*@bgen(jjtree) ExplicitConstructorInvocation */ + SimpleNode jjtn000 = new SimpleNode(JJTEXPLICITCONSTRUCTORINVOCATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + label_17: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + ; + break; + default: + break label_17; + } + jj_consume_token(IDENTIFIER); + jj_consume_token(DOT); + } + if (jj_2_13(2)) { + jj_consume_token(THIS); + jj_consume_token(DOT); + } else { + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LT: + TypeArguments(); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case THIS: + jj_consume_token(THIS); + break; + case SUPER: + jj_consume_token(SUPER); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + Arguments(); + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Initializer() throws ParseException { + /*@bgen(jjtree) Initializer */ + SimpleNode jjtn000 = new SimpleNode(JJTINITIALIZER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case STATIC: + jj_consume_token(STATIC); + break; + default: + ; + } + Block(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* + * Type, name and expression syntax follows. + */ + final public void Type() throws ParseException { + /*@bgen(jjtree) Type */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_14(2)) { + ReferenceType(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + PrimitiveType(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ReferenceType() throws ParseException { + /*@bgen(jjtree) ReferenceType */ + SimpleNode jjtn000 = new SimpleNode(JJTREFERENCETYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + PrimitiveType(); + label_18: + while (true) { + jj_consume_token(LBRACKET); + jj_consume_token(RBRACKET); + if (jj_2_15(2)) { + ; + } else { + break label_18; + } + } + break; + case IDENTIFIER: + ClassOrInterfaceType(); + label_19: + while (true) { + if (jj_2_16(2)) { + ; + } else { + break label_19; + } + jj_consume_token(LBRACKET); + jj_consume_token(RBRACKET); + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ClassOrInterfaceType() throws ParseException { + /*@bgen(jjtree) ClassOrInterfaceType */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACETYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + if (jj_2_17(2)) { + TypeArguments(); + } else { + ; + } + label_20: + while (true) { + if (jj_2_18(2)) { + ; + } else { + break label_20; + } + jj_consume_token(DOT); + jj_consume_token(IDENTIFIER); + if (jj_2_19(2)) { + TypeArguments(); + } else { + ; + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void TypeArguments() throws ParseException { + /*@bgen(jjtree) TypeArguments */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEARGUMENTS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LT); + TypeArgument(); + label_21: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_21; + } + jj_consume_token(COMMA); + TypeArgument(); + } + jj_consume_token(GT); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void TypeArgumentsForAllocation() throws ParseException { + /*@bgen(jjtree) TypeArguments */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEARGUMENTS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LT); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case GT: + // Diamond expression (jdk7) + jj_consume_token(GT); + return; + } + TypeArgument(); + label_21: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_21; + } + jj_consume_token(COMMA); + TypeArgument(); + } + jj_consume_token(GT); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void TypeArgument() throws ParseException { + /*@bgen(jjtree) TypeArgument */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEARGUMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + case IDENTIFIER: + ReferenceType(); + break; + case HOOK: + jj_consume_token(HOOK); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case EXTENDS: + case SUPER: + WildcardBounds(); + break; + default: + ; + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void WildcardBounds() throws ParseException { + /*@bgen(jjtree) WildcardBounds */ + SimpleNode jjtn000 = new SimpleNode(JJTWILDCARDBOUNDS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case EXTENDS: + jj_consume_token(EXTENDS); + ReferenceType(); + break; + case SUPER: + jj_consume_token(SUPER); + ReferenceType(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PrimitiveType() throws ParseException { + /*@bgen(jjtree) PrimitiveType */ + SimpleNode jjtn000 = new SimpleNode(JJTPRIMITIVETYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + jj_consume_token(BOOLEAN); + break; + case CHAR: + jj_consume_token(CHAR); + break; + case BYTE: + jj_consume_token(BYTE); + break; + case SHORT: + jj_consume_token(SHORT); + break; + case INT: + jj_consume_token(INT); + break; + case LONG: + jj_consume_token(LONG); + break; + case FLOAT: + jj_consume_token(FLOAT); + break; + case DOUBLE: + jj_consume_token(DOUBLE); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ResultType() throws ParseException { + /*@bgen(jjtree) ResultType */ + SimpleNode jjtn000 = new SimpleNode(JJTRESULTTYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case VOID: + jj_consume_token(VOID); + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + case IDENTIFIER: + Type(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Name() throws ParseException { + /*@bgen(jjtree) Name */ + SimpleNode jjtn000 = new SimpleNode(JJTNAME); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + label_22: + while (true) { + if (jj_2_20(2)) { + ; + } else { + break label_22; + } + jj_consume_token(DOT); + jj_consume_token(IDENTIFIER); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void NameList() throws ParseException { + /*@bgen(jjtree) NameList */ + SimpleNode jjtn000 = new SimpleNode(JJTNAMELIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Name(); + label_23: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_23; + } + jj_consume_token(COMMA); + Name(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* + * Expression syntax follows. + */ + final public void Expression() throws ParseException { + /*@bgen(jjtree) Expression */ + SimpleNode jjtn000 = new SimpleNode(JJTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + ConditionalExpression(); + if (jj_2_21(2)) { + AssignmentOperator(); + Expression(); + } else { + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AssignmentOperator() throws ParseException { + /*@bgen(jjtree) AssignmentOperator */ + SimpleNode jjtn000 = new SimpleNode(JJTASSIGNMENTOPERATOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ASSIGN: + jj_consume_token(ASSIGN); + break; + case STARASSIGN: + jj_consume_token(STARASSIGN); + break; + case SLASHASSIGN: + jj_consume_token(SLASHASSIGN); + break; + case REMASSIGN: + jj_consume_token(REMASSIGN); + break; + case PLUSASSIGN: + jj_consume_token(PLUSASSIGN); + break; + case MINUSASSIGN: + jj_consume_token(MINUSASSIGN); + break; + case LSHIFTASSIGN: + jj_consume_token(LSHIFTASSIGN); + break; + case RSIGNEDSHIFTASSIGN: + jj_consume_token(RSIGNEDSHIFTASSIGN); + break; + case RUNSIGNEDSHIFTASSIGN: + jj_consume_token(RUNSIGNEDSHIFTASSIGN); + break; + case ANDASSIGN: + jj_consume_token(ANDASSIGN); + break; + case XORASSIGN: + jj_consume_token(XORASSIGN); + break; + case ORASSIGN: + jj_consume_token(ORASSIGN); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AssignmentExpression() throws ParseException { + /*@bgen(jjtree) AssignmentExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTASSIGNMENTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + PrimaryExpression(); + AssignmentOperator(); + Expression(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ConditionalExpression() throws ParseException { + /*@bgen(jjtree) ConditionalExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTCONDITIONALEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + ConditionalOrExpression(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case HOOK: + jj_consume_token(HOOK); + Expression(); + jj_consume_token(COLON); + Expression(); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ConditionalOrExpression() throws ParseException { + /*@bgen(jjtree) ConditionalOrExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTCONDITIONALOREXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + ConditionalAndExpression(); + label_24: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case SC_OR: + ; + break; + default: + break label_24; + } + jj_consume_token(SC_OR); + ConditionalAndExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ConditionalAndExpression() throws ParseException { + /*@bgen(jjtree) ConditionalAndExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTCONDITIONALANDEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + InclusiveOrExpression(); + label_25: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case SC_AND: + ; + break; + default: + break label_25; + } + jj_consume_token(SC_AND); + InclusiveOrExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void InclusiveOrExpression() throws ParseException { + /*@bgen(jjtree) InclusiveOrExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTINCLUSIVEOREXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + ExclusiveOrExpression(); + label_26: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BIT_OR: + ; + break; + default: + break label_26; + } + jj_consume_token(BIT_OR); + ExclusiveOrExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ExclusiveOrExpression() throws ParseException { + /*@bgen(jjtree) ExclusiveOrExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTEXCLUSIVEOREXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + AndExpression(); + label_27: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case XOR: + ; + break; + default: + break label_27; + } + jj_consume_token(XOR); + AndExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AndExpression() throws ParseException { + /*@bgen(jjtree) AndExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTANDEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + EqualityExpression(); + label_28: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BIT_AND: + ; + break; + default: + break label_28; + } + jj_consume_token(BIT_AND); + EqualityExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void EqualityExpression() throws ParseException { + /*@bgen(jjtree) EqualityExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTEQUALITYEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + InstanceOfExpression(); + label_29: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case EQ: + case NE: + ; + break; + default: + break label_29; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case EQ: + jj_consume_token(EQ); + break; + case NE: + jj_consume_token(NE); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + InstanceOfExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void InstanceOfExpression() throws ParseException { + /*@bgen(jjtree) InstanceOfExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTINSTANCEOFEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + RelationalExpression(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case INSTANCEOF: + jj_consume_token(INSTANCEOF); + Type(); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void RelationalExpression() throws ParseException { + /*@bgen(jjtree) RelationalExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTRELATIONALEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + ShiftExpression(); + label_30: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LT: + case LE: + case GE: + case GT: + ; + break; + default: + break label_30; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LT: + jj_consume_token(LT); + break; + case GT: + jj_consume_token(GT); + break; + case LE: + jj_consume_token(LE); + break; + case GE: + jj_consume_token(GE); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + ShiftExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ShiftExpression() throws ParseException { + /*@bgen(jjtree) ShiftExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTSHIFTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + AdditiveExpression(); + label_31: + while (true) { + if (jj_2_22(1)) { + ; + } else { + break label_31; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LSHIFT: + jj_consume_token(LSHIFT); + break; + default: + if (jj_2_23(1)) { + RSIGNEDSHIFT(); + } else if (jj_2_24(1)) { + RUNSIGNEDSHIFT(); + } else { + jj_consume_token(-1); + throw new ParseException(); + } + } + AdditiveExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AdditiveExpression() throws ParseException { + /*@bgen(jjtree) AdditiveExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTADDITIVEEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + MultiplicativeExpression(); + label_32: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PLUS: + case MINUS: + ; + break; + default: + break label_32; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PLUS: + jj_consume_token(PLUS); + break; + case MINUS: + jj_consume_token(MINUS); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + MultiplicativeExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MultiplicativeExpression() throws ParseException { + /*@bgen(jjtree) MultiplicativeExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTMULTIPLICATIVEEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + UnaryExpression(); + label_33: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case STAR: + case SLASH: + case REM: + ; + break; + default: + break label_33; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case STAR: + jj_consume_token(STAR); + break; + case SLASH: + jj_consume_token(SLASH); + break; + case REM: + jj_consume_token(REM); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + UnaryExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void UnaryExpression() throws ParseException { + /*@bgen(jjtree) UnaryExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTUNARYEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PLUS: + case MINUS: + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PLUS: + jj_consume_token(PLUS); + break; + case MINUS: + jj_consume_token(MINUS); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + UnaryExpression(); + break; + case INCR: + PreIncrementExpression(); + break; + case DECR: + PreDecrementExpression(); + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case BANG: + case TILDE: + UnaryExpressionNotPlusMinus(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PreIncrementExpression() throws ParseException { + /*@bgen(jjtree) PreIncrementExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTPREINCREMENTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(INCR); + PrimaryExpression(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PreDecrementExpression() throws ParseException { + /*@bgen(jjtree) PreDecrementExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTPREDECREMENTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(DECR); + PrimaryExpression(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void UnaryExpressionNotPlusMinus() throws ParseException { + /*@bgen(jjtree) UnaryExpressionNotPlusMinus */ + SimpleNode jjtn000 = new SimpleNode(JJTUNARYEXPRESSIONNOTPLUSMINUS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BANG: + case TILDE: + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case TILDE: + jj_consume_token(TILDE); + break; + case BANG: + jj_consume_token(BANG); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + UnaryExpression(); + break; + default: + if (jj_2_25(2147483647)) { + CastExpression(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + PostfixExpression(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + +// This production is to determine lookahead only. The LOOKAHEAD specifications +// below are not used, but they are there just to indicate that we know about + + // this. + final public void CastLookahead() throws ParseException { + /*@bgen(jjtree) CastLookahead */ + SimpleNode jjtn000 = new SimpleNode(JJTCASTLOOKAHEAD); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_26(2)) { + jj_consume_token(LPAREN); + PrimitiveType(); + } else if (jj_2_27(2147483647)) { + jj_consume_token(LPAREN); + Type(); + jj_consume_token(LBRACKET); + jj_consume_token(RBRACKET); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LPAREN: + jj_consume_token(LPAREN); + Type(); + jj_consume_token(RPAREN); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case TILDE: + jj_consume_token(TILDE); + break; + case BANG: + jj_consume_token(BANG); + break; + case LPAREN: + jj_consume_token(LPAREN); + break; + case IDENTIFIER: + jj_consume_token(IDENTIFIER); + break; + case THIS: + jj_consume_token(THIS); + break; + case SUPER: + jj_consume_token(SUPER); + break; + case NEW: + jj_consume_token(NEW); + break; + case FALSE: + case NULL: + case TRUE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + Literal(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PostfixExpression() throws ParseException { + /*@bgen(jjtree) PostfixExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTPOSTFIXEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + PrimaryExpression(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case INCR: + case DECR: + PostfixOperator(); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PostfixOperator() throws ParseException { + /*@bgen(jjtree) PostfixOperator */ + SimpleNode jjtn000 = new SimpleNode(JJTPOSTFIXOPERATOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case INCR: + jj_consume_token(INCR); + break; + case DECR: + jj_consume_token(DECR); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void CastExpression() throws ParseException { + /*@bgen(jjtree) CastExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTCASTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_28(2147483647)) { + jj_consume_token(LPAREN); + Type(); + jj_consume_token(RPAREN); + UnaryExpression(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LPAREN: + jj_consume_token(LPAREN); + Type(); + jj_consume_token(RPAREN); + UnaryExpressionNotPlusMinus(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PrimaryExpression() throws ParseException { + /*@bgen(jjtree) PrimaryExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTPRIMARYEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + PrimaryPrefix(); + label_34: + while (true) { + if (jj_2_29(2)) { + ; + } else { + break label_34; + } + PrimarySuffix(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MemberSelector() throws ParseException { + /*@bgen(jjtree) MemberSelector */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERSELECTOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(DOT); + TypeArguments(); + jj_consume_token(IDENTIFIER); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PrimaryPrefix() throws ParseException { + /*@bgen(jjtree) PrimaryPrefix */ + SimpleNode jjtn000 = new SimpleNode(JJTPRIMARYPREFIX); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case FALSE: + case NULL: + case TRUE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + Literal(); + break; + default: + if (jj_2_30(2147483647)) { + label_35: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + ; + break; + default: + break label_35; + } + jj_consume_token(IDENTIFIER); + jj_consume_token(DOT); + } + jj_consume_token(THIS); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case SUPER: + jj_consume_token(SUPER); + jj_consume_token(DOT); + jj_consume_token(IDENTIFIER); + break; + case LPAREN: + jj_consume_token(LPAREN); + Expression(); + jj_consume_token(RPAREN); + break; + case NEW: + AllocationExpression(); + break; + default: + if (jj_2_31(2147483647)) { + ResultType(); + jj_consume_token(DOT); + jj_consume_token(CLASS); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + Name(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PrimarySuffix() throws ParseException { + /*@bgen(jjtree) PrimarySuffix */ + SimpleNode jjtn000 = new SimpleNode(JJTPRIMARYSUFFIX); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_32(2147483647)) { + jj_consume_token(DOT); + jj_consume_token(SUPER); + } else if (jj_2_33(2147483647)) { + jj_consume_token(DOT); + jj_consume_token(THIS); + } else if (jj_2_34(2)) { + jj_consume_token(DOT); + AllocationExpression(); + } else if (jj_2_35(3)) { + MemberSelector(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACKET: + jj_consume_token(LBRACKET); + Expression(); + jj_consume_token(RBRACKET); + break; + case DOT: + jj_consume_token(DOT); + jj_consume_token(IDENTIFIER); + break; + case LPAREN: + Arguments(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Literal() throws ParseException { + /*@bgen(jjtree) Literal */ + SimpleNode jjtn000 = new SimpleNode(JJTLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case INTEGER_LITERAL: + jj_consume_token(INTEGER_LITERAL); + break; + case FLOATING_POINT_LITERAL: + jj_consume_token(FLOATING_POINT_LITERAL); + break; + case CHARACTER_LITERAL: + jj_consume_token(CHARACTER_LITERAL); + break; + case STRING_LITERAL: + jj_consume_token(STRING_LITERAL); + break; + case FALSE: + case TRUE: + BooleanLiteral(); + break; + case NULL: + NullLiteral(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void BooleanLiteral() throws ParseException { + /*@bgen(jjtree) BooleanLiteral */ + SimpleNode jjtn000 = new SimpleNode(JJTBOOLEANLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case TRUE: + jj_consume_token(TRUE); + break; + case FALSE: + jj_consume_token(FALSE); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void NullLiteral() throws ParseException { + /*@bgen(jjtree) NullLiteral */ + SimpleNode jjtn000 = new SimpleNode(JJTNULLLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(NULL); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Arguments() throws ParseException { + /*@bgen(jjtree) Arguments */ + SimpleNode jjtn000 = new SimpleNode(JJTARGUMENTS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LPAREN); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case BANG: + case TILDE: + case INCR: + case DECR: + case PLUS: + case MINUS: + ArgumentList(); + break; + default: + ; + } + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ArgumentList() throws ParseException { + /*@bgen(jjtree) ArgumentList */ + SimpleNode jjtn000 = new SimpleNode(JJTARGUMENTLIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Expression(); + label_36: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_36; + } + jj_consume_token(COMMA); + Expression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AllocationExpression() throws ParseException { + /*@bgen(jjtree) AllocationExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTALLOCATIONEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_36(2)) { + jj_consume_token(NEW); + PrimitiveType(); + ArrayDimsAndInits(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case NEW: + jj_consume_token(NEW); + ClassOrInterfaceType(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LT: + TypeArgumentsForAllocation(); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACKET: + ArrayDimsAndInits(); + break; + case LPAREN: + Arguments(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACE: + ClassOrInterfaceBody(false); + break; + default: + ; + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* + * The third LOOKAHEAD specification below is to parse to PrimarySuffix + * if there is an expression between the "[...]". + */ + final public void ArrayDimsAndInits() throws ParseException { + /*@bgen(jjtree) ArrayDimsAndInits */ + SimpleNode jjtn000 = new SimpleNode(JJTARRAYDIMSANDINITS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_39(2)) { + label_37: + while (true) { + jj_consume_token(LBRACKET); + Expression(); + jj_consume_token(RBRACKET); + if (jj_2_37(2)) { + ; + } else { + break label_37; + } + } + label_38: + while (true) { + if (jj_2_38(2)) { + ; + } else { + break label_38; + } + jj_consume_token(LBRACKET); + jj_consume_token(RBRACKET); + } + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACKET: + label_39: + while (true) { + jj_consume_token(LBRACKET); + jj_consume_token(RBRACKET); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACKET: + ; + break; + default: + break label_39; + } + } + ArrayInitializer(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* + * Statement syntax follows. + */ + final public void Statement() throws ParseException { + /*@bgen(jjtree) Statement */ + SimpleNode jjtn000 = new SimpleNode(JJTSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_40(2)) { + LabeledStatement(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ASSERT: + AssertStatement(); + break; + case LBRACE: + Block(); + break; + case SEMICOLON: + EmptyStatement(); + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case INCR: + case DECR: + StatementExpression(); + jj_consume_token(SEMICOLON); + break; + case SWITCH: + SwitchStatement(); + break; + case IF: + IfStatement(); + break; + case WHILE: + WhileStatement(); + break; + case DO: + DoStatement(); + break; + case FOR: + ForStatement(); + break; + case BREAK: + BreakStatement(); + break; + case CONTINUE: + ContinueStatement(); + break; + case RETURN: + ReturnStatement(); + break; + case THROW: + ThrowStatement(); + break; + case SYNCHRONIZED: + SynchronizedStatement(); + break; + case TRY: + TryStatement(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AssertStatement() throws ParseException { + /*@bgen(jjtree) AssertStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTASSERTSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(ASSERT); + Expression(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COLON: + jj_consume_token(COLON); + Expression(); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void LabeledStatement() throws ParseException { + /*@bgen(jjtree) LabeledStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTLABELEDSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + jj_consume_token(COLON); + Statement(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Block() throws ParseException { + /*@bgen(jjtree) Block */ + SimpleNode jjtn000 = new SimpleNode(JJTBLOCK); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LBRACE); + label_40: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case ASSERT: + case BOOLEAN: + case BREAK: + case BYTE: + case CHAR: + case CLASS: + case CONTINUE: + case DO: + case DOUBLE: + case FALSE: + case FINAL: + case FLOAT: + case FOR: + case IF: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case NEW: + case NULL: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case RETURN: + case SHORT: + case STATIC: + case STRICTFP: + case SUPER: + case SWITCH: + case SYNCHRONIZED: + case THIS: + case THROW: + case TRANSIENT: + case TRUE: + case TRY: + case VOID: + case VOLATILE: + case WHILE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case LBRACE: + case SEMICOLON: + case AT: + case INCR: + case DECR: + ; + break; + default: + break label_40; + } + BlockStatement(); + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void BlockStatement() throws ParseException { + /*@bgen(jjtree) BlockStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTBLOCKSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_41(2147483647)) { + LocalVariableDeclaration(); + jj_consume_token(SEMICOLON); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ASSERT: + case BOOLEAN: + case BREAK: + case BYTE: + case CHAR: + case CONTINUE: + case DO: + case DOUBLE: + case FALSE: + case FLOAT: + case FOR: + case IF: + case INT: + case LONG: + case NEW: + case NULL: + case RETURN: + case SHORT: + case SUPER: + case SWITCH: + case SYNCHRONIZED: + case THIS: + case THROW: + case TRUE: + case TRY: + case VOID: + case WHILE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case LBRACE: + case SEMICOLON: + case INCR: + case DECR: + Statement(); + break; + case CLASS: + case INTERFACE: + ClassOrInterfaceDeclaration(0); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void LocalVariableDeclaration() throws ParseException { + /*@bgen(jjtree) LocalVariableDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTLOCALVARIABLEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Modifiers(); + Type(); + VariableDeclarator(); + label_41: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_41; + } + jj_consume_token(COMMA); + VariableDeclarator(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void EmptyStatement() throws ParseException { + /*@bgen(jjtree) EmptyStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTEMPTYSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(SEMICOLON); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void StatementExpression() throws ParseException { + /*@bgen(jjtree) StatementExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTSTATEMENTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case INCR: + PreIncrementExpression(); + break; + case DECR: + PreDecrementExpression(); + break; + default: + if (jj_2_42(2147483647)) { + AssignmentExpression(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + PostfixExpression(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void SwitchStatement() throws ParseException { + /*@bgen(jjtree) SwitchStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTSWITCHSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(SWITCH); + jj_consume_token(LPAREN); + Expression(); + jj_consume_token(RPAREN); + jj_consume_token(LBRACE); + label_42: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case CASE: + case _DEFAULT: + ; + break; + default: + break label_42; + } + SwitchLabel(); + label_43: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case ASSERT: + case BOOLEAN: + case BREAK: + case BYTE: + case CHAR: + case CLASS: + case CONTINUE: + case DO: + case DOUBLE: + case FALSE: + case FINAL: + case FLOAT: + case FOR: + case IF: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case NEW: + case NULL: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case RETURN: + case SHORT: + case STATIC: + case STRICTFP: + case SUPER: + case SWITCH: + case SYNCHRONIZED: + case THIS: + case THROW: + case TRANSIENT: + case TRUE: + case TRY: + case VOID: + case VOLATILE: + case WHILE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case LBRACE: + case SEMICOLON: + case AT: + case INCR: + case DECR: + ; + break; + default: + break label_43; + } + BlockStatement(); + } + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void SwitchLabel() throws ParseException { + /*@bgen(jjtree) SwitchLabel */ + SimpleNode jjtn000 = new SimpleNode(JJTSWITCHLABEL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case CASE: + jj_consume_token(CASE); + Expression(); + jj_consume_token(COLON); + break; + case _DEFAULT: + jj_consume_token(_DEFAULT); + jj_consume_token(COLON); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void IfStatement() throws ParseException { + /*@bgen(jjtree) IfStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTIFSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IF); + jj_consume_token(LPAREN); + Expression(); + jj_consume_token(RPAREN); + Statement(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ELSE: + jj_consume_token(ELSE); + Statement(); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void WhileStatement() throws ParseException { + /*@bgen(jjtree) WhileStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTWHILESTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(WHILE); + jj_consume_token(LPAREN); + Expression(); + jj_consume_token(RPAREN); + Statement(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void DoStatement() throws ParseException { + /*@bgen(jjtree) DoStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTDOSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(DO); + Statement(); + jj_consume_token(WHILE); + jj_consume_token(LPAREN); + Expression(); + jj_consume_token(RPAREN); + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ForStatement() throws ParseException { + /*@bgen(jjtree) ForStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTFORSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(FOR); + jj_consume_token(LPAREN); + if (jj_2_43(2147483647)) { + Modifiers(); + Type(); + jj_consume_token(IDENTIFIER); + jj_consume_token(COLON); + Expression(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FINAL: + case FLOAT: + case INT: + case LONG: + case NATIVE: + case NEW: + case NULL: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SUPER: + case SYNCHRONIZED: + case THIS: + case TRANSIENT: + case TRUE: + case VOID: + case VOLATILE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case SEMICOLON: + case AT: + case INCR: + case DECR: + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FINAL: + case FLOAT: + case INT: + case LONG: + case NATIVE: + case NEW: + case NULL: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SUPER: + case SYNCHRONIZED: + case THIS: + case TRANSIENT: + case TRUE: + case VOID: + case VOLATILE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case AT: + case INCR: + case DECR: + ForInit(); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case BANG: + case TILDE: + case INCR: + case DECR: + case PLUS: + case MINUS: + Expression(); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case INCR: + case DECR: + ForUpdate(); + break; + default: + ; + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + jj_consume_token(RPAREN); + Statement(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ForInit() throws ParseException { + /*@bgen(jjtree) ForInit */ + SimpleNode jjtn000 = new SimpleNode(JJTFORINIT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_44(2147483647)) { + LocalVariableDeclaration(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case INCR: + case DECR: + StatementExpressionList(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void StatementExpressionList() throws ParseException { + /*@bgen(jjtree) StatementExpressionList */ + SimpleNode jjtn000 = new SimpleNode(JJTSTATEMENTEXPRESSIONLIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + StatementExpression(); + label_44: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_44; + } + jj_consume_token(COMMA); + StatementExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ForUpdate() throws ParseException { + /*@bgen(jjtree) ForUpdate */ + SimpleNode jjtn000 = new SimpleNode(JJTFORUPDATE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + StatementExpressionList(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void BreakStatement() throws ParseException { + /*@bgen(jjtree) BreakStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTBREAKSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(BREAK); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + jj_consume_token(IDENTIFIER); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ContinueStatement() throws ParseException { + /*@bgen(jjtree) ContinueStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTCONTINUESTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(CONTINUE); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + jj_consume_token(IDENTIFIER); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ReturnStatement() throws ParseException { + /*@bgen(jjtree) ReturnStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTRETURNSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(RETURN); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case BANG: + case TILDE: + case INCR: + case DECR: + case PLUS: + case MINUS: + Expression(); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ThrowStatement() throws ParseException { + /*@bgen(jjtree) ThrowStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTTHROWSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(THROW); + Expression(); + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void SynchronizedStatement() throws ParseException { + /*@bgen(jjtree) SynchronizedStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTSYNCHRONIZEDSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(SYNCHRONIZED); + jj_consume_token(LPAREN); + Expression(); + jj_consume_token(RPAREN); + Block(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void TryStatement() throws ParseException { + /*@bgen(jjtree) TryStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTTRYSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(TRY); + Block(); + label_45: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case CATCH: + ; + break; + default: + break label_45; + } + jj_consume_token(CATCH); + jj_consume_token(LPAREN); + FormalParameter(); + jj_consume_token(RPAREN); + Block(); + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case FINALLY: + jj_consume_token(FINALLY); + Block(); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* We use productions to match >>>, >> and > so that we can keep the + * type declaration syntax with generics clean + */ + final public void RUNSIGNEDSHIFT() throws ParseException { + /*@bgen(jjtree) RUNSIGNEDSHIFT */ + SimpleNode jjtn000 = new SimpleNode(JJTRUNSIGNEDSHIFT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (getToken(1).kind == GT && + ((Token.GTToken) getToken(1)).realKind == RUNSIGNEDSHIFT) { + + } else { + jj_consume_token(-1); + throw new ParseException(); + } + jj_consume_token(GT); + jj_consume_token(GT); + jj_consume_token(GT); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void RSIGNEDSHIFT() throws ParseException { + /*@bgen(jjtree) RSIGNEDSHIFT */ + SimpleNode jjtn000 = new SimpleNode(JJTRSIGNEDSHIFT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (getToken(1).kind == GT && + ((Token.GTToken) getToken(1)).realKind == RSIGNEDSHIFT) { + + } else { + jj_consume_token(-1); + throw new ParseException(); + } + jj_consume_token(GT); + jj_consume_token(GT); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* Annotation syntax follows. */ + final public void Annotation() throws ParseException { + /*@bgen(jjtree) Annotation */ + SimpleNode jjtn000 = new SimpleNode(JJTANNOTATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_45(2147483647)) { + NormalAnnotation(); + } else if (jj_2_46(2147483647)) { + SingleMemberAnnotation(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case AT: + MarkerAnnotation(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void NormalAnnotation() throws ParseException { + /*@bgen(jjtree) NormalAnnotation */ + SimpleNode jjtn000 = new SimpleNode(JJTNORMALANNOTATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(AT); + Name(); + jj_consume_token(LPAREN); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + MemberValuePairs(); + break; + default: + ; + } + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MarkerAnnotation() throws ParseException { + /*@bgen(jjtree) MarkerAnnotation */ + SimpleNode jjtn000 = new SimpleNode(JJTMARKERANNOTATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(AT); + Name(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void SingleMemberAnnotation() throws ParseException { + /*@bgen(jjtree) SingleMemberAnnotation */ + SimpleNode jjtn000 = new SimpleNode(JJTSINGLEMEMBERANNOTATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(AT); + Name(); + jj_consume_token(LPAREN); + MemberValue(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MemberValuePairs() throws ParseException { + /*@bgen(jjtree) MemberValuePairs */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUEPAIRS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + MemberValuePair(); + label_46: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_46; + } + jj_consume_token(COMMA); + MemberValuePair(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MemberValuePair() throws ParseException { + /*@bgen(jjtree) MemberValuePair */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUEPAIR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + jj_consume_token(ASSIGN); + MemberValue(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MemberValue() throws ParseException { + /*@bgen(jjtree) MemberValue */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case AT: + Annotation(); + break; + case LBRACE: + MemberValueArrayInitializer(); + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case BANG: + case TILDE: + case INCR: + case DECR: + case PLUS: + case MINUS: + ConditionalExpression(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MemberValueArrayInitializer() throws ParseException { + /*@bgen(jjtree) MemberValueArrayInitializer */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUEARRAYINITIALIZER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LBRACE); + MemberValue(); + label_47: + while (true) { + if (jj_2_47(2)) { + ; + } else { + break label_47; + } + jj_consume_token(COMMA); + MemberValue(); + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + jj_consume_token(COMMA); + break; + default: + ; + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* Annotation Types. */ + final public void AnnotationTypeDeclaration(int modifiers) throws ParseException { + /*@bgen(jjtree) AnnotationTypeDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTANNOTATIONTYPEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(AT); + jj_consume_token(INTERFACE); + jj_consume_token(IDENTIFIER); + AnnotationTypeBody(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AnnotationTypeBody() throws ParseException { + /*@bgen(jjtree) AnnotationTypeBody */ + SimpleNode jjtn000 = new SimpleNode(JJTANNOTATIONTYPEBODY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LBRACE); + label_48: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case CLASS: + case DOUBLE: + case ENUM: + case FINAL: + case FLOAT: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOLATILE: + case IDENTIFIER: + case SEMICOLON: + case AT: + ; + break; + default: + break label_48; + } + AnnotationTypeMemberDeclaration(); + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AnnotationTypeMemberDeclaration() throws ParseException { + /*@bgen(jjtree) AnnotationTypeMemberDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTANNOTATIONTYPEMEMBERDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + int modifiers; + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case CLASS: + case DOUBLE: + case ENUM: + case FINAL: + case FLOAT: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOLATILE: + case IDENTIFIER: + case AT: + modifiers = Modifiers(); + if (jj_2_48(2147483647)) { + Type(); + jj_consume_token(IDENTIFIER); + jj_consume_token(LPAREN); + jj_consume_token(RPAREN); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case _DEFAULT: + DefaultValue(); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case CLASS: + case INTERFACE: + ClassOrInterfaceDeclaration(modifiers); + break; + case ENUM: + EnumDeclaration(modifiers); + break; + case AT: + AnnotationTypeDeclaration(modifiers); + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + case IDENTIFIER: + FieldDeclaration(modifiers); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + break; + case SEMICOLON: + jj_consume_token(SEMICOLON); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void DefaultValue() throws ParseException { + /*@bgen(jjtree) DefaultValue */ + SimpleNode jjtn000 = new SimpleNode(JJTDEFAULTVALUE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(_DEFAULT); + MemberValue(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final private boolean jj_2_1(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_1(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_2(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_2(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_3(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_3(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_4(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_4(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_5(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_5(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_6(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_6(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_7(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_7(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_8(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_8(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_9(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_9(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_10(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_10(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_11(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_11(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_12(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_12(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_13(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_13(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_14(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_14(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_15(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_15(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_16(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_16(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_17(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_17(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_18(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_18(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_19(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_19(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_20(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_20(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_21(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_21(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_22(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_22(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_23(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_23(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_24(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_24(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_25(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_25(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_26(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_26(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_27(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_27(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_28(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_28(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_29(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_29(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_30(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_30(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_31(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_31(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_32(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_32(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_33(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_33(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_34(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_34(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_35(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_35(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_36(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_36(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_37(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_37(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_38(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_38(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_39(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_39(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_40(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_40(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_41(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_41(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_42(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_42(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_43(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_43(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_44(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_44(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_45(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_45(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_46(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_46(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_47(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_47(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_48(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_48(); + } catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_3R_56() { + if (jj_3R_101()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3_21()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_135() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_91()) return true; + return false; + } + + final private boolean jj_3R_99() { + if (jj_3R_91()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_135()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3_20() { + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(IDENTIFIER)) return true; + return false; + } + + final private boolean jj_3R_91() { + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_20()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_122() { + if (jj_3R_72()) return true; + return false; + } + + final private boolean jj_3R_86() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(58)) { + jj_scanpos = xsp; + if (jj_3R_122()) return true; + } + return false; + } + + final private boolean jj_3_19() { + if (jj_3R_78()) return true; + return false; + } + + final private boolean jj_3R_83() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(10)) { + jj_scanpos = xsp; + if (jj_scan_token(15)) { + jj_scanpos = xsp; + if (jj_scan_token(12)) { + jj_scanpos = xsp; + if (jj_scan_token(46)) { + jj_scanpos = xsp; + if (jj_scan_token(35)) { + jj_scanpos = xsp; + if (jj_scan_token(37)) { + jj_scanpos = xsp; + if (jj_scan_token(28)) { + jj_scanpos = xsp; + if (jj_scan_token(21)) return true; + } + } + } + } + } + } + } + return false; + } + + final private boolean jj_3R_194() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_112()) return true; + return false; + } + + final private boolean jj_3R_290() { + if (jj_scan_token(SUPER)) return true; + if (jj_3R_77()) return true; + return false; + } + + final private boolean jj_3_16() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_289() { + if (jj_scan_token(EXTENDS)) return true; + if (jj_3R_77()) return true; + return false; + } + + final private boolean jj_3R_277() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_289()) { + jj_scanpos = xsp; + if (jj_3R_290()) return true; + } + return false; + } + + final private boolean jj_3R_256() { + if (jj_3R_277()) return true; + return false; + } + + final private boolean jj_3R_151() { + if (jj_scan_token(HOOK)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_256()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3_17() { + if (jj_3R_78()) return true; + return false; + } + + final private boolean jj_3R_112() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_150()) { + jj_scanpos = xsp; + if (jj_3R_151()) return true; + } + return false; + } + + final private boolean jj_3R_150() { + if (jj_3R_77()) return true; + return false; + } + + final private boolean jj_3_15() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_78() { + if (jj_scan_token(LT)) return true; + if (jj_3R_112()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_194()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(GT)) return true; + return false; + } + + final private boolean jj_3_18() { + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3_19()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_149() { + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3_17()) jj_scanpos = xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_18()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_111() { + if (jj_3R_149()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_16()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_110() { + if (jj_3R_83()) return true; + Token xsp; + if (jj_3_15()) return true; + while (true) { + xsp = jj_scanpos; + if (jj_3_15()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_77() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_110()) { + jj_scanpos = xsp; + if (jj_3R_111()) return true; + } + return false; + } + + final private boolean jj_3_13() { + if (jj_scan_token(THIS)) return true; + if (jj_scan_token(DOT)) return true; + return false; + } + + final private boolean jj_3R_221() { + if (jj_scan_token(THROWS)) return true; + if (jj_3R_99()) return true; + return false; + } + + final private boolean jj_3R_103() { + if (jj_3R_83()) return true; + return false; + } + + final private boolean jj_3R_72() { + Token xsp; + xsp = jj_scanpos; + if (jj_3_14()) { + jj_scanpos = xsp; + if (jj_3R_103()) return true; + } + return false; + } + + final private boolean jj_3_14() { + if (jj_3R_77()) return true; + return false; + } + + final private boolean jj_3R_74() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(47)) jj_scanpos = xsp; + if (jj_3R_104()) return true; + return false; + } + + final private boolean jj_3_12() { + if (jj_3R_76()) return true; + return false; + } + + final private boolean jj_3R_108() { + if (jj_3R_78()) return true; + return false; + } + + final private boolean jj_3R_107() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(DOT)) return true; + return false; + } + + final private boolean jj_3R_252() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_76() { + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_107()) { + jj_scanpos = xsp; + break; + } + } + xsp = jj_scanpos; + if (jj_3_13()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_108()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_scan_token(52)) { + jj_scanpos = xsp; + if (jj_scan_token(49)) return true; + } + if (jj_3R_109()) return true; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_134() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_133()) return true; + return false; + } + + final private boolean jj_3R_223() { + if (jj_3R_49()) return true; + return false; + } + + final private boolean jj_3R_222() { + if (jj_3R_76()) return true; + return false; + } + + final private boolean jj_3R_220() { + if (jj_3R_97()) return true; + return false; + } + + final private boolean jj_3R_186() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_220()) jj_scanpos = xsp; + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_3R_53()) return true; + xsp = jj_scanpos; + if (jj_3R_221()) jj_scanpos = xsp; + if (jj_scan_token(LBRACE)) return true; + xsp = jj_scanpos; + if (jj_3R_222()) jj_scanpos = xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_223()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(RBRACE)) return true; + return false; + } + + final private boolean jj_3_11() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_75()) return true; + return false; + } + + final private boolean jj_3R_227() { + if (jj_scan_token(THROWS)) return true; + if (jj_3R_99()) return true; + return false; + } + + final private boolean jj_3R_98() { + if (jj_3R_133()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_134()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_133() { + if (jj_3R_50()) return true; + if (jj_3R_72()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(119)) jj_scanpos = xsp; + if (jj_3R_184()) return true; + return false; + } + + final private boolean jj_3R_53() { + if (jj_scan_token(LPAREN)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_98()) jj_scanpos = xsp; + if (jj_scan_token(RPAREN)) return true; + return false; + } + + final private boolean jj_3_48() { + if (jj_3R_72()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(LPAREN)) return true; + return false; + } + + final private boolean jj_3R_226() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_3R_53()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_252()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_228() { + if (jj_3R_104()) return true; + return false; + } + + final private boolean jj_3R_225() { + if (jj_3R_97()) return true; + return false; + } + + final private boolean jj_3R_292() { + if (jj_3R_75()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_11()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_188() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_225()) jj_scanpos = xsp; + if (jj_3R_86()) return true; + if (jj_3R_226()) return true; + xsp = jj_scanpos; + if (jj_3R_227()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_228()) { + jj_scanpos = xsp; + if (jj_scan_token(81)) return true; + } + return false; + } + + final private boolean jj_3R_198() { + if (jj_scan_token(ASSIGN)) return true; + if (jj_3R_75()) return true; + return false; + } + + final private boolean jj_3R_224() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_161()) return true; + return false; + } + + final private boolean jj_3_47() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_93()) return true; + return false; + } + + final private boolean jj_3R_217() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_147() { + if (jj_scan_token(LBRACE)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_292()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_scan_token(82)) jj_scanpos = xsp; + if (jj_scan_token(RBRACE)) return true; + return false; + } + + final private boolean jj_3R_73() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_106() { + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_105() { + if (jj_3R_147()) return true; + return false; + } + + final private boolean jj_3R_75() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_105()) { + jj_scanpos = xsp; + if (jj_3R_106()) return true; + } + return false; + } + + final private boolean jj_3R_184() { + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_217()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_160() { + if (jj_scan_token(LBRACE)) return true; + if (jj_3R_93()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_47()) { + jj_scanpos = xsp; + break; + } + } + xsp = jj_scanpos; + if (jj_scan_token(82)) jj_scanpos = xsp; + if (jj_scan_token(RBRACE)) return true; + return false; + } + + final private boolean jj_3R_276() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_275()) return true; + return false; + } + + final private boolean jj_3R_161() { + if (jj_3R_184()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_198()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_127() { + if (jj_3R_101()) return true; + return false; + } + + final private boolean jj_3_9() { + if (jj_3R_72()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_73()) { + jj_scanpos = xsp; + break; + } + } + xsp = jj_scanpos; + if (jj_scan_token(82)) { + jj_scanpos = xsp; + if (jj_scan_token(85)) { + jj_scanpos = xsp; + if (jj_scan_token(81)) return true; + } + } + return false; + } + + final private boolean jj_3R_126() { + if (jj_3R_160()) return true; + return false; + } + + final private boolean jj_3R_71() { + if (jj_3R_97()) return true; + return false; + } + + final private boolean jj_3R_93() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_125()) { + jj_scanpos = xsp; + if (jj_3R_126()) { + jj_scanpos = xsp; + if (jj_3R_127()) return true; + } + } + return false; + } + + final private boolean jj_3R_125() { + if (jj_3R_102()) return true; + return false; + } + + final private boolean jj_3_8() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_71()) jj_scanpos = xsp; + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(LPAREN)) return true; + return false; + } + + final private boolean jj_3R_187() { + if (jj_3R_72()) return true; + if (jj_3R_161()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_224()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_275() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(ASSIGN)) return true; + if (jj_3R_93()) return true; + return false; + } + + final private boolean jj_3R_140() { + if (jj_3R_188()) return true; + return false; + } + + final private boolean jj_3R_139() { + if (jj_3R_187()) return true; + return false; + } + + final private boolean jj_3R_249() { + if (jj_scan_token(BIT_AND)) return true; + if (jj_3R_149()) return true; + return false; + } + + final private boolean jj_3R_138() { + if (jj_3R_186()) return true; + return false; + } + + final private boolean jj_3R_255() { + if (jj_3R_275()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_276()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_231() { + if (jj_3R_255()) return true; + return false; + } + + final private boolean jj_3R_137() { + if (jj_3R_185()) return true; + return false; + } + + final private boolean jj_3R_92() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(ASSIGN)) return true; + return false; + } + + final private boolean jj_3R_136() { + if (jj_3R_130()) return true; + return false; + } + + final private boolean jj_3R_192() { + if (jj_scan_token(AT)) return true; + if (jj_3R_91()) return true; + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_93()) return true; + if (jj_scan_token(RPAREN)) return true; + return false; + } + + final private boolean jj_3R_286() { + if (jj_3R_182()) return true; + return false; + } + + final private boolean jj_3R_100() { + if (jj_3R_50()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_136()) { + jj_scanpos = xsp; + if (jj_3R_137()) { + jj_scanpos = xsp; + if (jj_3R_138()) { + jj_scanpos = xsp; + if (jj_3R_139()) { + jj_scanpos = xsp; + if (jj_3R_140()) return true; + } + } + } + } + return false; + } + + final private boolean jj_3R_193() { + if (jj_scan_token(AT)) return true; + if (jj_3R_91()) return true; + return false; + } + + final private boolean jj_3_46() { + if (jj_scan_token(AT)) return true; + if (jj_3R_91()) return true; + if (jj_scan_token(LPAREN)) return true; + return false; + } + + final private boolean jj_3_10() { + if (jj_3R_74()) return true; + return false; + } + + final private boolean jj_3R_55() { + Token xsp; + xsp = jj_scanpos; + if (jj_3_10()) { + jj_scanpos = xsp; + if (jj_3R_100()) { + jj_scanpos = xsp; + if (jj_scan_token(81)) return true; + } + } + return false; + } + + final private boolean jj_3R_191() { + if (jj_scan_token(AT)) return true; + if (jj_3R_91()) return true; + if (jj_scan_token(LPAREN)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_231()) jj_scanpos = xsp; + if (jj_scan_token(RPAREN)) return true; + return false; + } + + final private boolean jj_3_45() { + if (jj_scan_token(AT)) return true; + if (jj_3R_91()) return true; + if (jj_scan_token(LPAREN)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_92()) { + jj_scanpos = xsp; + if (jj_scan_token(76)) return true; + } + return false; + } + + final private boolean jj_3R_215() { + if (jj_3R_55()) return true; + return false; + } + + final private boolean jj_3R_132() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_131()) return true; + return false; + } + + final private boolean jj_3R_183() { + if (jj_3R_216()) return true; + return false; + } + + final private boolean jj_3R_285() { + if (jj_3R_109()) return true; + return false; + } + + final private boolean jj_3R_145() { + if (jj_3R_193()) return true; + return false; + } + + final private boolean jj_3R_182() { + if (jj_scan_token(LBRACE)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_215()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(RBRACE)) return true; + return false; + } + + final private boolean jj_3R_144() { + if (jj_3R_192()) return true; + return false; + } + + final private boolean jj_3R_113() { + return false; + } + + final private boolean jj_3R_102() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_143()) { + jj_scanpos = xsp; + if (jj_3R_144()) { + jj_scanpos = xsp; + if (jj_3R_145()) return true; + } + } + return false; + } + + final private boolean jj_3R_143() { + if (jj_3R_191()) return true; + return false; + } + + final private boolean jj_3R_216() { + if (jj_scan_token(EXTENDS)) return true; + if (jj_3R_149()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_249()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_131() { + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_183()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_114() { + return false; + } + + final private boolean jj_3_7() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_70()) return true; + return false; + } + + final private boolean jj_3R_80() { + Token xsp; + xsp = jj_scanpos; + lookingAhead = true; + jj_semLA = getToken(1).kind == GT && + ((Token.GTToken) getToken(1)).realKind == RSIGNEDSHIFT; + lookingAhead = false; + if (!jj_semLA || jj_3R_113()) return true; + if (jj_scan_token(GT)) return true; + if (jj_scan_token(GT)) return true; + return false; + } + + final private boolean jj_3R_97() { + if (jj_scan_token(LT)) return true; + if (jj_3R_131()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_132()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(GT)) return true; + return false; + } + + final private boolean jj_3R_272() { + if (jj_3R_55()) return true; + return false; + } + + final private boolean jj_3R_70() { + if (jj_3R_50()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_285()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_286()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_81() { + Token xsp; + xsp = jj_scanpos; + lookingAhead = true; + jj_semLA = getToken(1).kind == GT && + ((Token.GTToken) getToken(1)).realKind == RUNSIGNEDSHIFT; + lookingAhead = false; + if (!jj_semLA || jj_3R_114()) return true; + if (jj_scan_token(GT)) return true; + if (jj_scan_token(GT)) return true; + if (jj_scan_token(GT)) return true; + return false; + } + + final private boolean jj_3R_251() { + if (jj_scan_token(SEMICOLON)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_272()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_250() { + if (jj_3R_70()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_7()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_246() { + if (jj_scan_token(FINALLY)) return true; + if (jj_3R_104()) return true; + return false; + } + + final private boolean jj_3R_219() { + if (jj_scan_token(LBRACE)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_250()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_scan_token(82)) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_251()) jj_scanpos = xsp; + if (jj_scan_token(RBRACE)) return true; + return false; + } + + final private boolean jj_3R_245() { + if (jj_scan_token(CATCH)) return true; + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_133()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_3R_104()) return true; + return false; + } + + final private boolean jj_3R_212() { + if (jj_scan_token(TRY)) return true; + if (jj_3R_104()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_245()) { + jj_scanpos = xsp; + break; + } + } + xsp = jj_scanpos; + if (jj_3R_246()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_218() { + if (jj_3R_214()) return true; + return false; + } + + final private boolean jj_3R_185() { + if (jj_scan_token(ENUM)) return true; + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_218()) jj_scanpos = xsp; + if (jj_3R_219()) return true; + return false; + } + + final private boolean jj_3R_211() { + if (jj_scan_token(SYNCHRONIZED)) return true; + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_3R_104()) return true; + return false; + } + + final private boolean jj_3R_244() { + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_248() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_149()) return true; + return false; + } + + final private boolean jj_3R_214() { + if (jj_scan_token(IMPLEMENTS)) return true; + if (jj_3R_149()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_248()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_210() { + if (jj_scan_token(THROW)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_271() { + if (jj_3R_284()) return true; + return false; + } + + final private boolean jj_3R_299() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_201()) return true; + return false; + } + + final private boolean jj_3R_209() { + if (jj_scan_token(RETURN)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_244()) jj_scanpos = xsp; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_247() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_149()) return true; + return false; + } + + final private boolean jj_3R_213() { + if (jj_scan_token(EXTENDS)) return true; + if (jj_3R_149()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_247()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_208() { + if (jj_scan_token(CONTINUE)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(72)) jj_scanpos = xsp; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_178() { + if (jj_scan_token(INTERFACE)) return true; + return false; + } + + final private boolean jj_3R_207() { + if (jj_scan_token(BREAK)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(72)) jj_scanpos = xsp; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_181() { + if (jj_3R_214()) return true; + return false; + } + + final private boolean jj_3R_180() { + if (jj_3R_213()) return true; + return false; + } + + final private boolean jj_3R_179() { + if (jj_3R_97()) return true; + return false; + } + + final private boolean jj_3R_284() { + if (jj_3R_296()) return true; + return false; + } + + final private boolean jj_3R_270() { + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_130() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(16)) { + jj_scanpos = xsp; + if (jj_3R_178()) return true; + } + if (jj_scan_token(IDENTIFIER)) return true; + xsp = jj_scanpos; + if (jj_3R_179()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_180()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_181()) jj_scanpos = xsp; + if (jj_3R_182()) return true; + return false; + } + + final private boolean jj_3_44() { + if (jj_3R_50()) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + return false; + } + + final private boolean jj_3R_296() { + if (jj_3R_201()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_299()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_241() { + if (jj_scan_token(ELSE)) return true; + if (jj_3R_129()) return true; + return false; + } + + final private boolean jj_3R_295() { + if (jj_3R_296()) return true; + return false; + } + + final private boolean jj_3_43() { + if (jj_3R_50()) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(COLON)) return true; + return false; + } + + final private boolean jj_3R_294() { + if (jj_3R_128()) return true; + return false; + } + + final private boolean jj_3R_283() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_294()) { + jj_scanpos = xsp; + if (jj_3R_295()) return true; + } + return false; + } + + final private boolean jj_3R_269() { + if (jj_3R_283()) return true; + return false; + } + + final private boolean jj_3R_243() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_269()) jj_scanpos = xsp; + if (jj_scan_token(SEMICOLON)) return true; + xsp = jj_scanpos; + if (jj_3R_270()) jj_scanpos = xsp; + if (jj_scan_token(SEMICOLON)) return true; + xsp = jj_scanpos; + if (jj_3R_271()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_242() { + if (jj_3R_50()) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(COLON)) return true; + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_54() { + if (jj_scan_token(THROWS)) return true; + if (jj_3R_99()) return true; + return false; + } + + final private boolean jj_3R_206() { + if (jj_scan_token(FOR)) return true; + if (jj_scan_token(LPAREN)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_242()) { + jj_scanpos = xsp; + if (jj_3R_243()) return true; + } + if (jj_scan_token(RPAREN)) return true; + if (jj_3R_129()) return true; + return false; + } + + final private boolean jj_3R_69() { + if (jj_3R_102()) return true; + return false; + } + + final private boolean jj_3R_205() { + if (jj_scan_token(DO)) return true; + if (jj_3R_129()) return true; + if (jj_scan_token(WHILE)) return true; + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_68() { + if (jj_scan_token(STRICTFP)) return true; + return false; + } + + final private boolean jj_3R_67() { + if (jj_scan_token(VOLATILE)) return true; + return false; + } + + final private boolean jj_3R_66() { + if (jj_scan_token(TRANSIENT)) return true; + return false; + } + + final private boolean jj_3R_204() { + if (jj_scan_token(WHILE)) return true; + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_3R_129()) return true; + return false; + } + + final private boolean jj_3R_65() { + if (jj_scan_token(NATIVE)) return true; + return false; + } + + final private boolean jj_3R_64() { + if (jj_scan_token(SYNCHRONIZED)) return true; + return false; + } + + final private boolean jj_3R_63() { + if (jj_scan_token(ABSTRACT)) return true; + return false; + } + + final private boolean jj_3R_268() { + if (jj_3R_49()) return true; + return false; + } + + final private boolean jj_3R_203() { + if (jj_scan_token(IF)) return true; + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_3R_129()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_241()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_62() { + if (jj_scan_token(FINAL)) return true; + return false; + } + + final private boolean jj_3R_61() { + if (jj_scan_token(PRIVATE)) return true; + return false; + } + + final private boolean jj_3R_162() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_161()) return true; + return false; + } + + final private boolean jj_3R_60() { + if (jj_scan_token(PROTECTED)) return true; + return false; + } + + final private boolean jj_3R_59() { + if (jj_scan_token(STATIC)) return true; + return false; + } + + final private boolean jj_3R_58() { + if (jj_scan_token(PUBLIC)) return true; + return false; + } + + final private boolean jj_3R_282() { + if (jj_scan_token(_DEFAULT)) return true; + if (jj_scan_token(COLON)) return true; + return false; + } + + final private boolean jj_3_6() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_58()) { + jj_scanpos = xsp; + if (jj_3R_59()) { + jj_scanpos = xsp; + if (jj_3R_60()) { + jj_scanpos = xsp; + if (jj_3R_61()) { + jj_scanpos = xsp; + if (jj_3R_62()) { + jj_scanpos = xsp; + if (jj_3R_63()) { + jj_scanpos = xsp; + if (jj_3R_64()) { + jj_scanpos = xsp; + if (jj_3R_65()) { + jj_scanpos = xsp; + if (jj_3R_66()) { + jj_scanpos = xsp; + if (jj_3R_67()) { + jj_scanpos = xsp; + if (jj_3R_68()) { + jj_scanpos = xsp; + if (jj_3R_69()) return true; + } + } + } + } + } + } + } + } + } + } + } + return false; + } + + final private boolean jj_3R_281() { + if (jj_scan_token(CASE)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(COLON)) return true; + return false; + } + + final private boolean jj_3R_267() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_281()) { + jj_scanpos = xsp; + if (jj_3R_282()) return true; + } + return false; + } + + final private boolean jj_3R_50() { + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_6()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_240() { + if (jj_3R_267()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_268()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3_42() { + if (jj_3R_90()) return true; + if (jj_3R_79()) return true; + return false; + } + + final private boolean jj_3R_202() { + if (jj_scan_token(SWITCH)) return true; + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_scan_token(LBRACE)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_240()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(RBRACE)) return true; + return false; + } + + final private boolean jj_3R_239() { + if (jj_3R_266()) return true; + return false; + } + + final private boolean jj_3R_57() { + if (jj_3R_102()) return true; + return false; + } + + final private boolean jj_3R_52() { + if (jj_3R_86()) return true; + return false; + } + + final private boolean jj_3R_238() { + if (jj_3R_265()) return true; + return false; + } + + final private boolean jj_3_5() { + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_57()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(PACKAGE)) return true; + return false; + } + + final private boolean jj_3R_237() { + if (jj_3R_264()) return true; + return false; + } + + final private boolean jj_3R_201() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_236()) { + jj_scanpos = xsp; + if (jj_3R_237()) { + jj_scanpos = xsp; + if (jj_3R_238()) { + jj_scanpos = xsp; + if (jj_3R_239()) return true; + } + } + } + return false; + } + + final private boolean jj_3R_236() { + if (jj_3R_263()) return true; + return false; + } + + final private boolean jj_3R_200() { + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3_41() { + if (jj_3R_50()) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + return false; + } + + final private boolean jj_3R_128() { + if (jj_3R_50()) return true; + if (jj_3R_72()) return true; + if (jj_3R_161()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_162()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_51() { + if (jj_3R_97()) return true; + return false; + } + + final private boolean jj_3R_235() { + if (jj_scan_token(COLON)) return true; + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_96() { + if (jj_3R_130()) return true; + return false; + } + + final private boolean jj_3R_95() { + if (jj_3R_129()) return true; + return false; + } + + final private boolean jj_3_4() { + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_94() { + if (jj_3R_128()) return true; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_49() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_94()) { + jj_scanpos = xsp; + if (jj_3R_95()) { + jj_scanpos = xsp; + if (jj_3R_96()) return true; + } + } + return false; + } + + final private boolean jj_3R_146() { + if (jj_3R_49()) return true; + return false; + } + + final private boolean jj_3_3() { + if (jj_3R_55()) return true; + return false; + } + + final private boolean jj_3R_104() { + if (jj_scan_token(LBRACE)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_146()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(RBRACE)) return true; + return false; + } + + final private boolean jj_3_2() { + if (jj_3R_50()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_51()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_52()) jj_scanpos = xsp; + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_3R_53()) return true; + xsp = jj_scanpos; + if (jj_3R_54()) jj_scanpos = xsp; + if (jj_scan_token(LBRACE)) return true; + return false; + } + + final private boolean jj_3R_89() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(COLON)) return true; + if (jj_3R_129()) return true; + return false; + } + + final private boolean jj_3_1() { + if (jj_3R_49()) return true; + return false; + } + + final private boolean jj_3R_199() { + if (jj_scan_token(ASSERT)) return true; + if (jj_3R_56()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_235()) jj_scanpos = xsp; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_177() { + if (jj_3R_212()) return true; + return false; + } + + final private boolean jj_3R_176() { + if (jj_3R_211()) return true; + return false; + } + + final private boolean jj_3_38() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_175() { + if (jj_3R_210()) return true; + return false; + } + + final private boolean jj_3R_174() { + if (jj_3R_209()) return true; + return false; + } + + final private boolean jj_3R_173() { + if (jj_3R_208()) return true; + return false; + } + + final private boolean jj_3R_172() { + if (jj_3R_207()) return true; + return false; + } + + final private boolean jj_3R_171() { + if (jj_3R_206()) return true; + return false; + } + + final private boolean jj_3R_170() { + if (jj_3R_205()) return true; + return false; + } + + final private boolean jj_3R_169() { + if (jj_3R_204()) return true; + return false; + } + + final private boolean jj_3R_168() { + if (jj_3R_203()) return true; + return false; + } + + final private boolean jj_3R_167() { + if (jj_3R_202()) return true; + return false; + } + + final private boolean jj_3R_166() { + if (jj_3R_201()) return true; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_165() { + if (jj_3R_200()) return true; + return false; + } + + final private boolean jj_3R_164() { + if (jj_3R_104()) return true; + return false; + } + + final private boolean jj_3R_163() { + if (jj_3R_199()) return true; + return false; + } + + final private boolean jj_3R_260() { + if (jj_3R_78()) return true; + return false; + } + + final private boolean jj_3_40() { + if (jj_3R_89()) return true; + return false; + } + + final private boolean jj_3R_129() { + Token xsp; + xsp = jj_scanpos; + if (jj_3_40()) { + jj_scanpos = xsp; + if (jj_3R_163()) { + jj_scanpos = xsp; + if (jj_3R_164()) { + jj_scanpos = xsp; + if (jj_3R_165()) { + jj_scanpos = xsp; + if (jj_3R_166()) { + jj_scanpos = xsp; + if (jj_3R_167()) { + jj_scanpos = xsp; + if (jj_3R_168()) { + jj_scanpos = xsp; + if (jj_3R_169()) { + jj_scanpos = xsp; + if (jj_3R_170()) { + jj_scanpos = xsp; + if (jj_3R_171()) { + jj_scanpos = xsp; + if (jj_3R_172()) { + jj_scanpos = xsp; + if (jj_3R_173()) { + jj_scanpos = xsp; + if (jj_3R_174()) { + jj_scanpos = xsp; + if (jj_3R_175()) { + jj_scanpos = xsp; + if (jj_3R_176()) { + jj_scanpos = xsp; + if (jj_3R_177()) + return true; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return false; + } + + final private boolean jj_3R_279() { + if (jj_3R_182()) return true; + return false; + } + + final private boolean jj_3R_291() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_278() { + Token xsp; + if (jj_3R_291()) return true; + while (true) { + xsp = jj_scanpos; + if (jj_3R_291()) { + jj_scanpos = xsp; + break; + } + } + if (jj_3R_147()) return true; + return false; + } + + final private boolean jj_3_37() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3_39() { + Token xsp; + if (jj_3_37()) return true; + while (true) { + xsp = jj_scanpos; + if (jj_3_37()) { + jj_scanpos = xsp; + break; + } + } + while (true) { + xsp = jj_scanpos; + if (jj_3_38()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_259() { + Token xsp; + xsp = jj_scanpos; + if (jj_3_39()) { + jj_scanpos = xsp; + if (jj_3R_278()) return true; + } + return false; + } + + final private boolean jj_3R_262() { + if (jj_3R_109()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_279()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_232() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_261() { + if (jj_3R_259()) return true; + return false; + } + + final private boolean jj_3R_123() { + if (jj_scan_token(NEW)) return true; + if (jj_3R_149()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_260()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_261()) { + jj_scanpos = xsp; + if (jj_3R_262()) return true; + } + return false; + } + + final private boolean jj_3R_87() { + Token xsp; + xsp = jj_scanpos; + if (jj_3_36()) { + jj_scanpos = xsp; + if (jj_3R_123()) return true; + } + return false; + } + + final private boolean jj_3_36() { + if (jj_scan_token(NEW)) return true; + if (jj_3R_83()) return true; + if (jj_3R_259()) return true; + return false; + } + + final private boolean jj_3R_148() { + if (jj_3R_195()) return true; + return false; + } + + final private boolean jj_3R_195() { + if (jj_3R_56()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_232()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_109() { + if (jj_scan_token(LPAREN)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_148()) jj_scanpos = xsp; + if (jj_scan_token(RPAREN)) return true; + return false; + } + + final private boolean jj_3R_258() { + if (jj_scan_token(NULL)) return true; + return false; + } + + final private boolean jj_3R_257() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(56)) { + jj_scanpos = xsp; + if (jj_scan_token(25)) return true; + } + return false; + } + + final private boolean jj_3R_234() { + if (jj_3R_258()) return true; + return false; + } + + final private boolean jj_3R_233() { + if (jj_3R_257()) return true; + return false; + } + + final private boolean jj_3R_196() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(61)) { + jj_scanpos = xsp; + if (jj_scan_token(65)) { + jj_scanpos = xsp; + if (jj_scan_token(70)) { + jj_scanpos = xsp; + if (jj_scan_token(71)) { + jj_scanpos = xsp; + if (jj_3R_233()) { + jj_scanpos = xsp; + if (jj_3R_234()) return true; + } + } + } + } + } + return false; + } + + final private boolean jj_3R_152() { + if (jj_3R_196()) return true; + return false; + } + + final private boolean jj_3R_121() { + if (jj_3R_109()) return true; + return false; + } + + final private boolean jj_3R_120() { + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(IDENTIFIER)) return true; + return false; + } + + final private boolean jj_3_33() { + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(THIS)) return true; + return false; + } + + final private boolean jj_3R_119() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3_32() { + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(SUPER)) return true; + if (jj_scan_token(DOT)) return true; + return false; + } + + final private boolean jj_3_35() { + if (jj_3R_88()) return true; + return false; + } + + final private boolean jj_3_34() { + if (jj_scan_token(DOT)) return true; + if (jj_3R_87()) return true; + return false; + } + + final private boolean jj_3R_118() { + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(THIS)) return true; + return false; + } + + final private boolean jj_3_31() { + if (jj_3R_86()) return true; + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(CLASS)) return true; + return false; + } + + final private boolean jj_3R_117() { + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(SUPER)) return true; + return false; + } + + final private boolean jj_3R_84() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_117()) { + jj_scanpos = xsp; + if (jj_3R_118()) { + jj_scanpos = xsp; + if (jj_3_34()) { + jj_scanpos = xsp; + if (jj_3_35()) { + jj_scanpos = xsp; + if (jj_3R_119()) { + jj_scanpos = xsp; + if (jj_3R_120()) { + jj_scanpos = xsp; + if (jj_3R_121()) return true; + } + } + } + } + } + } + return false; + } + + final private boolean jj_3R_85() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(DOT)) return true; + return false; + } + + final private boolean jj_3R_159() { + if (jj_3R_91()) return true; + return false; + } + + final private boolean jj_3_30() { + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_85()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(THIS)) return true; + return false; + } + + final private boolean jj_3R_158() { + if (jj_3R_86()) return true; + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(CLASS)) return true; + return false; + } + + final private boolean jj_3R_157() { + if (jj_3R_87()) return true; + return false; + } + + final private boolean jj_3R_156() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RPAREN)) return true; + return false; + } + + final private boolean jj_3_29() { + if (jj_3R_84()) return true; + return false; + } + + final private boolean jj_3R_155() { + if (jj_scan_token(SUPER)) return true; + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(IDENTIFIER)) return true; + return false; + } + + final private boolean jj_3R_197() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(DOT)) return true; + return false; + } + + final private boolean jj_3R_154() { + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_197()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(THIS)) return true; + return false; + } + + final private boolean jj_3R_124() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_153()) { + jj_scanpos = xsp; + if (jj_3R_154()) { + jj_scanpos = xsp; + if (jj_3R_155()) { + jj_scanpos = xsp; + if (jj_3R_156()) { + jj_scanpos = xsp; + if (jj_3R_157()) { + jj_scanpos = xsp; + if (jj_3R_158()) { + jj_scanpos = xsp; + if (jj_3R_159()) return true; + } + } + } + } + } + } + return false; + } + + final private boolean jj_3R_153() { + if (jj_3R_196()) return true; + return false; + } + + final private boolean jj_3R_88() { + if (jj_scan_token(DOT)) return true; + if (jj_3R_78()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + return false; + } + + final private boolean jj_3R_280() { + if (jj_3R_293()) return true; + return false; + } + + final private boolean jj_3_28() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_83()) return true; + return false; + } + + final private boolean jj_3R_90() { + if (jj_3R_124()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_29()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_319() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_3R_313()) return true; + return false; + } + + final private boolean jj_3R_318() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_3R_307()) return true; + return false; + } + + final private boolean jj_3R_317() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_318()) { + jj_scanpos = xsp; + if (jj_3R_319()) return true; + } + return false; + } + + final private boolean jj_3R_293() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(97)) { + jj_scanpos = xsp; + if (jj_scan_token(98)) return true; + } + return false; + } + + final private boolean jj_3_27() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(LBRACKET)) return true; + return false; + } + + final private boolean jj_3R_266() { + if (jj_3R_90()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_280()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_116() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(RPAREN)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(88)) { + jj_scanpos = xsp; + if (jj_scan_token(87)) { + jj_scanpos = xsp; + if (jj_scan_token(75)) { + jj_scanpos = xsp; + if (jj_scan_token(72)) { + jj_scanpos = xsp; + if (jj_scan_token(52)) { + jj_scanpos = xsp; + if (jj_scan_token(49)) { + jj_scanpos = xsp; + if (jj_scan_token(39)) { + jj_scanpos = xsp; + if (jj_3R_152()) return true; + } + } + } + } + } + } + } + return false; + } + + final private boolean jj_3R_115() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_82() { + Token xsp; + xsp = jj_scanpos; + if (jj_3_26()) { + jj_scanpos = xsp; + if (jj_3R_115()) { + jj_scanpos = xsp; + if (jj_3R_116()) return true; + } + } + return false; + } + + final private boolean jj_3_26() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_83()) return true; + return false; + } + + final private boolean jj_3_25() { + if (jj_3R_82()) return true; + return false; + } + + final private boolean jj_3_24() { + if (jj_3R_81()) return true; + return false; + } + + final private boolean jj_3R_316() { + if (jj_3R_266()) return true; + return false; + } + + final private boolean jj_3R_315() { + if (jj_3R_317()) return true; + return false; + } + + final private boolean jj_3R_314() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(88)) { + jj_scanpos = xsp; + if (jj_scan_token(87)) return true; + } + if (jj_3R_307()) return true; + return false; + } + + final private boolean jj_3R_313() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_314()) { + jj_scanpos = xsp; + if (jj_3R_315()) { + jj_scanpos = xsp; + if (jj_3R_316()) return true; + } + } + return false; + } + + final private boolean jj_3R_264() { + if (jj_scan_token(DECR)) return true; + if (jj_3R_90()) return true; + return false; + } + + final private boolean jj_3R_306() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(99)) { + jj_scanpos = xsp; + if (jj_scan_token(100)) return true; + } + if (jj_3R_305()) return true; + return false; + } + + final private boolean jj_3R_308() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(101)) { + jj_scanpos = xsp; + if (jj_scan_token(102)) { + jj_scanpos = xsp; + if (jj_scan_token(106)) return true; + } + } + if (jj_3R_307()) return true; + return false; + } + + final private boolean jj_3_23() { + if (jj_3R_80()) return true; + return false; + } + + final private boolean jj_3R_263() { + if (jj_scan_token(INCR)) return true; + if (jj_3R_90()) return true; + return false; + } + + final private boolean jj_3R_312() { + if (jj_3R_313()) return true; + return false; + } + + final private boolean jj_3_22() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(107)) { + jj_scanpos = xsp; + if (jj_3_23()) { + jj_scanpos = xsp; + if (jj_3_24()) return true; + } + } + if (jj_3R_304()) return true; + return false; + } + + final private boolean jj_3R_311() { + if (jj_3R_264()) return true; + return false; + } + + final private boolean jj_3R_310() { + if (jj_3R_263()) return true; + return false; + } + + final private boolean jj_3R_309() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(99)) { + jj_scanpos = xsp; + if (jj_scan_token(100)) return true; + } + if (jj_3R_307()) return true; + return false; + } + + final private boolean jj_3R_307() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_309()) { + jj_scanpos = xsp; + if (jj_3R_310()) { + jj_scanpos = xsp; + if (jj_3R_311()) { + jj_scanpos = xsp; + if (jj_3R_312()) return true; + } + } + } + return false; + } + + final private boolean jj_3R_303() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(86)) { + jj_scanpos = xsp; + if (jj_scan_token(122)) { + jj_scanpos = xsp; + if (jj_scan_token(92)) { + jj_scanpos = xsp; + if (jj_scan_token(93)) return true; + } + } + } + if (jj_3R_302()) return true; + return false; + } + + final private boolean jj_3R_301() { + if (jj_scan_token(INSTANCEOF)) return true; + if (jj_3R_72()) return true; + return false; + } + + final private boolean jj_3R_305() { + if (jj_3R_307()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_308()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_298() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(91)) { + jj_scanpos = xsp; + if (jj_scan_token(94)) return true; + } + if (jj_3R_297()) return true; + return false; + } + + final private boolean jj_3R_304() { + if (jj_3R_305()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_306()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_302() { + if (jj_3R_304()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_22()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_288() { + if (jj_scan_token(BIT_AND)) return true; + if (jj_3R_287()) return true; + return false; + } + + final private boolean jj_3R_300() { + if (jj_3R_302()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_303()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_254() { + if (jj_scan_token(BIT_OR)) return true; + if (jj_3R_253()) return true; + return false; + } + + final private boolean jj_3R_297() { + if (jj_3R_300()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_301()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_274() { + if (jj_scan_token(XOR)) return true; + if (jj_3R_273()) return true; + return false; + } + + final private boolean jj_3R_230() { + if (jj_scan_token(SC_AND)) return true; + if (jj_3R_229()) return true; + return false; + } + + final private boolean jj_3R_287() { + if (jj_3R_297()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_298()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_190() { + if (jj_scan_token(SC_OR)) return true; + if (jj_3R_189()) return true; + return false; + } + + final private boolean jj_3R_273() { + if (jj_3R_287()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_288()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_142() { + if (jj_scan_token(HOOK)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(COLON)) return true; + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_253() { + if (jj_3R_273()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_274()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_229() { + if (jj_3R_253()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_254()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_189() { + if (jj_3R_229()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_230()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_141() { + if (jj_3R_189()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_190()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_101() { + if (jj_3R_141()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_142()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_265() { + if (jj_3R_90()) return true; + if (jj_3R_79()) return true; + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_79() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(85)) { + jj_scanpos = xsp; + if (jj_scan_token(110)) { + jj_scanpos = xsp; + if (jj_scan_token(111)) { + jj_scanpos = xsp; + if (jj_scan_token(115)) { + jj_scanpos = xsp; + if (jj_scan_token(108)) { + jj_scanpos = xsp; + if (jj_scan_token(109)) { + jj_scanpos = xsp; + if (jj_scan_token(116)) { + jj_scanpos = xsp; + if (jj_scan_token(117)) { + jj_scanpos = xsp; + if (jj_scan_token(118)) { + jj_scanpos = xsp; + if (jj_scan_token(112)) { + jj_scanpos = xsp; + if (jj_scan_token(114)) { + jj_scanpos = xsp; + if (jj_scan_token(113)) + return true; + } + } + } + } + } + } + } + } + } + } + } + return false; + } + + final private boolean jj_3_21() { + if (jj_3R_79()) return true; + if (jj_3R_56()) return true; + return false; + } + + public JavaParserTokenManager token_source; + + JavaCharStream jj_input_stream; + + public Token token, jj_nt; + + private int jj_ntk; + + private Token jj_scanpos, jj_lastpos; + + private int jj_la; + + public boolean lookingAhead = false; + + private boolean jj_semLA; + + private final boolean parseMethodBody; + + public JavaParser(java.io.InputStream stream) { + this(stream, null, false); + } + + public JavaParser(java.io.InputStream stream, boolean parseMethodBody) { + this(stream, null, parseMethodBody); + } + + public JavaParser(java.io.InputStream stream, String encoding) { + this(stream, encoding, false); + } + + public JavaParser(java.io.InputStream stream, String encoding, boolean parseMethodBody) { + this.parseMethodBody = parseMethodBody; + try { + jj_input_stream = new JavaCharStream(stream, encoding, 1, 1); + } catch (java.io.UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + token_source = new JavaParserTokenManager(jj_input_stream); + token = new Token(); + jj_ntk = -1; + } + + public void ReInit(java.io.InputStream stream) { + ReInit(stream, null); + } + + public void ReInit(java.io.InputStream stream, String encoding) { + try { + jj_input_stream.ReInit(stream, encoding, 1, 1); + } catch (java.io.UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + token_source.ReInit(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + } + + public JavaParser(java.io.Reader stream) { + this(stream, false); + } + + public JavaParser(java.io.Reader stream, boolean parseMethodBody) { + this.parseMethodBody=parseMethodBody; + jj_input_stream = new JavaCharStream(stream, 1, 1); + token_source = new JavaParserTokenManager(jj_input_stream); + token = new Token(); + jj_ntk = -1; + } + + public void ReInit(java.io.Reader stream) { + jj_input_stream.ReInit(stream, 1, 1); + token_source.ReInit(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + } + + public JavaParser(JavaParserTokenManager tm, boolean parseMethodBody) { + this.parseMethodBody =parseMethodBody; + token_source = tm; + token = new Token(); + jj_ntk = -1; + } + + public void ReInit(JavaParserTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + } + + final private Token jj_consume_token(int kind) throws ParseException { + Token oldToken; + if ((oldToken = token).next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + if (token.kind == kind) { + return token; + } + token = oldToken; + throw generateParseException(); + } + + static private final class LookaheadSuccess extends java.lang.Error { + } + + final private LookaheadSuccess jj_ls = new LookaheadSuccess(); + + final private boolean jj_scan_token(int kind) { + if (jj_scanpos == jj_lastpos) { + jj_la--; + if (jj_scanpos.next == null) { + jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken(); + } else { + jj_lastpos = jj_scanpos = jj_scanpos.next; + } + } else { + jj_scanpos = jj_scanpos.next; + } + if (jj_scanpos.kind != kind) return true; + if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls; + return false; + } + + final public Token getNextToken() { + if (token.next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + return token; + } + + final public Token getToken(int index) { + Token t = lookingAhead ? jj_scanpos : token; + for (int i = 0; i < index; i++) { + if (t.next != null) t = t.next; + else t = t.next = token_source.getNextToken(); + } + return t; + } + + final private int jj_ntk() { + if ((jj_nt = token.next) == null) + return (jj_ntk = (token.next = token_source.getNextToken()).kind); + else + return (jj_ntk = jj_nt.kind); + } + + public ParseException generateParseException() { + Token errortok = token.next; + int line = errortok.beginLine, column = errortok.beginColumn; + String mess = (errortok.kind == 0) ? tokenImage[0] : errortok.image; + return new ParseException("Unable to parse Java code near token: " + mess, line, column); + } + + final public void enable_tracing() { + } + + final public void disable_tracing() { + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaParserConstants.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaParserConstants.java new file mode 100644 index 0000000..a0b5820 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaParserConstants.java @@ -0,0 +1,404 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree&JavaCC: Do not edit this line. JavaParserConstants.java */ + +package org.nuiton.jaxx.compiler.java.parser; + +public interface JavaParserConstants { + + int EOF = 0; + + int WHITE_SPACE = 3; + + int SINGLE_LINE_COMMENT = 4; + + int FORMAL_COMMENT = 5; + + int MULTI_LINE_COMMENT = 6; + + int ABSTRACT = 8; + + int ASSERT = 9; + + int BOOLEAN = 10; + + int BREAK = 11; + + int BYTE = 12; + + int CASE = 13; + + int CATCH = 14; + + int CHAR = 15; + + int CLASS = 16; + + int CONST = 17; + + int CONTINUE = 18; + + int _DEFAULT = 19; + + int DO = 20; + + int DOUBLE = 21; + + int ELSE = 22; + + int ENUM = 23; + + int EXTENDS = 24; + + int FALSE = 25; + + int FINAL = 26; + + int FINALLY = 27; + + int FLOAT = 28; + + int FOR = 29; + + int GOTO = 30; + + int IF = 31; + + int IMPLEMENTS = 32; + + int IMPORT = 33; + + int INSTANCEOF = 34; + + int INT = 35; + + int INTERFACE = 36; + + int LONG = 37; + + int NATIVE = 38; + + int NEW = 39; + + int NULL = 40; + + int PACKAGE = 41; + + int PRIVATE = 42; + + int PROTECTED = 43; + + int PUBLIC = 44; + + int RETURN = 45; + + int SHORT = 46; + + int STATIC = 47; + + int STRICTFP = 48; + + int SUPER = 49; + + int SWITCH = 50; + + int SYNCHRONIZED = 51; + + int THIS = 52; + + int THROW = 53; + + int THROWS = 54; + + int TRANSIENT = 55; + + int TRUE = 56; + + int TRY = 57; + + int VOID = 58; + + int VOLATILE = 59; + + int WHILE = 60; + + int INTEGER_LITERAL = 61; + + int DECIMAL_LITERAL = 62; + + int HEX_LITERAL = 63; + + int OCTAL_LITERAL = 64; + + int FLOATING_POINT_LITERAL = 65; + + int DECIMAL_FLOATING_POINT_LITERAL = 66; + + int DECIMAL_EXPONENT = 67; + + int HEXADECIMAL_FLOATING_POINT_LITERAL = 68; + + int HEXADECIMAL_EXPONENT = 69; + + int CHARACTER_LITERAL = 70; + + int STRING_LITERAL = 71; + + int IDENTIFIER = 72; + + int LETTER = 73; + + int PART_LETTER = 74; + + int LPAREN = 75; + + int RPAREN = 76; + + int LBRACE = 77; + + int RBRACE = 78; + + int LBRACKET = 79; + + int RBRACKET = 80; + + int SEMICOLON = 81; + + int COMMA = 82; + + int DOT = 83; + + int AT = 84; + + int ASSIGN = 85; + + int LT = 86; + + int BANG = 87; + + int TILDE = 88; + + int HOOK = 89; + + int COLON = 90; + + int EQ = 91; + + int LE = 92; + + int GE = 93; + + int NE = 94; + + int SC_OR = 95; + + int SC_AND = 96; + + int INCR = 97; + + int DECR = 98; + + int PLUS = 99; + + int MINUS = 100; + + int STAR = 101; + + int SLASH = 102; + + int BIT_AND = 103; + + int BIT_OR = 104; + + int XOR = 105; + + int REM = 106; + + int LSHIFT = 107; + + int PLUSASSIGN = 108; + + int MINUSASSIGN = 109; + + int STARASSIGN = 110; + + int SLASHASSIGN = 111; + + int ANDASSIGN = 112; + + int ORASSIGN = 113; + + int XORASSIGN = 114; + + int REMASSIGN = 115; + + int LSHIFTASSIGN = 116; + + int RSIGNEDSHIFTASSIGN = 117; + + int RUNSIGNEDSHIFTASSIGN = 118; + + int ELLIPSIS = 119; + + int RUNSIGNEDSHIFT = 120; + + int RSIGNEDSHIFT = 121; + + int GT = 122; + + int STUFF_TO_IGNORE = 124; + + int DEFAULT = 0; + + int IN_FORMAL_COMMENT = 1; + + int IN_MULTI_LINE_COMMENT = 2; + + String[] tokenImage = { + "<EOF>", + "<token of kind 1>", + "\"/*\"", + "<WHITE_SPACE>", + "<SINGLE_LINE_COMMENT>", + "\"*/\"", + "\"*/\"", + "<token of kind 7>", + "\"abstract\"", + "\"assert\"", + "\"boolean\"", + "\"break\"", + "\"byte\"", + "\"case\"", + "\"catch\"", + "\"char\"", + "\"class\"", + "\"const\"", + "\"continue\"", + "\"default\"", + "\"do\"", + "\"double\"", + "\"else\"", + "\"enum\"", + "\"extends\"", + "\"false\"", + "\"final\"", + "\"finally\"", + "\"float\"", + "\"for\"", + "\"goto\"", + "\"if\"", + "\"implements\"", + "\"import\"", + "\"instanceof\"", + "\"int\"", + "\"interface\"", + "\"long\"", + "\"native\"", + "\"new\"", + "\"null\"", + "\"package\"", + "\"private\"", + "\"protected\"", + "\"public\"", + "\"return\"", + "\"short\"", + "\"static\"", + "\"strictfp\"", + "\"super\"", + "\"switch\"", + "\"synchronized\"", + "\"this\"", + "\"throw\"", + "\"throws\"", + "\"transient\"", + "\"true\"", + "\"try\"", + "\"void\"", + "\"volatile\"", + "\"while\"", + "<INTEGER_LITERAL>", + "<DECIMAL_LITERAL>", + "<HEX_LITERAL>", + "<OCTAL_LITERAL>", + "<FLOATING_POINT_LITERAL>", + "<DECIMAL_FLOATING_POINT_LITERAL>", + "<DECIMAL_EXPONENT>", + "<HEXADECIMAL_FLOATING_POINT_LITERAL>", + "<HEXADECIMAL_EXPONENT>", + "<CHARACTER_LITERAL>", + "<STRING_LITERAL>", + "<IDENTIFIER>", + "<LETTER>", + "<PART_LETTER>", + "\"(\"", + "\")\"", + "\"{\"", + "\"}\"", + "\"[\"", + "\"]\"", + "\";\"", + "\",\"", + "\".\"", + "\"@\"", + "\"=\"", + "\"<\"", + "\"!\"", + "\"~\"", + "\"?\"", + "\":\"", + "\"==\"", + "\"<=\"", + "\">=\"", + "\"!=\"", + "\"||\"", + "\"&&\"", + "\"++\"", + "\"--\"", + "\"+\"", + "\"-\"", + "\"*\"", + "\"/\"", + "\"&\"", + "\"|\"", + "\"^\"", + "\"%\"", + "\"<<\"", + "\"+=\"", + "\"-=\"", + "\"*=\"", + "\"/=\"", + "\"&=\"", + "\"|=\"", + "\"^=\"", + "\"%=\"", + "\"<<=\"", + "\">>=\"", + "\">>>=\"", + "\"...\"", + "\">>>\"", + "\">>\"", + "\">\"", + "\"\\u001a\"", + "<STUFF_TO_IGNORE>" + }; + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaParserTokenManager.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaParserTokenManager.java new file mode 100644 index 0000000..c19f7a3 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaParserTokenManager.java @@ -0,0 +1,2156 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree&JavaCC: Do not edit this line. JavaParserTokenManager.java */ + +package org.nuiton.jaxx.compiler.java.parser; + +import java.io.IOException; +import java.io.PrintStream; + +public class JavaParserTokenManager implements JavaParserConstants { + public PrintStream debugStream = System.out; + + public void setDebugStream(PrintStream ds) { + debugStream = ds; + } + + private int jjStopStringLiteralDfa_0(int pos, long active0, long active1) { + switch (pos) { + case 0: + if ((active0 & 0x4L) != 0L || (active1 & 0x804000000000L) != 0L) + return 48; + if ((active1 & 0x80000000080000L) != 0L) + return 5; + if ((active0 & 0x1fffffffffffff00L) != 0L) { + jjmatchedKind = 72; + return 29; + } + return -1; + case 1: + if ((active0 & 0x4L) != 0L) + return 46; + if ((active0 & 0x1fffffff7fcfff00L) != 0L) { + if (jjmatchedPos != 1) { + jjmatchedKind = 72; + jjmatchedPos = 1; + } + return 29; + } + if ((active0 & 0x80300000L) != 0L) + return 29; + return -1; + case 2: + if ((active0 & 0x1dffff675fefff00L) != 0L) { + if (jjmatchedPos != 2) { + jjmatchedKind = 72; + jjmatchedPos = 2; + } + return 29; + } + if ((active0 & 0x200009820000000L) != 0L) + return 29; + return -1; + case 3: + if ((active0 & 0x18effe571f2f4f00L) != 0L) { + jjmatchedKind = 72; + jjmatchedPos = 3; + return 29; + } + if ((active0 & 0x510012040c0b000L) != 0L) + return 29; + return -1; + case 4: + if ((active0 & 0x88dbe57012c0700L) != 0L) { + if (jjmatchedPos != 4) { + jjmatchedKind = 72; + jjmatchedPos = 4; + } + return 29; + } + if ((active0 & 0x106240001e034800L) != 0L) + return 29; + return -1; + case 5: + if ((active0 & 0x8890e15090c0500L) != 0L) { + jjmatchedKind = 72; + jjmatchedPos = 5; + return 29; + } + if ((active0 & 0x44b04200200200L) != 0L) + return 29; + return -1; + case 6: + if ((active0 & 0x889081500040100L) != 0L) { + jjmatchedKind = 72; + jjmatchedPos = 6; + return 29; + } + if ((active0 & 0x60009080400L) != 0L) + return 29; + return -1; + case 7: + if ((active0 & 0x801000000040100L) != 0L) + return 29; + if ((active0 & 0x88081500000000L) != 0L) { + jjmatchedKind = 72; + jjmatchedPos = 7; + return 29; + } + return -1; + case 8: + if ((active0 & 0x8000500000000L) != 0L) { + jjmatchedKind = 72; + jjmatchedPos = 8; + return 29; + } + if ((active0 & 0x80081000000000L) != 0L) + return 29; + return -1; + case 9: + if ((active0 & 0x8000000000000L) != 0L) { + jjmatchedKind = 72; + jjmatchedPos = 9; + return 29; + } + if ((active0 & 0x500000000L) != 0L) + return 29; + return -1; + case 10: + if ((active0 & 0x8000000000000L) != 0L) { + jjmatchedKind = 72; + jjmatchedPos = 10; + return 29; + } + return -1; + default: + return -1; + } + } + + private int jjStartNfa_0(int pos, long active0, long active1) { + return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0, active1), pos + 1); + } + + private int jjStopAtPos(int pos, int kind) { + jjmatchedKind = kind; + jjmatchedPos = pos; + return pos + 1; + } + + private int jjStartNfaWithStates_0(int pos, int kind, int state) { + jjmatchedKind = kind; + jjmatchedPos = pos; + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + return pos + 1; + } + return jjMoveNfa_0(state, pos + 1); + } + + private int jjMoveStringLiteralDfa0_0() { + switch (curChar) { + case 26: + return jjStopAtPos(0, 123); + case 33: + jjmatchedKind = 87; + return jjMoveStringLiteralDfa1_0(0x0L, 0x40000000L); + case 37: + jjmatchedKind = 106; + return jjMoveStringLiteralDfa1_0(0x0L, 0x8000000000000L); + case 38: + jjmatchedKind = 103; + return jjMoveStringLiteralDfa1_0(0x0L, 0x1000100000000L); + case 40: + return jjStopAtPos(0, 75); + case 41: + return jjStopAtPos(0, 76); + case 42: + jjmatchedKind = 101; + return jjMoveStringLiteralDfa1_0(0x0L, 0x400000000000L); + case 43: + jjmatchedKind = 99; + return jjMoveStringLiteralDfa1_0(0x0L, 0x100200000000L); + case 44: + return jjStopAtPos(0, 82); + case 45: + jjmatchedKind = 100; + return jjMoveStringLiteralDfa1_0(0x0L, 0x200400000000L); + case 46: + jjmatchedKind = 83; + return jjMoveStringLiteralDfa1_0(0x0L, 0x80000000000000L); + case 47: + jjmatchedKind = 102; + return jjMoveStringLiteralDfa1_0(0x4L, 0x800000000000L); + case 58: + return jjStopAtPos(0, 90); + case 59: + return jjStopAtPos(0, 81); + case 60: + jjmatchedKind = 86; + return jjMoveStringLiteralDfa1_0(0x0L, 0x10080010000000L); + case 61: + jjmatchedKind = 85; + return jjMoveStringLiteralDfa1_0(0x0L, 0x8000000L); + case 62: + jjmatchedKind = 122; + return jjMoveStringLiteralDfa1_0(0x0L, 0x360000020000000L); + case 63: + return jjStopAtPos(0, 89); + case 64: + return jjStopAtPos(0, 84); + case 91: + return jjStopAtPos(0, 79); + case 93: + return jjStopAtPos(0, 80); + case 94: + jjmatchedKind = 105; + return jjMoveStringLiteralDfa1_0(0x0L, 0x4000000000000L); + case 97: + return jjMoveStringLiteralDfa1_0(0x300L, 0x0L); + case 98: + return jjMoveStringLiteralDfa1_0(0x1c00L, 0x0L); + case 99: + return jjMoveStringLiteralDfa1_0(0x7e000L, 0x0L); + case 100: + return jjMoveStringLiteralDfa1_0(0x380000L, 0x0L); + case 101: + return jjMoveStringLiteralDfa1_0(0x1c00000L, 0x0L); + case 102: + return jjMoveStringLiteralDfa1_0(0x3e000000L, 0x0L); + case 103: + return jjMoveStringLiteralDfa1_0(0x40000000L, 0x0L); + case 105: + return jjMoveStringLiteralDfa1_0(0x1f80000000L, 0x0L); + case 108: + return jjMoveStringLiteralDfa1_0(0x2000000000L, 0x0L); + case 110: + return jjMoveStringLiteralDfa1_0(0x1c000000000L, 0x0L); + case 112: + return jjMoveStringLiteralDfa1_0(0x1e0000000000L, 0x0L); + case 114: + return jjMoveStringLiteralDfa1_0(0x200000000000L, 0x0L); + case 115: + return jjMoveStringLiteralDfa1_0(0xfc00000000000L, 0x0L); + case 116: + return jjMoveStringLiteralDfa1_0(0x3f0000000000000L, 0x0L); + case 118: + return jjMoveStringLiteralDfa1_0(0xc00000000000000L, 0x0L); + case 119: + return jjMoveStringLiteralDfa1_0(0x1000000000000000L, 0x0L); + case 123: + return jjStopAtPos(0, 77); + case 124: + jjmatchedKind = 104; + return jjMoveStringLiteralDfa1_0(0x0L, 0x2000080000000L); + case 125: + return jjStopAtPos(0, 78); + case 126: + return jjStopAtPos(0, 88); + default: + return jjMoveNfa_0(1, 0); + } + } + + private int jjMoveStringLiteralDfa1_0(long active0, long active1) { + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + jjStopStringLiteralDfa_0(0, active0, active1); + return 1; + } + switch (curChar) { + case 38: + if ((active1 & 0x100000000L) != 0L) + return jjStopAtPos(1, 96); + break; + case 42: + if ((active0 & 0x4L) != 0L) + return jjStartNfaWithStates_0(1, 2, 46); + break; + case 43: + if ((active1 & 0x200000000L) != 0L) + return jjStopAtPos(1, 97); + break; + case 45: + if ((active1 & 0x400000000L) != 0L) + return jjStopAtPos(1, 98); + break; + case 46: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x80000000000000L); + case 60: + if ((active1 & 0x80000000000L) != 0L) { + jjmatchedKind = 107; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x10000000000000L); + case 61: + if ((active1 & 0x8000000L) != 0L) + return jjStopAtPos(1, 91); + else if ((active1 & 0x10000000L) != 0L) + return jjStopAtPos(1, 92); + else if ((active1 & 0x20000000L) != 0L) + return jjStopAtPos(1, 93); + else if ((active1 & 0x40000000L) != 0L) + return jjStopAtPos(1, 94); + else if ((active1 & 0x100000000000L) != 0L) + return jjStopAtPos(1, 108); + else if ((active1 & 0x200000000000L) != 0L) + return jjStopAtPos(1, 109); + else if ((active1 & 0x400000000000L) != 0L) + return jjStopAtPos(1, 110); + else if ((active1 & 0x800000000000L) != 0L) + return jjStopAtPos(1, 111); + else if ((active1 & 0x1000000000000L) != 0L) + return jjStopAtPos(1, 112); + else if ((active1 & 0x2000000000000L) != 0L) + return jjStopAtPos(1, 113); + else if ((active1 & 0x4000000000000L) != 0L) + return jjStopAtPos(1, 114); + else if ((active1 & 0x8000000000000L) != 0L) + return jjStopAtPos(1, 115); + break; + case 62: + if ((active1 & 0x200000000000000L) != 0L) { + jjmatchedKind = 121; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x160000000000000L); + case 97: + return jjMoveStringLiteralDfa2_0(active0, 0x24002006000L, active1, 0L); + case 98: + return jjMoveStringLiteralDfa2_0(active0, 0x100L, active1, 0L); + case 101: + return jjMoveStringLiteralDfa2_0(active0, 0x208000080000L, active1, 0L); + case 102: + if ((active0 & 0x80000000L) != 0L) + return jjStartNfaWithStates_0(1, 31, 29); + break; + case 104: + return jjMoveStringLiteralDfa2_0(active0, 0x1070400000008000L, active1, 0L); + case 105: + return jjMoveStringLiteralDfa2_0(active0, 0xc000000L, active1, 0L); + case 108: + return jjMoveStringLiteralDfa2_0(active0, 0x10410000L, active1, 0L); + case 109: + return jjMoveStringLiteralDfa2_0(active0, 0x300000000L, active1, 0L); + case 110: + return jjMoveStringLiteralDfa2_0(active0, 0x1c00800000L, active1, 0L); + case 111: + if ((active0 & 0x100000L) != 0L) { + jjmatchedKind = 20; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0xc00002060260400L, active1, 0L); + case 114: + return jjMoveStringLiteralDfa2_0(active0, 0x3800c0000000800L, active1, 0L); + case 115: + return jjMoveStringLiteralDfa2_0(active0, 0x200L, active1, 0L); + case 116: + return jjMoveStringLiteralDfa2_0(active0, 0x1800000000000L, active1, 0L); + case 117: + return jjMoveStringLiteralDfa2_0(active0, 0x2110000000000L, active1, 0L); + case 119: + return jjMoveStringLiteralDfa2_0(active0, 0x4000000000000L, active1, 0L); + case 120: + return jjMoveStringLiteralDfa2_0(active0, 0x1000000L, active1, 0L); + case 121: + return jjMoveStringLiteralDfa2_0(active0, 0x8000000001000L, active1, 0L); + case 124: + if ((active1 & 0x80000000L) != 0L) + return jjStopAtPos(1, 95); + break; + default: + break; + } + return jjStartNfa_0(0, active0, active1); + } + + private int jjMoveStringLiteralDfa2_0(long old0, long active0, long old1, long active1) { + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(0, old0, old1); + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + jjStopStringLiteralDfa_0(1, active0, active1); + return 2; + } + switch (curChar) { + case 46: + if ((active1 & 0x80000000000000L) != 0L) + return jjStopAtPos(2, 119); + break; + case 61: + if ((active1 & 0x10000000000000L) != 0L) + return jjStopAtPos(2, 116); + else if ((active1 & 0x20000000000000L) != 0L) + return jjStopAtPos(2, 117); + break; + case 62: + if ((active1 & 0x100000000000000L) != 0L) { + jjmatchedKind = 120; + jjmatchedPos = 2; + } + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x40000000000000L); + case 97: + return jjMoveStringLiteralDfa3_0(active0, 0x80800000018000L, active1, 0L); + case 98: + return jjMoveStringLiteralDfa3_0(active0, 0x100000000000L, active1, 0L); + case 99: + return jjMoveStringLiteralDfa3_0(active0, 0x20000000000L, active1, 0L); + case 101: + return jjMoveStringLiteralDfa3_0(active0, 0x800L, active1, 0L); + case 102: + return jjMoveStringLiteralDfa3_0(active0, 0x80000L, active1, 0L); + case 105: + return jjMoveStringLiteralDfa3_0(active0, 0x1414040000000000L, active1, 0L); + case 108: + return jjMoveStringLiteralDfa3_0(active0, 0x800010002000000L, active1, 0L); + case 110: + return jjMoveStringLiteralDfa3_0(active0, 0x800200c060000L, active1, 0L); + case 111: + return jjMoveStringLiteralDfa3_0(active0, 0x480010000400L, active1, 0L); + case 112: + return jjMoveStringLiteralDfa3_0(active0, 0x2000300000000L, active1, 0L); + case 114: + if ((active0 & 0x20000000L) != 0L) + return jjStartNfaWithStates_0(2, 29, 29); + return jjMoveStringLiteralDfa3_0(active0, 0x61000000000000L, active1, 0L); + case 115: + return jjMoveStringLiteralDfa3_0(active0, 0x400402300L, active1, 0L); + case 116: + if ((active0 & 0x800000000L) != 0L) { + jjmatchedKind = 35; + jjmatchedPos = 2; + } + return jjMoveStringLiteralDfa3_0(active0, 0x205041005000L, active1, 0L); + case 117: + return jjMoveStringLiteralDfa3_0(active0, 0x100000000a00000L, active1, 0L); + case 119: + if ((active0 & 0x8000000000L) != 0L) + return jjStartNfaWithStates_0(2, 39, 29); + break; + case 121: + if ((active0 & 0x200000000000000L) != 0L) + return jjStartNfaWithStates_0(2, 57, 29); + break; + default: + break; + } + return jjStartNfa_0(1, active0, active1); + } + + private int jjMoveStringLiteralDfa3_0(long old0, long active0, long old1, long active1) { + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(1, old0, old1); + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + jjStopStringLiteralDfa_0(2, active0, active1); + return 3; + } + switch (curChar) { + case 61: + if ((active1 & 0x40000000000000L) != 0L) + return jjStopAtPos(3, 118); + break; + case 97: + return jjMoveStringLiteralDfa4_0(active0, 0x80000001c080800L, active1, 0L); + case 98: + return jjMoveStringLiteralDfa4_0(active0, 0x200000L, active1, 0L); + case 99: + return jjMoveStringLiteralDfa4_0(active0, 0x8000000004000L, active1, 0L); + case 100: + if ((active0 & 0x400000000000000L) != 0L) + return jjStartNfaWithStates_0(3, 58, 29); + break; + case 101: + if ((active0 & 0x1000L) != 0L) + return jjStartNfaWithStates_0(3, 12, 29); + else if ((active0 & 0x2000L) != 0L) + return jjStartNfaWithStates_0(3, 13, 29); + else if ((active0 & 0x400000L) != 0L) + return jjStartNfaWithStates_0(3, 22, 29); + else if ((active0 & 0x100000000000000L) != 0L) + return jjStartNfaWithStates_0(3, 56, 29); + return jjMoveStringLiteralDfa4_0(active0, 0x2001001000200L, active1, 0L); + case 103: + if ((active0 & 0x2000000000L) != 0L) + return jjStartNfaWithStates_0(3, 37, 29); + break; + case 105: + return jjMoveStringLiteralDfa4_0(active0, 0x1004000000000L, active1, 0L); + case 107: + return jjMoveStringLiteralDfa4_0(active0, 0x20000000000L, active1, 0L); + case 108: + if ((active0 & 0x10000000000L) != 0L) + return jjStartNfaWithStates_0(3, 40, 29); + return jjMoveStringLiteralDfa4_0(active0, 0x1000100100000400L, active1, 0L); + case 109: + if ((active0 & 0x800000L) != 0L) + return jjStartNfaWithStates_0(3, 23, 29); + break; + case 110: + return jjMoveStringLiteralDfa4_0(active0, 0x80000000000000L, active1, 0L); + case 111: + if ((active0 & 0x40000000L) != 0L) + return jjStartNfaWithStates_0(3, 30, 29); + return jjMoveStringLiteralDfa4_0(active0, 0x60000200000000L, active1, 0L); + case 114: + if ((active0 & 0x8000L) != 0L) + return jjStartNfaWithStates_0(3, 15, 29); + return jjMoveStringLiteralDfa4_0(active0, 0x400000000000L, active1, 0L); + case 115: + if ((active0 & 0x10000000000000L) != 0L) + return jjStartNfaWithStates_0(3, 52, 29); + return jjMoveStringLiteralDfa4_0(active0, 0x2030000L, active1, 0L); + case 116: + return jjMoveStringLiteralDfa4_0(active0, 0x4880400040100L, active1, 0L); + case 117: + return jjMoveStringLiteralDfa4_0(active0, 0x200000000000L, active1, 0L); + case 118: + return jjMoveStringLiteralDfa4_0(active0, 0x40000000000L, active1, 0L); + default: + break; + } + return jjStartNfa_0(2, active0, active1); + } + + private int jjMoveStringLiteralDfa4_0(long old0, long active0, long old1, long active1) { + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(2, old0, old1); + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + jjStopStringLiteralDfa_0(3, active0, 0L); + return 4; + } + switch (curChar) { + case 97: + return jjMoveStringLiteralDfa5_0(active0, 0x60400000000L); + case 99: + return jjMoveStringLiteralDfa5_0(active0, 0x5000000000000L); + case 101: + if ((active0 & 0x2000000L) != 0L) + return jjStartNfaWithStates_0(4, 25, 29); + else if ((active0 & 0x1000000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 60, 29); + return jjMoveStringLiteralDfa5_0(active0, 0x80100000400L); + case 104: + if ((active0 & 0x4000L) != 0L) + return jjStartNfaWithStates_0(4, 14, 29); + return jjMoveStringLiteralDfa5_0(active0, 0x8000000000000L); + case 105: + return jjMoveStringLiteralDfa5_0(active0, 0x900000040000L); + case 107: + if ((active0 & 0x800L) != 0L) + return jjStartNfaWithStates_0(4, 11, 29); + break; + case 108: + if ((active0 & 0x4000000L) != 0L) { + jjmatchedKind = 26; + jjmatchedPos = 4; + } + return jjMoveStringLiteralDfa5_0(active0, 0x8200000L); + case 110: + return jjMoveStringLiteralDfa5_0(active0, 0x1000000L); + case 114: + if ((active0 & 0x2000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 49, 29); + return jjMoveStringLiteralDfa5_0(active0, 0x201200000300L); + case 115: + if ((active0 & 0x10000L) != 0L) + return jjStartNfaWithStates_0(4, 16, 29); + return jjMoveStringLiteralDfa5_0(active0, 0x80000000000000L); + case 116: + if ((active0 & 0x20000L) != 0L) + return jjStartNfaWithStates_0(4, 17, 29); + else if ((active0 & 0x10000000L) != 0L) + return jjStartNfaWithStates_0(4, 28, 29); + else if ((active0 & 0x400000000000L) != 0L) + return jjStartNfaWithStates_0(4, 46, 29); + return jjMoveStringLiteralDfa5_0(active0, 0x800000000000000L); + case 117: + return jjMoveStringLiteralDfa5_0(active0, 0x80000L); + case 118: + return jjMoveStringLiteralDfa5_0(active0, 0x4000000000L); + case 119: + if ((active0 & 0x20000000000000L) != 0L) { + jjmatchedKind = 53; + jjmatchedPos = 4; + } + return jjMoveStringLiteralDfa5_0(active0, 0x40000000000000L); + default: + break; + } + return jjStartNfa_0(3, active0, 0L); + } + + private int jjMoveStringLiteralDfa5_0(long old0, long active0) { + if ((active0 &= old0) == 0L) + return jjStartNfa_0(3, old0, 0L); + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + jjStopStringLiteralDfa_0(4, active0, 0L); + return 5; + } + switch (curChar) { + case 97: + return jjMoveStringLiteralDfa6_0(active0, 0x500L); + case 99: + if ((active0 & 0x100000000000L) != 0L) + return jjStartNfaWithStates_0(5, 44, 29); + else if ((active0 & 0x800000000000L) != 0L) + return jjStartNfaWithStates_0(5, 47, 29); + return jjMoveStringLiteralDfa6_0(active0, 0x80000000000L); + case 100: + return jjMoveStringLiteralDfa6_0(active0, 0x1000000L); + case 101: + if ((active0 & 0x200000L) != 0L) + return jjStartNfaWithStates_0(5, 21, 29); + else if ((active0 & 0x4000000000L) != 0L) + return jjStartNfaWithStates_0(5, 38, 29); + break; + case 102: + return jjMoveStringLiteralDfa6_0(active0, 0x1000000000L); + case 103: + return jjMoveStringLiteralDfa6_0(active0, 0x20000000000L); + case 104: + if ((active0 & 0x4000000000000L) != 0L) + return jjStartNfaWithStates_0(5, 50, 29); + break; + case 105: + return jjMoveStringLiteralDfa6_0(active0, 0x880000000000000L); + case 108: + return jjMoveStringLiteralDfa6_0(active0, 0x8080000L); + case 109: + return jjMoveStringLiteralDfa6_0(active0, 0x100000000L); + case 110: + if ((active0 & 0x200000000000L) != 0L) + return jjStartNfaWithStates_0(5, 45, 29); + return jjMoveStringLiteralDfa6_0(active0, 0x400040000L); + case 114: + return jjMoveStringLiteralDfa6_0(active0, 0x8000000000000L); + case 115: + if ((active0 & 0x40000000000000L) != 0L) + return jjStartNfaWithStates_0(5, 54, 29); + break; + case 116: + if ((active0 & 0x200L) != 0L) + return jjStartNfaWithStates_0(5, 9, 29); + else if ((active0 & 0x200000000L) != 0L) + return jjStartNfaWithStates_0(5, 33, 29); + return jjMoveStringLiteralDfa6_0(active0, 0x1040000000000L); + default: + break; + } + return jjStartNfa_0(4, active0, 0L); + } + + private int jjMoveStringLiteralDfa6_0(long old0, long active0) { + if ((active0 &= old0) == 0L) + return jjStartNfa_0(4, old0, 0L); + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + jjStopStringLiteralDfa_0(5, active0, 0L); + return 6; + } + switch (curChar) { + case 97: + return jjMoveStringLiteralDfa7_0(active0, 0x1000000000L); + case 99: + return jjMoveStringLiteralDfa7_0(active0, 0x400000100L); + case 101: + if ((active0 & 0x20000000000L) != 0L) + return jjStartNfaWithStates_0(6, 41, 29); + else if ((active0 & 0x40000000000L) != 0L) + return jjStartNfaWithStates_0(6, 42, 29); + return jjMoveStringLiteralDfa7_0(active0, 0x80000100000000L); + case 102: + return jjMoveStringLiteralDfa7_0(active0, 0x1000000000000L); + case 108: + return jjMoveStringLiteralDfa7_0(active0, 0x800000000000000L); + case 110: + if ((active0 & 0x400L) != 0L) + return jjStartNfaWithStates_0(6, 10, 29); + break; + case 111: + return jjMoveStringLiteralDfa7_0(active0, 0x8000000000000L); + case 115: + if ((active0 & 0x1000000L) != 0L) + return jjStartNfaWithStates_0(6, 24, 29); + break; + case 116: + if ((active0 & 0x80000L) != 0L) + return jjStartNfaWithStates_0(6, 19, 29); + return jjMoveStringLiteralDfa7_0(active0, 0x80000000000L); + case 117: + return jjMoveStringLiteralDfa7_0(active0, 0x40000L); + case 121: + if ((active0 & 0x8000000L) != 0L) + return jjStartNfaWithStates_0(6, 27, 29); + break; + default: + break; + } + return jjStartNfa_0(5, active0, 0L); + } + + private int jjMoveStringLiteralDfa7_0(long old0, long active0) { + if ((active0 &= old0) == 0L) + return jjStartNfa_0(5, old0, 0L); + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + jjStopStringLiteralDfa_0(6, active0, 0L); + return 7; + } + switch (curChar) { + case 99: + return jjMoveStringLiteralDfa8_0(active0, 0x1000000000L); + case 101: + if ((active0 & 0x40000L) != 0L) + return jjStartNfaWithStates_0(7, 18, 29); + else if ((active0 & 0x800000000000000L) != 0L) + return jjStartNfaWithStates_0(7, 59, 29); + return jjMoveStringLiteralDfa8_0(active0, 0x80400000000L); + case 110: + return jjMoveStringLiteralDfa8_0(active0, 0x88000100000000L); + case 112: + if ((active0 & 0x1000000000000L) != 0L) + return jjStartNfaWithStates_0(7, 48, 29); + break; + case 116: + if ((active0 & 0x100L) != 0L) + return jjStartNfaWithStates_0(7, 8, 29); + break; + default: + break; + } + return jjStartNfa_0(6, active0, 0L); + } + + private int jjMoveStringLiteralDfa8_0(long old0, long active0) { + if ((active0 &= old0) == 0L) + return jjStartNfa_0(6, old0, 0L); + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + jjStopStringLiteralDfa_0(7, active0, 0L); + return 8; + } + switch (curChar) { + case 100: + if ((active0 & 0x80000000000L) != 0L) + return jjStartNfaWithStates_0(8, 43, 29); + break; + case 101: + if ((active0 & 0x1000000000L) != 0L) + return jjStartNfaWithStates_0(8, 36, 29); + break; + case 105: + return jjMoveStringLiteralDfa9_0(active0, 0x8000000000000L); + case 111: + return jjMoveStringLiteralDfa9_0(active0, 0x400000000L); + case 116: + if ((active0 & 0x80000000000000L) != 0L) + return jjStartNfaWithStates_0(8, 55, 29); + return jjMoveStringLiteralDfa9_0(active0, 0x100000000L); + default: + break; + } + return jjStartNfa_0(7, active0, 0L); + } + + private int jjMoveStringLiteralDfa9_0(long old0, long active0) { + if ((active0 &= old0) == 0L) + return jjStartNfa_0(7, old0, 0L); + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + jjStopStringLiteralDfa_0(8, active0, 0L); + return 9; + } + switch (curChar) { + case 102: + if ((active0 & 0x400000000L) != 0L) + return jjStartNfaWithStates_0(9, 34, 29); + break; + case 115: + if ((active0 & 0x100000000L) != 0L) + return jjStartNfaWithStates_0(9, 32, 29); + break; + case 122: + return jjMoveStringLiteralDfa10_0(active0, 0x8000000000000L); + default: + break; + } + return jjStartNfa_0(8, active0, 0L); + } + + private int jjMoveStringLiteralDfa10_0(long old0, long active0) { + if ((active0 &= old0) == 0L) + return jjStartNfa_0(8, old0, 0L); + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + jjStopStringLiteralDfa_0(9, active0, 0L); + return 10; + } + switch (curChar) { + case 101: + return jjMoveStringLiteralDfa11_0(active0, 0x8000000000000L); + default: + break; + } + return jjStartNfa_0(9, active0, 0L); + } + + private int jjMoveStringLiteralDfa11_0(long old0, long active0) { + if ((active0 &= old0) == 0L) + return jjStartNfa_0(9, old0, 0L); + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + jjStopStringLiteralDfa_0(10, active0, 0L); + return 11; + } + switch (curChar) { + case 100: + if ((active0 & 0x8000000000000L) != 0L) + return jjStartNfaWithStates_0(11, 51, 29); + break; + default: + break; + } + return jjStartNfa_0(10, active0, 0L); + } + + private void jjCheckNAdd(int state) { + if (jjrounds[state] != jjround) { + jjstateSet[jjnewStateCnt++] = state; + jjrounds[state] = jjround; + } + } + + private void jjAddStates(int start, int end) { + do { + jjstateSet[jjnewStateCnt++] = jjnextStates[start]; + } while (start++ != end); + } + + private void jjCheckNAddTwoStates(int state1, int state2) { + jjCheckNAdd(state1); + jjCheckNAdd(state2); + } + + private void jjCheckNAddStates(int start, int end) { + do { + jjCheckNAdd(jjnextStates[start]); + } while (start++ != end); + } + + private void jjCheckNAddStates(int start) { + jjCheckNAdd(jjnextStates[start]); + jjCheckNAdd(jjnextStates[start + 1]); + } + + static final long[] jjbitVec0 = { + 0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL + }; + + static final long[] jjbitVec2 = { + 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL + }; + + static final long[] jjbitVec3 = { + 0xfff0000000200002L, 0xffffffffffffdfffL, 0xfffff00f7fffffffL, 0x12000000007fffffL + }; + + static final long[] jjbitVec4 = { + 0x0L, 0x0L, 0x420043c00000000L, 0xff7fffffff7fffffL + }; + + static final long[] jjbitVec5 = { + 0xffffcffffffffL, 0xffffffffffff0000L, 0xf9ff3fffffffffffL, 0x401f00030003L + }; + + static final long[] jjbitVec6 = { + 0x0L, 0x400000000000000L, 0xfffffffbffffd740L, 0xffffffcff7fffL + }; + + static final long[] jjbitVec7 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0xfffffffffffff003L, 0x33fffffffff199fL + }; + + static final long[] jjbitVec8 = { + 0xfffe000000000000L, 0xfffffffe027fffffL, 0xffL, 0x707ffffff0000L + }; + + static final long[] jjbitVec9 = { + 0x7fffffe00000000L, 0xfffe0000000007ffL, 0xffffffffffffffffL, 0x1c000060002fffffL + }; + + static final long[] jjbitVec10 = { + 0x1ffffffd0000L, 0x0L, 0x3fffffffffL, 0x0L + }; + + static final long[] jjbitVec11 = { + 0x23ffffffffffffe0L, 0x3ff010000L, 0x3c5fdfffff99fe0L, 0xf0003b0000000L + }; + + static final long[] jjbitVec12 = { + 0x36dfdfffff987e0L, 0x1c00005e000000L, 0x23edfdfffffbafe0L, 0x100010000L + }; + + static final long[] jjbitVec13 = { + 0x23cdfdfffff99fe0L, 0x3b0000000L, 0x3bfc718d63dc7e0L, 0x0L + }; + + static final long[] jjbitVec14 = { + 0x3effdfffffddfe0L, 0x300000000L, 0x3effdfffffddfe0L, 0x340000000L + }; + + static final long[] jjbitVec15 = { + 0x3fffdfffffddfe0L, 0x300000000L, 0x2ffbfffffc7fffe0L, 0x7fL + }; + + static final long[] jjbitVec16 = { + 0x800dfffffffffffeL, 0x7fL, 0x200decaefef02596L, 0x3000005fL + }; + + static final long[] jjbitVec17 = { + 0x1L, 0x7fffffffeffL, 0xf00L, 0x0L + }; + + static final long[] jjbitVec18 = { + 0x6fbffffffffL, 0x3f0000L, 0xffffffff00000000L, 0x7fffffffff003fL + }; + + static final long[] jjbitVec19 = { + 0xffffffffffffffffL, 0xffffffff83ffffffL, 0xffffff07ffffffffL, 0x3ffffffffffffffL + }; + + static final long[] jjbitVec20 = { + 0xffffffffffffff7fL, 0xffffffff3d7f3d7fL, 0x7f3d7fffffff3d7fL, 0xffff7fffff7f7f3dL + }; + + static final long[] jjbitVec21 = { + 0xffffffff7f3d7fffL, 0x7ffff7fL, 0xffffffff00000000L, 0x1fffffffffffffL + }; + + static final long[] jjbitVec22 = { + 0xffffffffffffffffL, 0x7f9fffffffffffL, 0xffffffff07fffffeL, 0x7ffffffffffL + }; + + static final long[] jjbitVec23 = { + 0x0L, 0x0L, 0xfffffffffffffL, 0x8000000L + }; + + static final long[] jjbitVec24 = { + 0xffffffff00000000L, 0xffffffffffffffL, 0x1ffffffffffL, 0x0L + }; + + static final long[] jjbitVec25 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffff0fffffffL, 0x3ffffffffffffffL + }; + + static final long[] jjbitVec26 = { + 0xffffffff3f3fffffL, 0x3fffffffaaff3f3fL, 0x5fdfffffffffffffL, 0x1fdc1fff0fcf1fdcL + }; + + static final long[] jjbitVec27 = { + 0x8000000000000000L, 0x8000000000000001L, 0xffff00000000L, 0x0L + }; + + static final long[] jjbitVec28 = { + 0x3fbbd503e2ffc84L, 0xffffffff00000000L, 0xfL, 0x0L + }; + + static final long[] jjbitVec29 = { + 0x73e03fe000000e0L, 0xfffffffffffffffeL, 0xfffffffe601fffffL, 0x7fffffffffffffffL + }; + + static final long[] jjbitVec30 = { + 0xfffe1fffffffffe0L, 0xffffffffffffffffL, 0xffffff00007fffL, 0x0L + }; + + static final long[] jjbitVec31 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0x3fffffffffffffL, 0x0L + }; + + static final long[] jjbitVec32 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0x3fffffffffL, 0x0L + }; + + static final long[] jjbitVec33 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0x1fffL, 0x0L + }; + + static final long[] jjbitVec34 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0xfffffffffL, 0x0L + }; + + static final long[] jjbitVec35 = { + 0x3fffffffffffL, 0x0L, 0x0L, 0x0L + }; + + static final long[] jjbitVec36 = { + 0x5f7ffdffa0f8007fL, 0xffffffffffffffdbL, 0x3ffffffffffffL, 0xfffffffffff80000L + }; + + static final long[] jjbitVec37 = { + 0x3fffffffffffffffL, 0xffffffffffff0000L, 0xfffffffffffcffffL, 0xfff0000000000ffL + }; + + static final long[] jjbitVec38 = { + 0x18000000000000L, 0xffd702000000e000L, 0xffffffffffffffffL, 0x1fffffffffffffffL + }; + + static final long[] jjbitVec39 = { + 0x87fffffe00000010L, 0xffffffe007fffffeL, 0x7fffffffffffffffL, 0x631cfcfcfcL + }; + + static final long[] jjbitVec40 = { + 0x0L, 0x0L, 0x420043cffffffffL, 0xff7fffffff7fffffL + }; + + static final long[] jjbitVec41 = { + 0xffffffffffffffffL, 0x400000700007fffL, 0xfffffffbffffd740L, 0xffffffcff7fffL + }; + + static final long[] jjbitVec42 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0xfffffffffffff07bL, 0x33fffffffff199fL + }; + + static final long[] jjbitVec43 = { + 0xfffe000000000000L, 0xfffffffe027fffffL, 0xbbfffffbfffe00ffL, 0x707ffffff0016L + }; + + static final long[] jjbitVec44 = { + 0x7fffffe00000000L, 0xffff03ff003fffffL, 0xffffffffffffffffL, 0x1fff3dff9fefffffL + }; + + static final long[] jjbitVec45 = { + 0xffff1fffffff8000L, 0x7ffL, 0x1ffffffffffffL, 0x0L + }; + + static final long[] jjbitVec46 = { + 0xf3ffffffffffffeeL, 0xffcfff1f3fffL, 0xd3c5fdfffff99feeL, 0xfffcfb080399fL + }; + + static final long[] jjbitVec47 = { + 0xd36dfdfffff987e4L, 0x1fffc05e003987L, 0xf3edfdfffffbafeeL, 0xffc100013bbfL + }; + + static final long[] jjbitVec48 = { + 0xf3cdfdfffff99feeL, 0xffc3b0c0398fL, 0xc3bfc718d63dc7ecL, 0xff8000803dc7L + }; + + static final long[] jjbitVec49 = { + 0xc3effdfffffddfeeL, 0xffc300603ddfL, 0xc3effdfffffddfecL, 0xffc340603ddfL + }; + + static final long[] jjbitVec50 = { + 0xc3fffdfffffddfecL, 0xffc300803dcfL, 0x2ffbfffffc7fffecL, 0xc0000ff5f847fL + }; + + static final long[] jjbitVec51 = { + 0x87fffffffffffffeL, 0x3ff7fffL, 0x3bffecaefef02596L, 0x33ff3f5fL + }; + + static final long[] jjbitVec52 = { + 0xc2a003ff03000001L, 0xfffe07fffffffeffL, 0x1ffffffffeff0fdfL, 0x40L + }; + + static final long[] jjbitVec53 = { + 0x3c7f6fbffffffffL, 0x3ff03ffL, 0xffffffff00000000L, 0x7fffffffff003fL + }; + + static final long[] jjbitVec54 = { + 0xffffffff7f3d7fffL, 0x3fe0007ffff7fL, 0xffffffff00000000L, 0x1fffffffffffffL + }; + + static final long[] jjbitVec55 = { + 0x0L, 0x0L, 0xffffffffffffffffL, 0x3ff080fffffL + }; + + static final long[] jjbitVec56 = { + 0xffffffff03ff7800L, 0xffffffffffffffL, 0x3ffffffffffL, 0x0L + }; + + static final long[] jjbitVec57 = { + 0x80007c000000f000L, 0x8000fc0000000001L, 0xffff00000000L, 0x21fff0000L + }; + + static final long[] jjbitVec58 = { + 0x73efffe000000e0L, 0xfffffffffffffffeL, 0xfffffffe661fffffL, 0x7fffffffffffffffL + }; + + static final long[] jjbitVec59 = { + 0x5f7ffdffe0f8007fL, 0xffffffffffffffdbL, 0x3ffffffffffffL, 0xfffffffffff80000L + }; + + static final long[] jjbitVec60 = { + 0x18000f00000000L, 0xffd702000000e000L, 0xffffffffffffffffL, 0x9fffffffffffffffL + }; + + static final long[] jjbitVec61 = { + 0x87fffffe03ff0010L, 0xffffffe007fffffeL, 0x7fffffffffffffffL, 0xe0000631cfcfcfcL + }; + + private int jjMoveNfa_0(int startState, int curPos) { + int[] nextStates; + int startsAt = 0; + jjnewStateCnt = 71; + int i = 1; + jjstateSet[0] = startState; + int j, kind = 0x7fffffff; + for (; ; ) { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) { + long l = 1L << curChar; + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 1: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(0, 6); + else if ((0x100003600L & l) != 0L) { + if (kind > 3) + kind = 3; + jjCheckNAdd(0); + } else if (curChar == 47) + jjAddStates(7, 8); + else if (curChar == 36) { + if (kind > 72) + kind = 72; + jjCheckNAdd(29); + } else if (curChar == 34) + jjCheckNAddStates(9, 11); + else if (curChar == 39) + jjAddStates(12, 13); + else if (curChar == 46) + jjCheckNAdd(5); + if ((0x3fe000000000000L & l) != 0L) { + if (kind > 61) + kind = 61; + jjCheckNAddTwoStates(2, 3); + } else if (curChar == 48) { + if (kind > 61) + kind = 61; + jjCheckNAddStates(14, 18); + } + break; + case 48: + if (curChar == 47) { + if (kind > 4) + kind = 4; + jjCheckNAddStates(19, 21); + } else if (curChar == 42) + jjstateSet[jjnewStateCnt++] = 46; + break; + case 0: + if ((0x100003600L & l) == 0L) + break; + if (kind > 3) + kind = 3; + jjCheckNAdd(0); + break; + case 2: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 61) + kind = 61; + jjCheckNAddTwoStates(2, 3); + break; + case 4: + if (curChar == 46) + jjCheckNAdd(5); + break; + case 5: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 65) + kind = 65; + jjCheckNAddStates(22, 24); + break; + case 7: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(8); + break; + case 8: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 65) + kind = 65; + jjCheckNAddTwoStates(8, 9); + break; + case 10: + if (curChar == 39) + jjAddStates(12, 13); + break; + case 11: + if ((0xffffff7fffffdbffL & l) != 0L) + jjCheckNAdd(12); + break; + case 12: + if (curChar == 39 && kind > 70) + kind = 70; + break; + case 14: + if ((0x8400000000L & l) != 0L) + jjCheckNAdd(12); + break; + case 15: + if ((0xff000000000000L & l) != 0L) + jjCheckNAddTwoStates(16, 12); + break; + case 16: + if ((0xff000000000000L & l) != 0L) + jjCheckNAdd(12); + break; + case 17: + if ((0xf000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 18; + break; + case 18: + if ((0xff000000000000L & l) != 0L) + jjCheckNAdd(16); + break; + case 19: + if (curChar == 34) + jjCheckNAddStates(9, 11); + break; + case 20: + if ((0xfffffffbffffdbffL & l) != 0L) + jjCheckNAddStates(9, 11); + break; + case 22: + if ((0x8400000000L & l) != 0L) + jjCheckNAddStates(9, 11); + break; + case 23: + if (curChar == 34 && kind > 71) + kind = 71; + break; + case 24: + if ((0xff000000000000L & l) != 0L) + jjCheckNAddStates(25, 28); + break; + case 25: + if ((0xff000000000000L & l) != 0L) + jjCheckNAddStates(9, 11); + break; + case 26: + if ((0xf000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 27; + break; + case 27: + if ((0xff000000000000L & l) != 0L) + jjCheckNAdd(25); + break; + case 28: + if (curChar != 36) + break; + if (kind > 72) + kind = 72; + jjCheckNAdd(29); + break; + case 29: + if ((0x3ff00100fffc1ffL & l) == 0L) + break; + if (kind > 72) + kind = 72; + jjCheckNAdd(29); + break; + case 30: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(0, 6); + break; + case 31: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(29, 31); + break; + case 33: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(34); + break; + case 34: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(34, 9); + break; + case 35: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(35, 36); + break; + case 37: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(38); + break; + case 38: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 65) + kind = 65; + jjCheckNAddTwoStates(38, 9); + break; + case 39: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(39, 40); + break; + case 40: + if (curChar != 46) + break; + if (kind > 65) + kind = 65; + jjCheckNAddStates(32, 34); + break; + case 41: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 65) + kind = 65; + jjCheckNAddStates(32, 34); + break; + case 43: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(44); + break; + case 44: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 65) + kind = 65; + jjCheckNAddTwoStates(44, 9); + break; + case 45: + if (curChar == 47) + jjAddStates(7, 8); + break; + case 46: + if (curChar == 42) + jjstateSet[jjnewStateCnt++] = 47; + break; + case 47: + if ((0xffff7fffffffffffL & l) != 0L && kind > 1) + kind = 1; + break; + case 49: + if (curChar != 47) + break; + if (kind > 4) + kind = 4; + jjCheckNAddStates(19, 21); + break; + case 50: + if ((0xffffffffffffdbffL & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAddStates(19, 21); + break; + case 51: + if ((0x2400L & l) != 0L && kind > 4) + kind = 4; + break; + case 52: + if (curChar == 10 && kind > 4) + kind = 4; + break; + case 53: + if (curChar == 13) + jjstateSet[jjnewStateCnt++] = 52; + break; + case 54: + if (curChar != 48) + break; + if (kind > 61) + kind = 61; + jjCheckNAddStates(14, 18); + break; + case 56: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 61) + kind = 61; + jjCheckNAddTwoStates(56, 3); + break; + case 57: + if ((0xff000000000000L & l) == 0L) + break; + if (kind > 61) + kind = 61; + jjCheckNAddTwoStates(57, 3); + break; + case 59: + if ((0x3ff000000000000L & l) != 0L) + jjAddStates(35, 36); + break; + case 60: + if (curChar == 46) + jjCheckNAdd(61); + break; + case 61: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(61, 62); + break; + case 63: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(64); + break; + case 64: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 65) + kind = 65; + jjCheckNAddTwoStates(64, 9); + break; + case 66: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(37, 39); + break; + case 67: + if (curChar == 46) + jjCheckNAdd(68); + break; + case 69: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(70); + break; + case 70: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 65) + kind = 65; + jjCheckNAddTwoStates(70, 9); + break; + default: + break; + } + } while (i != startsAt); + } else if (curChar < 128) { + long l = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 1: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 72) + kind = 72; + jjCheckNAdd(29); + break; + case 3: + if ((0x100000001000L & l) != 0L && kind > 61) + kind = 61; + break; + case 6: + if ((0x2000000020L & l) != 0L) + jjAddStates(40, 41); + break; + case 9: + if ((0x5000000050L & l) != 0L && kind > 65) + kind = 65; + break; + case 11: + if ((0xffffffffefffffffL & l) != 0L) + jjCheckNAdd(12); + break; + case 13: + if (curChar == 92) + jjAddStates(42, 44); + break; + case 14: + if ((0x14404410000000L & l) != 0L) + jjCheckNAdd(12); + break; + case 20: + if ((0xffffffffefffffffL & l) != 0L) + jjCheckNAddStates(9, 11); + break; + case 21: + if (curChar == 92) + jjAddStates(45, 47); + break; + case 22: + if ((0x14404410000000L & l) != 0L) + jjCheckNAddStates(9, 11); + break; + case 29: + if ((0x87fffffe87fffffeL & l) == 0L) + break; + if (kind > 72) + kind = 72; + jjCheckNAdd(29); + break; + case 32: + if ((0x2000000020L & l) != 0L) + jjAddStates(48, 49); + break; + case 36: + if ((0x2000000020L & l) != 0L) + jjAddStates(50, 51); + break; + case 42: + if ((0x2000000020L & l) != 0L) + jjAddStates(52, 53); + break; + case 47: + if (kind > 1) + kind = 1; + break; + case 50: + if (kind > 4) + kind = 4; + jjAddStates(19, 21); + break; + case 55: + if ((0x100000001000000L & l) != 0L) + jjCheckNAdd(56); + break; + case 56: + if ((0x7e0000007eL & l) == 0L) + break; + if (kind > 61) + kind = 61; + jjCheckNAddTwoStates(56, 3); + break; + case 58: + if ((0x100000001000000L & l) != 0L) + jjCheckNAddTwoStates(59, 60); + break; + case 59: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAddTwoStates(59, 60); + break; + case 61: + if ((0x7e0000007eL & l) != 0L) + jjAddStates(54, 55); + break; + case 62: + if ((0x1000000010000L & l) != 0L) + jjAddStates(56, 57); + break; + case 65: + if ((0x100000001000000L & l) != 0L) + jjCheckNAdd(66); + break; + case 66: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAddStates(37, 39); + break; + case 68: + if ((0x1000000010000L & l) != 0L) + jjAddStates(58, 59); + break; + default: + break; + } + } while (i != startsAt); + } else { + int hiByte = (int) (curChar >> 8); + int i1 = hiByte >> 6; + long l1 = 1L << (hiByte & 077); + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 1: + if (!jjCanMove_1(hiByte, i1, i2, l1, l2)) + break; + if (kind > 72) + kind = 72; + jjCheckNAdd(29); + break; + case 11: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjstateSet[jjnewStateCnt++] = 12; + break; + case 20: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjAddStates(9, 11); + break; + case 29: + if (!jjCanMove_2(hiByte, i1, i2, l1, l2)) + break; + if (kind > 72) + kind = 72; + jjCheckNAdd(29); + break; + case 47: + if (jjCanMove_0(hiByte, i1, i2, l1, l2) && kind > 1) + kind = 1; + break; + case 50: + if (!jjCanMove_0(hiByte, i1, i2, l1, l2)) + break; + if (kind > 4) + kind = 4; + jjAddStates(19, 21); + break; + default: + break; + } + } while (i != startsAt); + } + if (kind != 0x7fffffff) { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 71 - (jjnewStateCnt = startsAt))) + return curPos; + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + return curPos; + } + } + } + + private int jjMoveStringLiteralDfa0_2() { + switch (curChar) { + case 42: + return jjMoveStringLiteralDfa1_2(0x40L); + default: + return 1; + } + } + + private int jjMoveStringLiteralDfa1_2(long active0) { + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + return 1; + } + switch (curChar) { + case 47: + if ((active0 & 0x40L) != 0L) + return jjStopAtPos(1, 6); + break; + default: + return 2; + } + return 2; + } + + private int jjMoveStringLiteralDfa0_1() { + switch (curChar) { + case 42: + return jjMoveStringLiteralDfa1_1(0x20L); + default: + return 1; + } + } + + private int jjMoveStringLiteralDfa1_1(long active0) { + try { + curChar = input_stream.readChar(); + } catch (IOException e) { + return 1; + } + switch (curChar) { + case 47: + if ((active0 & 0x20L) != 0L) + return jjStopAtPos(1, 5); + break; + default: + return 2; + } + return 2; + } + + static final int[] jjnextStates = { + 31, 32, 9, 35, 36, 39, 40, 48, 49, 20, 21, 23, 11, 13, 55, 57, + 3, 58, 65, 50, 51, 53, 5, 6, 9, 20, 21, 25, 23, 31, 32, 9, + 41, 42, 9, 59, 60, 66, 67, 68, 7, 8, 14, 15, 17, 22, 24, 26, + 33, 34, 37, 38, 43, 44, 61, 62, 63, 64, 69, 70, + }; + + private static boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2) { + switch (hiByte) { + case 0: + return (jjbitVec2[i2] & l2) != 0L; + default: + if ((jjbitVec0[i1] & l1) != 0L) + return true; + return false; + } + } + + private static boolean jjCanMove_1(int hiByte, int i1, int i2, long l1, long l2) { + switch (hiByte) { + case 0: + return (jjbitVec4[i2] & l2) != 0L; + case 2: + return (jjbitVec5[i2] & l2) != 0L; + case 3: + return (jjbitVec6[i2] & l2) != 0L; + case 4: + return (jjbitVec7[i2] & l2) != 0L; + case 5: + return (jjbitVec8[i2] & l2) != 0L; + case 6: + return (jjbitVec9[i2] & l2) != 0L; + case 7: + return (jjbitVec10[i2] & l2) != 0L; + case 9: + return (jjbitVec11[i2] & l2) != 0L; + case 10: + return (jjbitVec12[i2] & l2) != 0L; + case 11: + return (jjbitVec13[i2] & l2) != 0L; + case 12: + return (jjbitVec14[i2] & l2) != 0L; + case 13: + return (jjbitVec15[i2] & l2) != 0L; + case 14: + return (jjbitVec16[i2] & l2) != 0L; + case 15: + return (jjbitVec17[i2] & l2) != 0L; + case 16: + return (jjbitVec18[i2] & l2) != 0L; + case 17: + return (jjbitVec19[i2] & l2) != 0L; + case 18: + return (jjbitVec20[i2] & l2) != 0L; + case 19: + return (jjbitVec21[i2] & l2) != 0L; + case 20: + return (jjbitVec0[i2] & l2) != 0L; + case 22: + return (jjbitVec22[i2] & l2) != 0L; + case 23: + return (jjbitVec23[i2] & l2) != 0L; + case 24: + return (jjbitVec24[i2] & l2) != 0L; + case 30: + return (jjbitVec25[i2] & l2) != 0L; + case 31: + return (jjbitVec26[i2] & l2) != 0L; + case 32: + return (jjbitVec27[i2] & l2) != 0L; + case 33: + return (jjbitVec28[i2] & l2) != 0L; + case 48: + return (jjbitVec29[i2] & l2) != 0L; + case 49: + return (jjbitVec30[i2] & l2) != 0L; + case 77: + return (jjbitVec31[i2] & l2) != 0L; + case 159: + return (jjbitVec32[i2] & l2) != 0L; + case 164: + return (jjbitVec33[i2] & l2) != 0L; + case 215: + return (jjbitVec34[i2] & l2) != 0L; + case 250: + return (jjbitVec35[i2] & l2) != 0L; + case 251: + return (jjbitVec36[i2] & l2) != 0L; + case 253: + return (jjbitVec37[i2] & l2) != 0L; + case 254: + return (jjbitVec38[i2] & l2) != 0L; + case 255: + return (jjbitVec39[i2] & l2) != 0L; + default: + if ((jjbitVec3[i1] & l1) != 0L) + return true; + return false; + } + } + + private static boolean jjCanMove_2(int hiByte, int i1, int i2, long l1, long l2) { + switch (hiByte) { + case 0: + return (jjbitVec40[i2] & l2) != 0L; + case 2: + return (jjbitVec5[i2] & l2) != 0L; + case 3: + return (jjbitVec41[i2] & l2) != 0L; + case 4: + return (jjbitVec42[i2] & l2) != 0L; + case 5: + return (jjbitVec43[i2] & l2) != 0L; + case 6: + return (jjbitVec44[i2] & l2) != 0L; + case 7: + return (jjbitVec45[i2] & l2) != 0L; + case 9: + return (jjbitVec46[i2] & l2) != 0L; + case 10: + return (jjbitVec47[i2] & l2) != 0L; + case 11: + return (jjbitVec48[i2] & l2) != 0L; + case 12: + return (jjbitVec49[i2] & l2) != 0L; + case 13: + return (jjbitVec50[i2] & l2) != 0L; + case 14: + return (jjbitVec51[i2] & l2) != 0L; + case 15: + return (jjbitVec52[i2] & l2) != 0L; + case 16: + return (jjbitVec53[i2] & l2) != 0L; + case 17: + return (jjbitVec19[i2] & l2) != 0L; + case 18: + return (jjbitVec20[i2] & l2) != 0L; + case 19: + return (jjbitVec54[i2] & l2) != 0L; + case 20: + return (jjbitVec0[i2] & l2) != 0L; + case 22: + return (jjbitVec22[i2] & l2) != 0L; + case 23: + return (jjbitVec55[i2] & l2) != 0L; + case 24: + return (jjbitVec56[i2] & l2) != 0L; + case 30: + return (jjbitVec25[i2] & l2) != 0L; + case 31: + return (jjbitVec26[i2] & l2) != 0L; + case 32: + return (jjbitVec57[i2] & l2) != 0L; + case 33: + return (jjbitVec28[i2] & l2) != 0L; + case 48: + return (jjbitVec58[i2] & l2) != 0L; + case 49: + return (jjbitVec30[i2] & l2) != 0L; + case 77: + return (jjbitVec31[i2] & l2) != 0L; + case 159: + return (jjbitVec32[i2] & l2) != 0L; + case 164: + return (jjbitVec33[i2] & l2) != 0L; + case 215: + return (jjbitVec34[i2] & l2) != 0L; + case 250: + return (jjbitVec35[i2] & l2) != 0L; + case 251: + return (jjbitVec59[i2] & l2) != 0L; + case 253: + return (jjbitVec37[i2] & l2) != 0L; + case 254: + return (jjbitVec60[i2] & l2) != 0L; + case 255: + return (jjbitVec61[i2] & l2) != 0L; + default: + if ((jjbitVec3[i1] & l1) != 0L) + return true; + return false; + } + } + + public static final String[] jjstrLiteralImages = { + "", null, null, null, null, null, null, null, + "\141\142\163\164\162\141\143\164", "\141\163\163\145\162\164", "\142\157\157\154\145\141\156", + "\142\162\145\141\153", "\142\171\164\145", "\143\141\163\145", "\143\141\164\143\150", + "\143\150\141\162", "\143\154\141\163\163", "\143\157\156\163\164", + "\143\157\156\164\151\156\165\145", "\144\145\146\141\165\154\164", "\144\157", "\144\157\165\142\154\145", + "\145\154\163\145", "\145\156\165\155", "\145\170\164\145\156\144\163", "\146\141\154\163\145", + "\146\151\156\141\154", "\146\151\156\141\154\154\171", "\146\154\157\141\164", "\146\157\162", + "\147\157\164\157", "\151\146", "\151\155\160\154\145\155\145\156\164\163", + "\151\155\160\157\162\164", "\151\156\163\164\141\156\143\145\157\146", "\151\156\164", + "\151\156\164\145\162\146\141\143\145", "\154\157\156\147", "\156\141\164\151\166\145", "\156\145\167", + "\156\165\154\154", "\160\141\143\153\141\147\145", "\160\162\151\166\141\164\145", + "\160\162\157\164\145\143\164\145\144", "\160\165\142\154\151\143", "\162\145\164\165\162\156", + "\163\150\157\162\164", "\163\164\141\164\151\143", "\163\164\162\151\143\164\146\160", + "\163\165\160\145\162", "\163\167\151\164\143\150", + "\163\171\156\143\150\162\157\156\151\172\145\144", "\164\150\151\163", "\164\150\162\157\167", "\164\150\162\157\167\163", + "\164\162\141\156\163\151\145\156\164", "\164\162\165\145", "\164\162\171", "\166\157\151\144", + "\166\157\154\141\164\151\154\145", "\167\150\151\154\145", null, null, null, null, null, null, null, null, null, + null, null, null, null, null, "\50", "\51", "\173", "\175", "\133", "\135", "\73", + "\54", "\56", "\100", "\75", "\74", "\41", "\176", "\77", "\72", "\75\75", "\74\75", + "\76\75", "\41\75", "\174\174", "\46\46", "\53\53", "\55\55", "\53", "\55", "\52", + "\57", "\46", "\174", "\136", "\45", "\74\74", "\53\75", "\55\75", "\52\75", + "\57\75", "\46\75", "\174\75", "\136\75", "\45\75", "\74\74\75", "\76\76\75", + "\76\76\76\75", "\56\56\56", "\76\76\76", "\76\76", "\76", "\32", null,}; + + public static final String[] lexStateNames = { + "DEFAULT", + "IN_FORMAL_COMMENT", + "IN_MULTI_LINE_COMMENT", + }; + + public static final int[] jjnewLexState = { + -1, 1, 2, -1, -1, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + + static final long[] jjtoToken = { + 0x3fffffffffffff01L, 0x1ffffffffffff9c2L, + }; + + static final long[] jjtoSkip = { + 0x78L, 0x0L, + }; + + static final long[] jjtoSpecial = { + 0x78L, 0x0L, + }; + + static final long[] jjtoMore = { + 0x86L, 0x0L, + }; + + protected JavaCharStream input_stream; + + private final int[] jjrounds = new int[71]; + + private final int[] jjstateSet = new int[142]; + + StringBuilder image; + + int jjimageLen; + + int lengthOfMatch; + + protected char curChar; + + public JavaParserTokenManager(JavaCharStream stream) { + if (JavaCharStream.staticFlag) + throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); + input_stream = stream; + } + + public JavaParserTokenManager(JavaCharStream stream, int lexState) { + this(stream); + SwitchTo(lexState); + } + + public void ReInit(JavaCharStream stream) { + jjmatchedPos = jjnewStateCnt = 0; + curLexState = defaultLexState; + input_stream = stream; + ReInitRounds(); + } + + private void ReInitRounds() { + int i; + jjround = 0x80000001; + for (i = 71; i-- > 0; ) + jjrounds[i] = 0x80000000; + } + + public void ReInit(JavaCharStream stream, int lexState) { + ReInit(stream); + SwitchTo(lexState); + } + + public void SwitchTo(int lexState) { + if (lexState >= 3 || lexState < 0) + throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); + else + curLexState = lexState; + } + + protected Token jjFillToken() { + Token t = Token.newToken(jjmatchedKind); + t.kind = jjmatchedKind; + String im = jjstrLiteralImages[jjmatchedKind]; + t.image = im == null ? input_stream.GetImage() : im; + t.beginLine = input_stream.getBeginLine(); + t.beginColumn = input_stream.getBeginColumn(); + t.endLine = input_stream.getEndLine(); + t.endColumn = input_stream.getEndColumn(); + return t; + } + + int curLexState = 0; + + int defaultLexState = 0; + + int jjnewStateCnt; + + int jjround; + + int jjmatchedPos; + + int jjmatchedKind; + + public Token getNextToken() { + int kind; + Token specialToken = null; + Token matchedToken; + int curPos = 0; + + EOFLoop: + for (; ; ) { + try { + curChar = input_stream.BeginToken(); + } catch (IOException e) { + jjmatchedKind = 0; + matchedToken = jjFillToken(); + matchedToken.specialToken = specialToken; + return matchedToken; + } + image = null; + jjimageLen = 0; + + for (; ; ) { + switch (curLexState) { + case 0: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_0(); + if (jjmatchedPos == 0 && jjmatchedKind > 124) { + jjmatchedKind = 124; + } + break; + case 1: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_1(); + if (jjmatchedPos == 0 && jjmatchedKind > 7) { + jjmatchedKind = 7; + } + break; + case 2: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_2(); + if (jjmatchedPos == 0 && jjmatchedKind > 7) { + jjmatchedKind = 7; + } + break; + } + if (jjmatchedKind != 0x7fffffff) { + if (jjmatchedPos + 1 < curPos) + input_stream.backup(curPos - jjmatchedPos - 1); + if ((jjtoToken[jjmatchedKind >> 6] & 1L << (jjmatchedKind & 077)) != 0L) { + matchedToken = jjFillToken(); + matchedToken.specialToken = specialToken; + TokenLexicalActions(matchedToken); + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + return matchedToken; + } else if ((jjtoSkip[jjmatchedKind >> 6] & 1L << (jjmatchedKind & 077)) != 0L) { + if ((jjtoSpecial[jjmatchedKind >> 6] & 1L << (jjmatchedKind & 077)) != 0L) { + matchedToken = jjFillToken(); + if (specialToken == null) + specialToken = matchedToken; + else { + matchedToken.specialToken = specialToken; + specialToken = specialToken.next = matchedToken; + } + SkipLexicalActions(matchedToken); + } else + SkipLexicalActions(null); + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + continue EOFLoop; + } + MoreLexicalActions(); + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + curPos = 0; + jjmatchedKind = 0x7fffffff; + try { + curChar = input_stream.readChar(); + continue; + } catch (IOException e1) { + } + } + int error_line = input_stream.getEndLine(); + int error_column = input_stream.getEndColumn(); + String error_after = null; + boolean EOFSeen = false; + try { + input_stream.readChar(); + input_stream.backup(1); + } catch (IOException e1) { + EOFSeen = true; + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + if (curChar == '\n' || curChar == '\r') { + error_line++; + error_column = 0; + } else + error_column++; + } + if (!EOFSeen) { + input_stream.backup(1); + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + } + throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); + } + } + } + + void SkipLexicalActions(Token matchedToken) { + switch (jjmatchedKind) { + default: + break; + } + } + + void MoreLexicalActions() { + jjimageLen += lengthOfMatch = jjmatchedPos + 1; + switch (jjmatchedKind) { + case 1: + if (image == null) + image = new StringBuilder(); + image.append(input_stream.GetSuffix(jjimageLen)); + jjimageLen = 0; + input_stream.backup(1); + break; + default: + break; + } + } + + void TokenLexicalActions(Token matchedToken) { + switch (jjmatchedKind) { + case 120: + if (image == null) + image = new StringBuilder(); + image.append(jjstrLiteralImages[120]); + matchedToken.kind = GT; + ((Token.GTToken) matchedToken).realKind = RUNSIGNEDSHIFT; + input_stream.backup(2); + matchedToken.image = ">"; + break; + case 121: + if (image == null) + image = new StringBuilder(); + image.append(jjstrLiteralImages[121]); + matchedToken.kind = GT; + ((Token.GTToken) matchedToken).realKind = RSIGNEDSHIFT; + input_stream.backup(1); + matchedToken.image = ">"; + break; + default: + break; + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaParserTreeConstants.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaParserTreeConstants.java new file mode 100644 index 0000000..5c1b375 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/JavaParserTreeConstants.java @@ -0,0 +1,361 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. ./JavaParserTreeConstants.java */ + + +package org.nuiton.jaxx.compiler.java.parser; + +public interface JavaParserTreeConstants { + int JJTLINE = 0; + + int JJTCOMPILATIONUNIT = 1; + + int JJTPACKAGEDECLARATION = 2; + + int JJTIMPORTDECLARATION = 3; + + int JJTMODIFIERS = 4; + + int JJTTYPEDECLARATION = 5; + + int JJTCLASSORINTERFACEDECLARATION = 6; + + int JJTEXTENDSLIST = 7; + + int JJTIMPLEMENTSLIST = 8; + + int JJTENUMDECLARATION = 9; + + int JJTENUMBODY = 10; + + int JJTENUMCONSTANT = 11; + + int JJTTYPEPARAMETERS = 12; + + int JJTTYPEPARAMETER = 13; + + int JJTTYPEBOUND = 14; + + int JJTCLASSORINTERFACEBODY = 15; + + int JJTCLASSORINTERFACEBODYDECLARATION = 16; + + int JJTFIELDDECLARATION = 17; + + int JJTVARIABLEDECLARATOR = 18; + + int JJTVARIABLEDECLARATORID = 19; + + int JJTVARIABLEINITIALIZER = 20; + + int JJTARRAYINITIALIZER = 21; + + int JJTMETHODDECLARATION = 22; + + int JJTMETHODDECLARATOR = 23; + + int JJTFORMALPARAMETERS = 24; + + int JJTFORMALPARAMETER = 25; + + int JJTCONSTRUCTORDECLARATION = 26; + + int JJTEXPLICITCONSTRUCTORINVOCATION = 27; + + int JJTINITIALIZER = 28; + + int JJTTYPE = 29; + + int JJTREFERENCETYPE = 30; + + int JJTCLASSORINTERFACETYPE = 31; + + int JJTTYPEARGUMENTS = 32; + + int JJTTYPEARGUMENT = 33; + + int JJTWILDCARDBOUNDS = 34; + + int JJTPRIMITIVETYPE = 35; + + int JJTRESULTTYPE = 36; + + int JJTNAME = 37; + + int JJTNAMELIST = 38; + + int JJTEXPRESSION = 39; + + int JJTASSIGNMENTOPERATOR = 40; + + int JJTASSIGNMENTEXPRESSION = 41; + + int JJTCONDITIONALEXPRESSION = 42; + + int JJTCONDITIONALOREXPRESSION = 43; + + int JJTCONDITIONALANDEXPRESSION = 44; + + int JJTINCLUSIVEOREXPRESSION = 45; + + int JJTEXCLUSIVEOREXPRESSION = 46; + + int JJTANDEXPRESSION = 47; + + int JJTEQUALITYEXPRESSION = 48; + + int JJTINSTANCEOFEXPRESSION = 49; + + int JJTRELATIONALEXPRESSION = 50; + + int JJTSHIFTEXPRESSION = 51; + + int JJTADDITIVEEXPRESSION = 52; + + int JJTMULTIPLICATIVEEXPRESSION = 53; + + int JJTUNARYEXPRESSION = 54; + + int JJTPREINCREMENTEXPRESSION = 55; + + int JJTPREDECREMENTEXPRESSION = 56; + + int JJTUNARYEXPRESSIONNOTPLUSMINUS = 57; + + int JJTCASTLOOKAHEAD = 58; + + int JJTPOSTFIXEXPRESSION = 59; + + int JJTPOSTFIXOPERATOR = 60; + + int JJTCASTEXPRESSION = 61; + + int JJTPRIMARYEXPRESSION = 62; + + int JJTMEMBERSELECTOR = 63; + + int JJTPRIMARYPREFIX = 64; + + int JJTPRIMARYSUFFIX = 65; + + int JJTLITERAL = 66; + + int JJTBOOLEANLITERAL = 67; + + int JJTNULLLITERAL = 68; + + int JJTARGUMENTS = 69; + + int JJTARGUMENTLIST = 70; + + int JJTALLOCATIONEXPRESSION = 71; + + int JJTARRAYDIMSANDINITS = 72; + + int JJTSTATEMENT = 73; + + int JJTASSERTSTATEMENT = 74; + + int JJTLABELEDSTATEMENT = 75; + + int JJTBLOCK = 76; + + int JJTBLOCKSTATEMENT = 77; + + int JJTLOCALVARIABLEDECLARATION = 78; + + int JJTEMPTYSTATEMENT = 79; + + int JJTSTATEMENTEXPRESSION = 80; + + int JJTSWITCHSTATEMENT = 81; + + int JJTSWITCHLABEL = 82; + + int JJTIFSTATEMENT = 83; + + int JJTWHILESTATEMENT = 84; + + int JJTDOSTATEMENT = 85; + + int JJTFORSTATEMENT = 86; + + int JJTFORINIT = 87; + + int JJTSTATEMENTEXPRESSIONLIST = 88; + + int JJTFORUPDATE = 89; + + int JJTBREAKSTATEMENT = 90; + + int JJTCONTINUESTATEMENT = 91; + + int JJTRETURNSTATEMENT = 92; + + int JJTTHROWSTATEMENT = 93; + + int JJTSYNCHRONIZEDSTATEMENT = 94; + + int JJTTRYSTATEMENT = 95; + + int JJTRUNSIGNEDSHIFT = 96; + + int JJTRSIGNEDSHIFT = 97; + + int JJTANNOTATION = 98; + + int JJTNORMALANNOTATION = 99; + + int JJTMARKERANNOTATION = 100; + + int JJTSINGLEMEMBERANNOTATION = 101; + + int JJTMEMBERVALUEPAIRS = 102; + + int JJTMEMBERVALUEPAIR = 103; + + int JJTMEMBERVALUE = 104; + + int JJTMEMBERVALUEARRAYINITIALIZER = 105; + + int JJTANNOTATIONTYPEDECLARATION = 106; + + int JJTANNOTATIONTYPEBODY = 107; + + int JJTANNOTATIONTYPEMEMBERDECLARATION = 108; + + int JJTDEFAULTVALUE = 109; + + + String[] jjtNodeName = { + "Line", + "CompilationUnit", + "PackageDeclaration", + "ImportDeclaration", + "Modifiers", + "TypeDeclaration", + "ClassOrInterfaceDeclaration", + "ExtendsList", + "ImplementsList", + "EnumDeclaration", + "EnumBody", + "EnumConstant", + "TypeParameters", + "TypeParameter", + "TypeBound", + "ClassOrInterfaceBody", + "ClassOrInterfaceBodyDeclaration", + "FieldDeclaration", + "VariableDeclarator", + "VariableDeclaratorId", + "VariableInitializer", + "ArrayInitializer", + "MethodDeclaration", + "MethodDeclarator", + "FormalParameters", + "FormalParameter", + "ConstructorDeclaration", + "ExplicitConstructorInvocation", + "Initializer", + "Type", + "ReferenceType", + "ClassOrInterfaceType", + "TypeArguments", + "TypeArgument", + "WildcardBounds", + "PrimitiveType", + "ResultType", + "Name", + "NameList", + "Expression", + "AssignmentOperator", + "AssignmentExpression", + "ConditionalExpression", + "ConditionalOrExpression", + "ConditionalAndExpression", + "InclusiveOrExpression", + "ExclusiveOrExpression", + "AndExpression", + "EqualityExpression", + "InstanceOfExpression", + "RelationalExpression", + "ShiftExpression", + "AdditiveExpression", + "MultiplicativeExpression", + "UnaryExpression", + "PreIncrementExpression", + "PreDecrementExpression", + "UnaryExpressionNotPlusMinus", + "CastLookahead", + "PostfixExpression", + "PostfixOperator", + "CastExpression", + "PrimaryExpression", + "MemberSelector", + "PrimaryPrefix", + "PrimarySuffix", + "Literal", + "BooleanLiteral", + "NullLiteral", + "Arguments", + "ArgumentList", + "AllocationExpression", + "ArrayDimsAndInits", + "Statement", + "AssertStatement", + "LabeledStatement", + "Block", + "BlockStatement", + "LocalVariableDeclaration", + "EmptyStatement", + "StatementExpression", + "SwitchStatement", + "SwitchLabel", + "IfStatement", + "WhileStatement", + "DoStatement", + "ForStatement", + "ForInit", + "StatementExpressionList", + "ForUpdate", + "BreakStatement", + "ContinueStatement", + "ReturnStatement", + "ThrowStatement", + "SynchronizedStatement", + "TryStatement", + "RUNSIGNEDSHIFT", + "RSIGNEDSHIFT", + "Annotation", + "NormalAnnotation", + "MarkerAnnotation", + "SingleMemberAnnotation", + "MemberValuePairs", + "MemberValuePair", + "MemberValue", + "MemberValueArrayInitializer", + "AnnotationTypeDeclaration", + "AnnotationTypeBody", + "AnnotationTypeMemberDeclaration", + "DefaultValue", + }; +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/Node.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/Node.java new file mode 100644 index 0000000..645de07 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/Node.java @@ -0,0 +1,73 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. Node.java */ + + +package org.nuiton.jaxx.compiler.java.parser; + +/* All AST nodes must implement this interface. It provides basic + machinery for constructing the parent and child relationships + between nodes. */ + +public interface Node { + + /** + * This method is called after the node has been made the current + * node. It indicates that child nodes can now be added to it. + */ + void jjtOpen(); + + /** + * This method is called after all the child nodes have been + * added. + */ + void jjtClose(); + + /** + * This pair of methods are used to inform the node of its + * parent. + * + * @param n node + */ + void jjtSetParent(Node n); + + Node jjtGetParent(); + + /** + * This method tells the node to add its argument to the node's + * list of children. + * + * @param n node + * @param i index ? + */ + void jjtAddChild(Node n, int i); + + /** + * @param i index of child + * @return a child node. The children are numbered + * from zero, left to right. + */ + Node jjtGetChild(int i); + + /** @return the number of children the node has. */ + int jjtGetNumChildren(); +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/ParseException.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/ParseException.java new file mode 100644 index 0000000..59bc494 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/ParseException.java @@ -0,0 +1,240 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */ + +package org.nuiton.jaxx.compiler.java.parser; + +import org.nuiton.jaxx.compiler.CompilerException; + +/** + * This exception is thrown when parse errors are encountered. + * You can explicitly create objects of this exception type by + * calling the method generateParseException in the generated + * parser. + * + * You can modify this class to customize your error reporting + * mechanisms so long as you retain the public fields. + */ +public class ParseException extends CompilerException { + int line; + + int column; + + private static final long serialVersionUID = 6179854408401024700L; + + /** + * This constructor is used by the method "generateParseException" + * in the generated parser. Calling this constructor generates + * a new object of this type with the fields "currentToken", + * "expectedTokenSequences", and "tokenImage" set. The boolean + * flag "specialConstructor" is also set to true to indicate that + * this constructor was used to create this object. + * This constructor calls its super class with the empty string + * to force the "toString" method of parent class "Throwable" to + * print the error message in the form: + * ParseException: <result of getMessage> + * + * @param currentTokenVal ? + * @param expectedTokenSequencesVal ? + * @param tokenImageVal ? + */ + public ParseException(Token currentTokenVal, + int[][] expectedTokenSequencesVal, + String[] tokenImageVal + ) { + super(""); + specialConstructor = true; + currentToken = currentTokenVal; + expectedTokenSequences = expectedTokenSequencesVal; + tokenImage = tokenImageVal; + } + + /** + * The following constructors are for use by you for whatever + * purpose you can think of. Constructing the exception in this + * manner makes the exception behave in the normal way - i.e., as + * documented in the class "Throwable". The fields "errorToken", + * "expectedTokenSequences", and "tokenImage" do not contain + * relevant information. The JavaCC generated code does not use + * these constructors. + */ + + public ParseException() { + super(); + specialConstructor = false; + } + + public ParseException(String message) { + super(message); + specialConstructor = false; + } + + public ParseException(String message, int line, int column) { + super(message); + specialConstructor = false; + this.line = line; + this.column = column; + } + + + /** + * This variable determines which constructor was used to create + * this object and thereby affects the semantics of the + * "getMessage" method (see below). + */ + protected boolean specialConstructor; + + /** + * This is the last token that has been consumed successfully. If + * this object has been created due to a parse error, the token + * followng this token will (therefore) be the first error token. + */ + public Token currentToken; + + /** + * Each entry in this array is an array of integers. Each array + * of integers represents a sequence of tokens (by their ordinal + * values) that is expected at this point of the parse. + */ + public int[][] expectedTokenSequences; + + /** + * This is a reference to the "tokenImage" array of the generated + * parser within which the parse error occurred. This array is + * defined in the generated ...Constants interface. + */ + public String[] tokenImage; + + /** + * This method has the standard behavior when this object has been + * created using the standard constructors. Otherwise, it uses + * "currentToken" and "expectedTokenSequences" to generate a parse + * error message and returns it. If this object has been created + * due to a parse error, and you do not catch it (it gets thrown + * from the parser), then this method is called during the printing + * of the final stack trace, and hence the correct error message + * gets displayed. + */ + public String getMessage() { + if (!specialConstructor) { + return super.getMessage(); + } + StringBuilder expected = new StringBuilder(); + int maxSize = 0; + for (int[] expectedTokenSequence : expectedTokenSequences) { + if (maxSize < expectedTokenSequence.length) { + maxSize = expectedTokenSequence.length; + } + for (int anExpectedTokenSequence : expectedTokenSequence) { + expected.append(tokenImage[anExpectedTokenSequence]).append(" "); + } + if (expectedTokenSequence[expectedTokenSequence.length - 1] != 0) { + expected.append("..."); + } + expected.append(eol).append(" "); + } + String retval = "Encountered \""; + Token tok = currentToken.next; + for (int i = 0; i < maxSize; i++) { + if (i != 0) retval += " "; + if (tok.kind == 0) { + retval += tokenImage[0]; + break; + } + retval += add_escapes(tok.image); + tok = tok.next; + } + retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; + retval += "." + eol; + if (expectedTokenSequences.length == 1) { + retval += "Was expecting:" + eol + " "; + } else { + retval += "Was expecting one of:" + eol + " "; + } + retval += expected.toString(); + return retval; + } + + + public int getLine() { + return line; + } + + public int getColumn() { + return column; + } + + /** The end of line string for this machine. */ + protected String eol = System.getProperty("line.separator", "\n"); + + /** + * Used to convert raw characters to their escaped version + * when these raw version cannot be used as part of an ASCII + * string literal. + * + * @param str text to treate + * @return the escaped version of text + */ + protected String add_escapes(String str) { + StringBuilder retval = new StringBuilder(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) { + case 0: + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u").append(s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + } + } + return retval.toString(); + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/SimpleNode.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/SimpleNode.java new file mode 100644 index 0000000..e709676 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/SimpleNode.java @@ -0,0 +1,163 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. SimpleNode.java */ + + +package org.nuiton.jaxx.compiler.java.parser; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; + +public class SimpleNode implements Node { + protected Node parent; + + protected Node[] children; + + protected int id; + + protected JavaParser parser; + + public Token firstToken; + + public Token lastToken; + + private ClassDescriptor javaType; + + + public SimpleNode(int i) { + id = i; + } + + public SimpleNode(JavaParser p, int i) { + this(i); + parser = p; + } + + + public int getId() { + return id; + } + + public void jjtOpen() { + } + + public void jjtClose() { + } + + public void jjtSetParent(Node n) { + parent = n; + } + + public Node jjtGetParent() { + return parent; + } + + public SimpleNode getParent() { + return (SimpleNode) parent; + } + + + public ClassDescriptor getJavaType() { + return javaType; + } + + + public void setJavaType(ClassDescriptor javaType) { + this.javaType = javaType; + } + + public void jjtAddChild(Node n, int i) { + if (children == null) { + children = new Node[i + 1]; + } else if (i >= children.length) { + Node c[] = new Node[i + 1]; + System.arraycopy(children, 0, c, 0, children.length); + children = c; + } + children[i] = n; + } + + public Node jjtGetChild(int i) { + return children[i]; + } + + public SimpleNode getChild(int i) { + return (SimpleNode) children[i]; + } + + public int jjtGetNumChildren() { + return (children == null) ? 0 : children.length; + } + + /* You can override these two methods in subclasses of SimpleNode to +customize the way the node appears when the tree is dumped. If +your output uses more than one line you should override +toString(String), otherwise overriding toString() is probably all +you need to do. */ + + @Override + public String toString() { + return getClass().getName() + "[" + getText() + "]"; + } + + public String toString(String prefix) { + return prefix + toString(); + } + + /* Override this method if you want to customize how the node dumps + out its children. */ + + public void dump(String prefix) { + System.out.println(toString(prefix)); + if (children != null) { + for (Node aChildren : children) { + SimpleNode n = (SimpleNode) aChildren; + if (n != null) { + n.dump(prefix + " "); + } + } + } + } + + private void appendSpecialTokens(StringBuilder s, Token st) { + if (st != null) { + appendSpecialTokens(s, st.specialToken); + s.append(st.image); + } + } + + + /** @return the text of the tokens comprising this node. */ + public String getText() { + StringBuilder text = new StringBuilder(); + Token t = firstToken; + while (t != null) { + appendSpecialTokens(text, t.specialToken); + text.append(t.image); + if (t == lastToken) + break; + t = t.next; + } + + return text.toString(); + } +} + diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/Token.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/Token.java new file mode 100644 index 0000000..52cf807 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/Token.java @@ -0,0 +1,101 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */ + +package org.nuiton.jaxx.compiler.java.parser; + +/** Describes the input token stream. */ + +public class Token { + /** + * An integer that describes the kind of this token. This numbering + * system is determined by JavaCCParser, and a table of these numbers is + * stored in the file ...Constants.java. + */ + public int kind; + + /** + * beginLine and beginColumn describe the position of the first character + * of this token; endLine and endColumn describe the position of the + * last character of this token. + */ + public int beginLine, beginColumn, endLine, endColumn; + + /** The string image of the token. */ + public String image; + + /** + * A reference to the next regular (non-special) token from the input + * stream. If this is the last token from the input stream, or if the + * token manager has not read tokens beyond this one, this field is + * set to null. This is true only if this token is also a regular + * token. Otherwise, see below for a description of the contents of + * this field. + */ + public Token next; + + /** + * This field is used to access special tokens that occur prior to this + * token, but after the immediately preceding regular (non-special) token. + * If there are no such special tokens, this field is set to null. + * When there are more than one such special token, this field refers + * to the last of these special tokens, which in turn refers to the next + * previous special token through its specialToken field, and so on + * until the first special token (whose specialToken field is null). + * The next fields of special tokens refer to other special tokens that + * immediately follow it (without an intervening regular token). If there + * is no such token, this field is null. + */ + public Token specialToken; + + /** Returns the image. */ + public String toString() { + return image; + } + + /** + * Returns a new Token object, by default. However, if you want, you + * can create and return subclass objects based on the value of ofKind. + * Simply add the cases to the switch for all those special cases. + * For example, if you have a subclass of Token called IDToken that + * you want to create if ofKind is ID, simlpy add something like : + * + * case MyParserConstants.ID : return new IDToken(); + * + * to the following switch statement. Then you can cast matchedToken + * variable to the appropriate type and use it in your lexical actions. + */ + public static final Token newToken(int ofKind) { + switch (ofKind) { + default: + return new Token(); + case JavaParserConstants.RUNSIGNEDSHIFT: + case JavaParserConstants.RSIGNEDSHIFT: + case JavaParserConstants.GT: + return new GTToken(); + } + } + + public static class GTToken extends Token { + int realKind = JavaParserConstants.GT; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/TokenMgrError.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/TokenMgrError.java new file mode 100644 index 0000000..6a2f46d --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/java/parser/TokenMgrError.java @@ -0,0 +1,149 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */ + +package org.nuiton.jaxx.compiler.java.parser; + +public class TokenMgrError extends Error { + /* + * Ordinals for various reasons why an Error of this type can be thrown. + */ + + /** Lexical error occured. */ + static final int LEXICAL_ERROR = 0; + + /** An attempt wass made to create a second instance of a static token manager. */ + static final int STATIC_LEXER_ERROR = 1; + + /** Tried to change to an invalid lexical state. */ + static final int INVALID_LEXICAL_STATE = 2; + + /** Detected (and bailed out of) an infinite loop in the token manager. */ + static final int LOOP_DETECTED = 3; + + /** + * Indicates the reason why the exception is thrown. It will have + * one of the above 4 values. + */ + int errorCode; + + private static final long serialVersionUID = -9131500865453532454L; + + /** + * Replaces unprintable characters by their espaced (or unicode escaped) + * equivalents in the given string + * + * @param str text to treate + * @return the treated text + */ + protected static String addEscapes(String str) { + StringBuilder retval = new StringBuilder(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) { + case 0: + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u").append(s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + } + } + return retval.toString(); + } + + /** + * @param EOFSeen : indicates if EOF caused the lexicl error + * @param lexState : lexical state in which this error occured + * @param errorLine : line number when the error occured + * @param errorColumn : column number when the error occured + * @param errorAfter : prefix that was seen before this error occured + * @param curChar : the offending character + * Note: You can customize the lexical error message by modifying this method. + * @return a detailed message for the Error when it is thrown by the + * token manager to indicate a lexical error. + */ + protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { + return "Lexical error at line " + + errorLine + ", column " + + errorColumn + ". Encountered: " + + (EOFSeen ? "<EOF> " : "\"" + addEscapes(String.valueOf(curChar)) + "\"" + " (" + (int) curChar + "), ") + + "after : \"" + addEscapes(errorAfter) + "\""; + } + + /** + * You can also modify the body of this method to customize your error messages. + * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not + * of end-users concern, so you can return something like : + * + * "Internal Error : Please file a bug report .... " + * + * from this method for such cases in the release version of your parser. + */ + @Override + public String getMessage() { + return super.getMessage(); + } + + /* + * Constructors of various flavors follow. + */ + + public TokenMgrError() { + } + + public TokenMgrError(String message, int reason) { + super(message); + errorCode = reason; + } + + public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { + this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/ClassDescriptor.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/ClassDescriptor.java new file mode 100644 index 0000000..e4a6267 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/ClassDescriptor.java @@ -0,0 +1,295 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.reflect; + +import org.nuiton.jaxx.runtime.JAXXObjectDescriptor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.Arrays; + +/** + * Mirrors the class <code>java.lang.Class</code>. JAXX uses <code>ClassDescriptor</code> instead of <code>Class</code> + * almost everywhere so that it can handle circular dependencies (there can't be a <code>Class</code> object for an uncompiled + * JAXX or Java source file, and a compiler must be allow references to symbols in uncompiled source files in order to handle + * circular dependencies). + */ +public abstract class ClassDescriptor { + + /** Logger. */ + private static final Log log = LogFactory.getLog(ClassDescriptor.class); + + public static final FieldDescriptor[] EMPTY_FIELD_DESCRIPTORS_ARRAY = + new FieldDescriptor[0]; + + private String name; + + private String packageName; + + private String superclass; + + private String[] interfaces; + + private boolean isInterface; + + private boolean isArray; + + private String componentType; + + private JAXXObjectDescriptor jaxxObjectDescriptor; + + private ClassLoader classLoader; + + private MethodDescriptor[] constructorDescriptors; + + private MethodDescriptor[] methodDescriptors; + + private FieldDescriptor[] fieldDescriptors; + + protected FieldDescriptor[] declaredFieldDescriptors; + + protected final ClassDescriptorHelper.ResolverType resolverType; + + public abstract MethodDescriptor getDeclaredMethodDescriptor( + String name, + ClassDescriptor... parameterTypes) throws NoSuchMethodException; + +// public abstract FieldDescriptor getDeclaredFieldDescriptor( +// String name) throws NoSuchFieldException; + + public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { + for (FieldDescriptor descriptor : declaredFieldDescriptors) { + if (name.equals(descriptor.getName())) { + if (log.isDebugEnabled()) { + log.debug("Using a declared field descriptor [" + name + + "] for " + getName()); + } + return descriptor; + } + } + throw new NoSuchFieldException(name); + } + + protected ClassDescriptor(ClassDescriptorHelper.ResolverType resolverType, + String name, + String packageName, + String superclass, + String[] interfaces, + boolean isInterface, + boolean isArray, + String componentType, + JAXXObjectDescriptor jaxxObjectDescriptor, + ClassLoader classLoader, + MethodDescriptor[] constructorDescriptors, + MethodDescriptor[] methodDescriptors, + FieldDescriptor[] fieldDescriptors) { + this( + resolverType, name, + packageName, + superclass, + interfaces, + isInterface, + isArray, + componentType, + jaxxObjectDescriptor, + classLoader, + constructorDescriptors, + methodDescriptors, + fieldDescriptors, + null + ); + } + + protected ClassDescriptor( + ClassDescriptorHelper.ResolverType resolverType, + String name, + String packageName, + String superclass, + String[] interfaces, + boolean isInterface, + boolean isArray, + String componentType, + JAXXObjectDescriptor jaxxObjectDescriptor, + ClassLoader classLoader, + MethodDescriptor[] constructorDescriptors, + MethodDescriptor[] methodDescriptors, + FieldDescriptor[] fieldDescriptors, + FieldDescriptor[] declaredFieldDescriptors) { + this.resolverType = resolverType; + this.name = name; + this.packageName = packageName; + this.superclass = superclass; + this.interfaces = interfaces; + this.isInterface = isInterface; + this.isArray = isArray; + this.componentType = componentType; + this.jaxxObjectDescriptor = jaxxObjectDescriptor; + this.classLoader = classLoader; + this.constructorDescriptors = constructorDescriptors; + this.methodDescriptors = methodDescriptors; + this.fieldDescriptors = fieldDescriptors; + this.declaredFieldDescriptors = declaredFieldDescriptors; + } + + + public ClassDescriptorHelper.ResolverType getResolverType() { + return resolverType; + } + + public String getName() { + return name; + } + + public String getSimpleName() { + int dot = name.lastIndexOf("."); + return dot == -1 ? name : name.substring(dot + 1); + } + + public String getPackageName() { + return packageName; + } + + public ClassDescriptor getSuperclass() { + return getClassDescriptor(superclass); + + } + + public ClassDescriptor[] getInterfaces() { + ClassDescriptor[] result = new ClassDescriptor[interfaces.length]; + for (int i = 0; i < result.length; i++) { + result[i] = getClassDescriptor(interfaces[i]); + } + return result; + } + + public boolean isInterface() { + return isInterface; + } + + public boolean isArray() { + return isArray; + } + + public ClassDescriptor getComponentType() { + return getClassDescriptor(componentType); + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public MethodDescriptor[] getConstructorDescriptors() { + return constructorDescriptors; + } + + public MethodDescriptor[] getMethodDescriptors() { + return methodDescriptors; + } + + public MethodDescriptor getMethodDescriptor(String name, + ClassDescriptor... parameterTypes) throws NoSuchMethodException { + for (MethodDescriptor m : methodDescriptors) { + if (m.getName().equals(name) && + m.getParameterTypes().length == parameterTypes.length && + Arrays.equals(m.getParameterTypes(), parameterTypes)) { + return m; + } + } + throw new NoSuchMethodException( + "Could not find method " + name + "(" + + Arrays.asList(parameterTypes) + ") in " + getName()); + } + + public FieldDescriptor[] getFieldDescriptors() { + return fieldDescriptors; + } + + public FieldDescriptor[] getDeclaredFieldDescriptors() { + return declaredFieldDescriptors == null ? EMPTY_FIELD_DESCRIPTORS_ARRAY : declaredFieldDescriptors; + } + + public FieldDescriptor getFieldDescriptor(String name) throws NoSuchFieldException { + for (FieldDescriptor fieldDescriptor : fieldDescriptors) { + if (fieldDescriptor.getName().equals(name)) { + return fieldDescriptor; + } + } + throw new NoSuchFieldException( + "Could not find field " + name + " in " + getName()); + } + + public JAXXObjectDescriptor getJAXXObjectDescriptor() { + return jaxxObjectDescriptor; + } + + public boolean isAssignableFrom(ClassDescriptor descriptor) { + while (descriptor != null) { + if (equals(descriptor)) { + return true; + } + for (ClassDescriptor anInterface : descriptor.getInterfaces()) { + if (equals(anInterface) || isAssignableFrom(anInterface)) { + return true; + } + } + descriptor = descriptor.getSuperclass(); + } + return false; + } + + @Override + public String toString() { + return "ClassDescriptor[" + getName() + "]"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ClassDescriptor)) return false; + + ClassDescriptor that = (ClassDescriptor) o; + + return name.equals(that.name); + + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + protected ClassDescriptor getClassDescriptor(String fqn) { + if (fqn == null) { + return null; + } + + try { + return ClassDescriptorHelper.getClassDescriptor( + fqn, + getClassLoader() + ); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/ClassDescriptorHelper.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/ClassDescriptorHelper.java new file mode 100644 index 0000000..98daf67 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/ClassDescriptorHelper.java @@ -0,0 +1,533 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.reflect; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXCompilerFile; +import org.nuiton.jaxx.compiler.JAXXEngine; +import org.nuiton.jaxx.compiler.JAXXFactory; +import org.nuiton.jaxx.compiler.reflect.resolvers.ClassDescriptorResolverFromJavaClass; +import org.nuiton.jaxx.compiler.reflect.resolvers.ClassDescriptorResolverFromJavaFile; +import org.nuiton.jaxx.compiler.reflect.resolvers.ClassDescriptorResolverFromJaxxFile; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.JAXXObjectDescriptor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; + +/** + * Mirrors the class <code>java.lang.ClassLoader</code>. JAXX uses <code>ClassDescriptor</code> instead of <code>Class</code> + * almost everywhere so that it can handle circular dependencies (there can't be a <code>Class</code> object for an uncompiled + * JAXX or Java source file, and a compiler must be allow references to symbols in uncompiled source files in order to handle + * circular dependencies). + * + * <b>Note : </b> Was previously {@code ClassDescriptorLoader}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class ClassDescriptorHelper { + + /** Logger */ + private static final Log log = LogFactory.getLog(ClassDescriptorHelper.class); + + /** + * Constants to define who load a {@link ClassDescriptor}. + * + * This will be usefull in some case (for consturctor for example when some + * descriptors are not fully loaded... + * + * @since 2.4 + */ + public enum ResolverType { + JAVA_CLASS, + JAVA_FILE, + JAXX_FILE + } + + private static boolean SHOW_LOADING = log.isDebugEnabled(); + + private static Map<String, ClassDescriptor> descriptors = + new HashMap<>(); + + private static Map<ResolverType, ClassDescriptorResolver> descriptorResolvers; + + protected static Map<ResolverType, ClassDescriptorResolver> getDescriptorResolvers() { + if (descriptorResolvers == null) { + descriptorResolvers = new EnumMap<>(ResolverType.class); + descriptorResolvers.put(ResolverType.JAVA_CLASS, new ClassDescriptorResolverFromJavaClass()); + descriptorResolvers.put(ResolverType.JAVA_FILE, new ClassDescriptorResolverFromJavaFile()); + descriptorResolvers.put(ResolverType.JAXX_FILE, new ClassDescriptorResolverFromJaxxFile()); + } + return descriptorResolvers; + } + + private ClassDescriptorHelper() { + // on instance + } + + public static boolean isAssignableFrom(ClassDescriptor classDescriptor, + Class<?> awareClass) throws ClassNotFoundException { + ClassDescriptor awareDescriptor = getClassDescriptor(awareClass); + return awareDescriptor.isAssignableFrom(classDescriptor); + } + + public static ClassDescriptor getClassDescriptor(String className) throws ClassNotFoundException { + + return getClassDescriptor(className, + Thread.currentThread().getContextClassLoader()); + } + + public static ClassDescriptor getClassDescriptor(Class<?> javaClass) { + try { + return getClassDescriptor(javaClass.getName(), + javaClass.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + public static URL getURL(ClassLoader classLoader, String className, String clasifier) { + String relativePath = className.replaceAll("\\.", "/"); + String path = relativePath + "." + clasifier; + if (log.isDebugEnabled()) { + log.debug("Path to search : " + path); + } + return classLoader.getResource(path); + } + + public static ClassDescriptor getClassDescriptor( + String className, + ClassLoader classLoader) throws ClassNotFoundException { + + if (classLoader == null) { + classLoader = ClassDescriptorHelper.class.getClassLoader(); + } + + ClassDescriptor result = descriptors.get(className); + if (result != null) { + + // found in cache + if (log.isTraceEnabled()) { + log.trace("resolved " + result + " from cache."); + } + return result; + } + + JAXXEngine engine = JAXXFactory.isEngineRegistred() ? + JAXXFactory.getEngine() : null; + + String relativePathPattern = ".*";// + className + ".*"; // used to ensure that the located resource has the right character cases + + if (engine != null) { + + JAXXCompilerFile file = engine.getJAXXCompilerFile(className); + + if (file != null) { + + // use the symbole table of this jaxx file on computation + + if (SHOW_LOADING) { + log.info("from JAXXFile " + file.getJaxxFile()); + } + result = getClassDescriptor0( + ResolverType.JAXX_FILE, + className, + file.getJAXXFileURL(), + classLoader + ); + + if (log.isDebugEnabled()) { + log.debug("[" + className + "] loaded"); + } + + return result; + } + } + + // the class is not in this compile set, try to have it from java + // sources or classes. + + // find the most recently updated source for the class -- Java source, JAXX source, or compiled class file + long javaLastModified = -1; + URL javaFile = getURL(classLoader, className, "java"); + if (javaFile != null && + javaFile.toString().startsWith("file:") && + javaFile.toString().matches(relativePathPattern)) { + javaLastModified = JAXXCompiler.URLtoFile(javaFile).lastModified(); + if (log.isTraceEnabled()) { + log.trace("[" + className + "] javaFile lastModified " + javaLastModified); + } + } + + long classLastModified = -1; + URL classFile = getURL(classLoader, className, "class"); + if (classFile != null && + classFile.toString().startsWith("file:") && + classFile.toString().matches(relativePathPattern)) { + classLastModified = JAXXCompiler.URLtoFile(classFile).lastModified(); + if (log.isTraceEnabled()) { + log.trace("[" + className + "] class lastModified " + classLastModified); + } + } + + // there is a java source and is the last modified + if (javaLastModified != -1 && javaLastModified > classLastModified) { + + // java file exist and it is the last modified file, so use it + + if (SHOW_LOADING) { + log.info("from JavaFile " + javaFile); + } + + result = getClassDescriptor0( + ResolverType.JAVA_FILE, + className, + javaFile, + classLoader + ); + + if (log.isDebugEnabled()) { + log.debug("[" + className + "] loaded"); + } + return result; + } + + // use the class ... + + if (SHOW_LOADING) { + log.info("from class " + className); + } + + result = getClassDescriptor0( + ResolverType.JAVA_CLASS, + className, + classFile, + classLoader + ); + + if (log.isDebugEnabled()) { + log.debug("[" + className + "] loaded"); + } + + if (result != null) { + return result; + } + + // can NOT come here, means could not find result... + + throw new IllegalStateException( + "Can not find descriptor for " + className); + } + + protected static ClassDescriptor getClassDescriptor0( + ResolverType resolverType, + String className, + URL source, + ClassLoader classLoader) throws ClassNotFoundException { + + if (log.isDebugEnabled()) { + log.debug("Loading class descriptor for [" + className + + "] with " + resolverType); + } + + Map<ResolverType, ClassDescriptorResolver> resolvers = + getDescriptorResolvers(); + + ClassDescriptorResolver resolver = resolvers.get(resolverType); + + resolver.setClassLoader(classLoader); + + ClassDescriptor result = resolver.resolvDescriptor(className, source); + if (result != null) { + descriptors.put(className, result); + } + return result; + } + + public static Class<?> getPrimitiveBoxedClass(String className) { + if (className.equals("boolean")) { + return Boolean.class; + } + if (className.equals("byte")) { + return Byte.class; + } + if (className.equals("short")) { + return Short.class; + } + if (className.equals("int")) { + return Integer.class; + } + if (className.equals("long")) { + return Long.class; + } + if (className.equals("float")) { + return Float.class; + } + if (className.equals("double")) { + return Double.class; + } + if (className.equals("char")) { + return Character.class; + } + if (className.equals("void")) { + return Void.class; + } + return null; + } + + public static Class<?> getPrimitiveClass( + String className) throws ClassNotFoundException { + if (className.equals("boolean")) { + return boolean.class; + } + if (className.equals("byte")) { + return byte.class; + } + if (className.equals("short")) { + return short.class; + } + if (className.equals("int")) { + return int.class; + } + if (className.equals("long")) { + return long.class; + } + if (className.equals("float")) { + return float.class; + } + if (className.equals("double")) { + return double.class; + } + if (className.equals("char")) { + return char.class; + } + if (className.equals("void")) { + return void.class; + } + // detect arrays + int arrayCount = 0; + while (className.endsWith("[]")) { + arrayCount++; + className = className.substring(0, className.length() - 2); + } + Class<?> klass; + if (arrayCount > 0) { + klass = getPrimitiveClass(className); + if (klass == null) { + // none primitive array + return null; + } + // must take the boxed class, other it does not works + // to make a Class.forName("[Lchar;"); but works + // with Class.forName("[LCharacter;"); ... + klass = getPrimitiveBoxedClass(className); + className = klass.getName(); + + className = "L" + className + ";"; + while (arrayCount > 0) { + className = "[" + className; + arrayCount--; + } + //System.out.println("primitive array class "+className); + return Class.forName(className); + } + return null; + } + + public static Class<?> getClass(String className, + ClassLoader classLoader) throws ClassNotFoundException { + Class<?> klass = getPrimitiveClass(className); + if (klass != null) { + return klass; + } + // try an array of none primitive classes + int arrayCount = 0; + while (className.endsWith("[]")) { + arrayCount++; + className = className.substring(0, className.length() - 2); + } + if (arrayCount > 0) { + className = "L" + className + ";"; + while (arrayCount > 0) { + className = "[" + className; + arrayCount--; + } + } + try { + return classLoader != null ? + Class.forName(className, true, classLoader) : + Class.forName(className); + + } catch (ClassNotFoundException e) { + // perharps we are in a inner class ? + int dotIndex = className.lastIndexOf("."); + if (dotIndex > -1) { + String parentFQN = className.substring(0, dotIndex); + String simpleName = className.substring(dotIndex + 1); + try { + Class<?> parentClass = classLoader != null ? Class.forName(parentFQN, true, classLoader) : Class.forName(parentFQN); + for (Class<?> innerClass : parentClass.getClasses()) { + if (simpleName.equals(innerClass.getSimpleName())) { + return innerClass; + } + } + } catch (ClassNotFoundException e1) { + // no super class,so let the first exception throw... + } + } + throw e; + } catch (NoClassDefFoundError e) { + + throw new ClassNotFoundException(e.toString()); + } + } + +// private static MethodDescriptor createMethodDescriptor(Method javaMethod, +// ClassLoader classLoader) { +// String methodName = javaMethod.getName(); +// int modifiers = javaMethod.getModifiers(); +// String returnType = javaMethod.getReturnType().getName(); +// Class<?>[] javaParameters = javaMethod.getParameterTypes(); +// String[] parameters = new String[javaParameters.length]; +// for (int i = 0; i < parameters.length; i++) { +// parameters[i] = javaParameters[i].getName(); +// } +// return new MethodDescriptor(methodName, modifiers, returnType, parameters, classLoader); +// } +// +// private static FieldDescriptor createFieldDescriptor(Field javaField, +// ClassLoader classLoader) { +// String fieldName = javaField.getName(); +// int modifiers = javaField.getModifiers(); +// String type = javaField.getType().getName(); +// return new FieldDescriptor(fieldName, modifiers, type, classLoader); +// } +// +// private static JAXXObjectDescriptor getJAXXObjectDescriptor(Class<?> jaxxClass) { +// if (!JAXXObject.class.isAssignableFrom(jaxxClass) || +// JAXXObject.class.equals(jaxxClass)) { +// return null; +// } +// try { +// Method getJAXXObjectDescriptor = jaxxClass.getMethod("$getJAXXObjectDescriptor"); +// return (JAXXObjectDescriptor) getJAXXObjectDescriptor.invoke(null); +// } catch (NoSuchMethodException e) { +// throw new CompilerException("Expected JAXXObject " + jaxxClass.getName() + " to have a static method named $getJAXXObjectDescriptor"); +// } catch (IllegalAccessException e) { +// throw new CompilerException("Expected JAXXObject " + jaxxClass.getName() + "'s $getJAXXObjectDescriptor method to be public"); +// } catch (InvocationTargetException e) { +// throw new RuntimeException(e); +// } +// } + + public static void checkSupportClass(Class<?> handlerClass, + ClassDescriptor beanClass, + Class<?>... tagClasses) { + for (Class<?> tagClass : tagClasses) { + if (getClassDescriptor(tagClass).isAssignableFrom(beanClass)) { + return; + } + } + throw new IllegalArgumentException(handlerClass.getName() + " does not support the class " + beanClass.getName()); + } + + public static void reset() { + descriptors.clear(); + } + + public static MethodDescriptor createMethodDescriptor(Method javaMethod, + ClassLoader classLoader) { + String methodName = javaMethod.getName(); + int modifiers = javaMethod.getModifiers(); + String returnType = javaMethod.getReturnType().getName(); + Class<?>[] javaParameters = javaMethod.getParameterTypes(); + String[] parameters = new String[javaParameters.length]; + for (int i = 0; i < parameters.length; i++) { + parameters[i] = javaParameters[i].getName(); + } + return new MethodDescriptor(methodName, + modifiers, + returnType, + parameters, + classLoader + ); + } + + public static MethodDescriptor createMethodDescriptor(Constructor<?> javaMethod, + ClassLoader classLoader) { + String methodName = javaMethod.getName(); + int modifiers = javaMethod.getModifiers(); + String returnType = null; + Class<?>[] javaParameters = javaMethod.getParameterTypes(); + String[] parameters = new String[javaParameters.length]; + for (int i = 0; i < parameters.length; i++) { + parameters[i] = javaParameters[i].getName(); + } + return new MethodDescriptor(methodName, + modifiers, + returnType, + parameters, + classLoader + ); + } + + public static FieldDescriptor createFieldDescriptor(Field javaField, + ClassLoader classLoader) { + String fieldName = javaField.getName(); + int modifiers = javaField.getModifiers(); + String type = javaField.getType().getName(); + return new FieldDescriptor(fieldName, modifiers, type, classLoader); + } + + public static JAXXObjectDescriptor getJAXXObjectDescriptor(Class<?> jaxxClass) { + if (!JAXXObject.class.isAssignableFrom(jaxxClass) || + JAXXObject.class.equals(jaxxClass) || + jaxxClass.isInterface()) { + return null; + } + try { + Method getJAXXObjectDescriptor = jaxxClass.getMethod("$getJAXXObjectDescriptor"); + return (JAXXObjectDescriptor) getJAXXObjectDescriptor.invoke(null); + } catch (NoSuchMethodException e) { + throw new CompilerException("Expected JAXXObject " + jaxxClass.getName() + " to have a static method named $getJAXXObjectDescriptor"); + } catch (IllegalAccessException e) { + throw new CompilerException("Expected JAXXObject " + jaxxClass.getName() + "'s $getJAXXObjectDescriptor method to be public"); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + public static void setShowLoading(boolean b) { + SHOW_LOADING = b; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/ClassDescriptorResolver.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/ClassDescriptorResolver.java new file mode 100644 index 0000000..052d899 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/ClassDescriptorResolver.java @@ -0,0 +1,67 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.reflect; + +import java.net.URL; + +/** + * Contract of a resolver of class descriptor. + * + * The unique method {@link #resolvDescriptor(String, URL)} will returns the + * descriptor if can be found. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public abstract class ClassDescriptorResolver { + + private ClassLoader classLoader; + + private ClassDescriptorHelper.ResolverType resolverType; + + protected ClassDescriptorResolver(ClassDescriptorHelper.ResolverType resolverType) { + this.resolverType = resolverType; + } + + public ClassDescriptorHelper.ResolverType getResolverType() { + return resolverType; + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + /** + * @param className the fully qualified name of the class + * @param source the source of the class (java file, jaxx file, class) + * @return the descriptor of the given class + * @throws ClassNotFoundException if class descriptor could not be found. + */ + public abstract ClassDescriptor resolvDescriptor(String className, + URL source) throws ClassNotFoundException; + + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/FieldDescriptor.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/FieldDescriptor.java new file mode 100644 index 0000000..2c1805d --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/FieldDescriptor.java @@ -0,0 +1,54 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.reflect; + +/** + * Mirrors the class <code>java.lang.ref.Field</code>. JAXX uses <code>ClassDescriptor</code> instead of <code>Class</code> + * almost everywhere so that it can handle circular dependencies (there can't be a <code>Class</code> object for an uncompiled + * JAXX or Java source file, and a compiler must be allow references to symbols in uncompiled source files in order to handle + * circular dependencies). + */ +public class FieldDescriptor extends MemberDescriptor { + + private String type; + + public FieldDescriptor(String name, int modifiers, String type, ClassLoader classLoader) { + super(name, modifiers, classLoader); + this.type = type; + } + + public ClassDescriptor getType() { + try { + return ClassDescriptorHelper.getClassDescriptor(type, getClassLoader()); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Type not found for field " + this, e); + } catch (Exception e) { + throw new RuntimeException("Type not found for field " + this, e); + } + } + + @Override + public String toString() { + return super.toString() + " type : [" + type + "]"; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/MemberDescriptor.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/MemberDescriptor.java new file mode 100644 index 0000000..3cf4b9b --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/MemberDescriptor.java @@ -0,0 +1,61 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.reflect; + +/** + * Mirrors the class <code>java.lang.ref.Member</code>. JAXX uses <code>ClassDescriptor</code> instead of <code>Class</code> + * almost everywhere so that it can handle circular dependencies (there can't be a <code>Class</code> object for an uncompiled + * JAXX or Java source file, and a compiler must be allow references to symbols in uncompiled source files in order to handle + * circular dependencies). + */ +public abstract class MemberDescriptor { + + private String name; + + private int modifiers; + + private ClassLoader classLoader; + + MemberDescriptor(String name, int modifiers, ClassLoader classLoader) { + this.name = name; + this.modifiers = modifiers; + this.classLoader = classLoader; + } + + public String getName() { + return name; + } + + public int getModifiers() { + return modifiers; + } + + protected ClassLoader getClassLoader() { + return classLoader; + } + + @Override + public String toString() { + return getClass().getName() + "[" + getName() + "]"; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/MethodDescriptor.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/MethodDescriptor.java new file mode 100644 index 0000000..dabc5ca --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/MethodDescriptor.java @@ -0,0 +1,75 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.reflect; + +import org.nuiton.jaxx.compiler.JAXXCompiler; + +import java.util.Arrays; + +/** + * Mirrors the class <code>java.lang.ref.Method</code>. JAXX uses <code>ClassDescriptor</code> instead of <code>Class</code> + * almost everywhere so that it can handle circular dependencies (there can't be a <code>Class</code> object for an uncompiled + * JAXX or Java source file, and a compiler must be allow references to symbols in uncompiled source files in order to handle + * circular dependencies). + */ +public class MethodDescriptor extends MemberDescriptor { + + private String returnType; + + private String[] parameterTypes; + + public MethodDescriptor(String name, int modifiers, String returnType, String[] parameterTypes, ClassLoader classLoader) { + super(name, modifiers, classLoader); + this.returnType = returnType; + this.parameterTypes = parameterTypes; + if (JAXXCompiler.STRICT_CHECKS && Arrays.asList(parameterTypes).contains(null)) { + throw new NullPointerException(name); + } + } + + public ClassDescriptor getReturnType() { + try { + //TC 20090228 : fix bug when no return type defined (constructor method) + if (returnType == null) { + return null; + } + return ClassDescriptorHelper.getClassDescriptor(returnType); + } catch (ClassNotFoundException e) { + throw new RuntimeException("could not find return type " + returnType, e); + } + } + + public ClassDescriptor[] getParameterTypes() { + ClassDescriptor[] result = new ClassDescriptor[parameterTypes.length]; + try { + for (int i = 0; i < result.length; i++) { + if (parameterTypes[i] != null) { + result[i] = ClassDescriptorHelper.getClassDescriptor(parameterTypes[i], getClassLoader()); + } + } + return result; + } catch (ClassNotFoundException e) { + throw new RuntimeException("could not find the parameter types " + Arrays.toString(parameterTypes), e); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaClass.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaClass.java new file mode 100644 index 0000000..178e31a --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaClass.java @@ -0,0 +1,200 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.reflect.resolvers; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorResolver; +import org.nuiton.jaxx.compiler.reflect.FieldDescriptor; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; +import org.nuiton.jaxx.runtime.JAXXObjectDescriptor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.URL; + +/** + * To obtain a class descriptor from a java source file. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class ClassDescriptorResolverFromJavaClass extends ClassDescriptorResolver { + + /** Logger */ + private static final Log log = + LogFactory.getLog(ClassDescriptorResolverFromJavaClass.class); + + public ClassDescriptorResolverFromJavaClass() { + super(ClassDescriptorHelper.ResolverType.JAVA_CLASS); + } + + @Override + public ClassDescriptor resolvDescriptor(String className, + URL source) throws ClassNotFoundException { + + if (log.isDebugEnabled()) { + log.debug("for source " + className); + } + + Class<?> javaClass = + ClassDescriptorHelper.getClass(className, getClassLoader()); + + String name = javaClass.getName(); + Package p = javaClass.getPackage(); + String packageName = p != null ? p.getName() : null; + Class<?> superclass = javaClass.getSuperclass(); + String superclassName = superclass != null ? superclass.getName() : null; + Class<?>[] interfaces = javaClass.getInterfaces(); + String[] interfaceNames = new String[interfaces.length]; + for (int i = 0; i < interfaces.length; i++) { + interfaceNames[i] = interfaces[i].getName(); + } + boolean isInterface = javaClass.isInterface(); + boolean isArray = javaClass.isArray(); + String componentTypeName = isArray ? javaClass.getComponentType().getName() : null; + ClassLoader classLoader = javaClass.getClassLoader(); + Constructor<?>[] javaConstructors = javaClass.getConstructors(); + MethodDescriptor[] constructors = new MethodDescriptor[javaConstructors.length]; + for (int i = 0; i < constructors.length; i++) { + constructors[i] = ClassDescriptorHelper.createMethodDescriptor( + javaConstructors[i], + javaClass.getClassLoader() + ); + } + Method[] javaMethods = javaClass.getMethods(); + MethodDescriptor[] methods = new MethodDescriptor[javaMethods.length]; + for (int i = 0; i < methods.length; i++) { + methods[i] = ClassDescriptorHelper.createMethodDescriptor( + javaMethods[i], + javaClass.getClassLoader() + ); + } + + Field[] javaFields = javaClass.getFields(); + FieldDescriptor[] fields = new FieldDescriptor[javaFields.length]; + for (int i = 0; i < fields.length; i++) { + fields[i] = ClassDescriptorHelper.createFieldDescriptor( + javaFields[i], + javaClass.getClassLoader() + ); + } + + Field[] javaDeclaredFields = javaClass.getDeclaredFields(); + FieldDescriptor[] declaredFields = + new FieldDescriptor[javaDeclaredFields.length]; + for (int i = 0; i < declaredFields.length; i++) { + declaredFields[i] = ClassDescriptorHelper.createFieldDescriptor( + javaDeclaredFields[i], + javaClass.getClassLoader() + ); + } + + JAXXObjectDescriptor jaxxObjectDescriptor = + ClassDescriptorHelper.getJAXXObjectDescriptor(javaClass); + + return new JavaClassClassDescriptor( + javaClass, + name, + packageName, + superclassName, + interfaceNames, + isInterface, + isArray, + componentTypeName, + jaxxObjectDescriptor, + classLoader, + constructors, + methods, + fields, + declaredFields + ); + } + + + private class JavaClassClassDescriptor extends ClassDescriptor { + + private final Class<?> javaClass; + + public JavaClassClassDescriptor( + Class<?> javaClass, + String name, + String packageName, + String superclassName, + String[] interfaceNames, + boolean anInterface, + boolean array, + String componentTypeName, + JAXXObjectDescriptor jaxxObjectDescriptor, + ClassLoader classLoader, + MethodDescriptor[] constructors, + MethodDescriptor[] methods, + FieldDescriptor[] fields, + FieldDescriptor[] declaredFields + ) { + super( + ClassDescriptorResolverFromJavaClass.this.getResolverType(), + name, + packageName, + superclassName, + interfaceNames, + anInterface, + array, + componentTypeName, + jaxxObjectDescriptor, + classLoader, + constructors, + methods, + fields, + declaredFields + ); + this.javaClass = javaClass; + } + +// @Override +// public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { +// return ClassDescriptorHelper.createFieldDescriptor(javaClass.getDeclaredField(name), +// javaClass.getClassLoader() +// ); +// } + + @Override + public MethodDescriptor getDeclaredMethodDescriptor(String name, + ClassDescriptor... parameterTypes) throws NoSuchMethodException { + try { + Class<?>[] parameterTypeClasses = new Class[parameterTypes.length]; + for (int i = 0; i < parameterTypes.length; i++) { + parameterTypeClasses[i] = Class.forName(parameterTypes[i].getName()); + } + return ClassDescriptorHelper.createMethodDescriptor(javaClass.getDeclaredMethod(name, parameterTypeClasses), javaClass.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + } + + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFile.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFile.java new file mode 100644 index 0000000..895c08f --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFile.java @@ -0,0 +1,746 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.reflect.resolvers; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXFactory; +import org.nuiton.jaxx.compiler.java.parser.JavaParser; +import org.nuiton.jaxx.compiler.java.parser.JavaParserTreeConstants; +import org.nuiton.jaxx.compiler.java.parser.ParseException; +import org.nuiton.jaxx.compiler.java.parser.SimpleNode; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorResolver; +import org.nuiton.jaxx.compiler.reflect.FieldDescriptor; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; +import org.nuiton.jaxx.compiler.tags.TagManager; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * To obtain a class descriptor from a java source file. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class ClassDescriptorResolverFromJavaFile extends ClassDescriptorResolver { + + /** Logger */ + private static final Log log = + LogFactory.getLog(ClassDescriptorResolverFromJavaFile.class); + + private final boolean parseMethodBody; + + public ClassDescriptorResolverFromJavaFile() { + this(false); + } + public ClassDescriptorResolverFromJavaFile(boolean parseMethodBody) { + super(ClassDescriptorHelper.ResolverType.JAVA_FILE); + this.parseMethodBody = parseMethodBody; + } + + @Override + public ClassDescriptor resolvDescriptor(String className, + URL source) throws ClassNotFoundException { + + ClassLoader classLoader = getClassLoader(); + + try { + Reader reader = new InputStreamReader(source.openStream(), "utf-8"); + try { + + String displayName = source.toString(); + if (log.isDebugEnabled()) { + log.debug("for source " + displayName); + } + JavaFileParser parser = new JavaFileParser(classLoader, parseMethodBody); + if (log.isDebugEnabled()) { + log.debug("starting parsing : " + displayName); + } + try { + parser.doParse(displayName, reader); + } catch (Exception e) { +// log.error(e.getMessage()); + throw new RuntimeException(e); + } + return new JavaFileClassDescriptor(parser, classLoader); + + } finally { + + reader.close(); + } + } catch (IOException e) { + throw new ClassNotFoundException( + "Could not resolv descriptor from source " + source, + e); + } + } + + private class JavaFileClassDescriptor extends ClassDescriptor { + + public JavaFileClassDescriptor(JavaFileParser parser, + ClassLoader classLoader) { + super( + ClassDescriptorResolverFromJavaFile.this.getResolverType(), + parser.className, + parser.packageName, + parser.superclass, + parser.interfaces.toArray(new String[parser.interfaces.size()]), + parser.isInterface, + false, + null, + parser.jaxxObjectDescriptorValue == null ? null : JAXXUtil.decodeCompressedJAXXObjectDescriptor(parser.jaxxObjectDescriptorValue), + classLoader, + parser.constructors.toArray(new MethodDescriptor[parser.constructors.size()]), + parser.methods.toArray(new MethodDescriptor[parser.methods.size()]), + parser.fields.toArray(new FieldDescriptor[parser.fields.size()]), + parser.declaredFields.toArray(new FieldDescriptor[parser.declaredFields.size()]) + ); + + } + +// @Override +// public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { +// for (FieldDescriptor descriptor : declaredFieldDescriptors) { +// if (name.equals(descriptor.getName())) { +// if (log.isDebugEnabled()) { +// log.debug("Using a declared field descriptor [" + name + "] for " + getName()); +// } +// return descriptor; +// } +// } +// throw new NoSuchFieldException(name); +// } + + @Override + public MethodDescriptor getDeclaredMethodDescriptor(String name, ClassDescriptor... parameterTypes) throws NoSuchMethodException { + throw new NoSuchMethodException(name); + } + + } + + public static class JavaFileParser { + + /** Logger */ + static private final Log log = LogFactory.getLog(JavaFileParser.class); + + /** + * the compiler used (this is a dummy compiler with no link with any file). + * + * FIXME-TC20100504 We should remove this link : should not need of a + * compiler to parse a java files. + */ + private JAXXCompiler compiler; + + /** fully qualified name of the class */ + private String className; + + /** package of the class */ + private String packageName; + + /** fully qualified name of the super class or {@code null} if no super class. */ + private String superclass; + + /** + * flag to known if we deal with an enum (the state is setted in the + * {@link #doParse(String, Reader)} method). + */ + private boolean isEnum; + + /** + * flag to known if we deal with an interface(the state is setted in the + * {@link #doParse(String, Reader)} method). + */ + private boolean isInterface; + + /** set of fully qualified names of interfaces of the class. */ + private Set<String> interfaces; + + /** public methods of the class */ + private List<MethodDescriptor> methods; + + private List<MethodDescriptor> constructors; + + /** none public methods of the class */ +// private List<MethodDescriptor> declaredMethods; + + /** public fields of the class */ + private List<FieldDescriptor> fields; + + /** none public fields of the class */ + private List<FieldDescriptor> declaredFields; + + /** + * If sets, compressed value of the $jaxxObjectDescriptor field, this means + * the class if a JAXXObject implementation. + */ + private String jaxxObjectDescriptorValue; + + public static final String[] EMPTY_STRING_ARRAY = new String[0]; + + private final boolean parseMethodBody; + + /** + * To test if a compilation unit was already parsed. If so, then stop + * parsing the java file : one parsing can only give one class + * descriptor. + * + * @since 2.4.2 + */ + private boolean firstTypeScanned; + + protected JavaFileParser(ClassLoader classLoader,boolean parseMethodBody) { + this.parseMethodBody = parseMethodBody; + //FIXME-TC-20100504 : shoudl remove this to make the parser free of jaxx :) + // We could imagine just to offers to the parser a list of namespaces + // (for class resolving)... + compiler = JAXXFactory.newDummyCompiler(classLoader); + methods = new ArrayList<>(); + constructors = new ArrayList<>(); +// declaredMethods = new ArrayList<MethodDescriptor>(); + interfaces = new HashSet<>(); + fields = new ArrayList<>(); + declaredFields = new ArrayList<>(); + superclass = Object.class.getName(); + } + + + public void doParse(String className, Reader src) throws ClassNotFoundException { + + // reset this internal state + firstTypeScanned = false; + + try { + JavaParser p = new JavaParser(src, parseMethodBody); + p.CompilationUnit(); + SimpleNode node = p.popNode(); + if (node != null) { + scanCompilationUnit(node); + if (isInterface) { + + // remove super class + superclass = null; + + // load all super classes + if (!interfaces.isEmpty()) { + for (String anInterface : interfaces) { + ClassDescriptor superclassDescriptor = ClassDescriptorHelper.getClassDescriptor(anInterface, compiler.getClassLoader()); + methods.addAll(Arrays.asList(superclassDescriptor.getMethodDescriptors())); + fields.addAll(Arrays.asList(superclassDescriptor.getFieldDescriptors())); + } + } + } + + if (isEnum) { + + // super class is always Enum + + superclass = Enum.class.getName(); + } + if (superclass != null) { + //FIXME-TC20100504 This is not good, should add nothing here + // and modify the algorithm of ClassDescriptor to go and seek + // in super classes on interfaces if required. + + ClassDescriptor superclassDescriptor = ClassDescriptorHelper.getClassDescriptor(superclass, compiler.getClassLoader()); + methods.addAll(Arrays.asList(superclassDescriptor.getMethodDescriptors())); + fields.addAll(Arrays.asList(superclassDescriptor.getFieldDescriptors())); + declaredFields.addAll(Arrays.asList(superclassDescriptor.getDeclaredFieldDescriptors())); + } + + return; + } + throw new CompilerException("Internal error: null node parsing Java file from " + src); + } catch (ParseException e) { + throw new CompilerException("Error parsing Java source code " + className + ": " + e.getMessage()); + } + } + + private void scanCompilationUnit(SimpleNode node) { + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + SimpleNode child = node.getChild(i); + scanCompilationUnitChild(child); + } + } + + private void scanCompilationUnitChild(SimpleNode child) { + if (firstTypeScanned) { + + // already scan the first class of the java file + // for the moment, can not do anything else... + if (log.isWarnEnabled()) { + log.warn("There is more than one type in current file, skip next type..."); + } + return; + } + int nodeType = child.getId(); + switch (nodeType) { + case JavaParserTreeConstants.JJTPACKAGEDECLARATION: + packageName = child.getChild(1).getText().trim(); + compiler.addImport(packageName + ".*"); + + // add implicit java.lnag namespace available + compiler.addImport("java.lang.*"); + break; + case JavaParserTreeConstants.JJTIMPORTDECLARATION: + String text = child.getText().trim(); + int importIndex = text.indexOf("import"); + if (importIndex > -1) { + text = text.substring(importIndex + "import".length()).trim(); + } + if (text.endsWith(";")) { + text = text.substring(0, text.length() - 1); + } + if (log.isDebugEnabled()) { + log.debug("import " + text); + } + compiler.addImport(text); + break; + case JavaParserTreeConstants.JJTTYPEDECLARATION: + scanCompilationUnit(child); + break; + + case JavaParserTreeConstants.JJTCLASSORINTERFACEDECLARATION: + isInterface = child.firstToken.image.equals("interface"); + scanClass(child); + break; + case JavaParserTreeConstants.JJTENUMDECLARATION: + isEnum = child.firstToken.image.equals("enum"); + scanClass(child); + break; + } + } + + // scans the main ClassOrInterfaceDeclaration + + private void scanClass(SimpleNode node) { + firstTypeScanned = true; +// boolean isInterface = node.firstToken.image.equals("interface"); + className = node.firstToken.next.image; + if (packageName != null) { + className = packageName + "." + className; + } + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + SimpleNode child = node.getChild(i); + int nodeType = child.getId(); + + if (nodeType == JavaParserTreeConstants.JJTIMPLEMENTSLIST) { + + if (log.isDebugEnabled()) { + log.debug("[" + className + "] Found a implements list " + child + " :: " + child.jjtGetNumChildren()); + } + + // obtain interfaces + for (int j = 0; j < child.jjtGetNumChildren(); j++) { + String rawName = child.getChild(j).getText().trim(); + + addInterface(rawName); + } + continue; + } + if (nodeType == JavaParserTreeConstants.JJTEXTENDSLIST) { + + if (isInterface) { + + // obtain interfaces + for (int j = 0; j < child.jjtGetNumChildren(); j++) { + String rawName = child.getChild(j).getText().trim(); + + addInterface(rawName); + } + continue; + } + + // this is an extends + assert child.jjtGetNumChildren() == 1 : "expected ExtendsList to have exactly one child for a non-interface class"; + String rawName = child.getChild(0).getText().trim(); + superclass = TagManager.resolveClassName(rawName, compiler); + if (superclass == null) { + throw new CompilerException("Could not find class: " + rawName); + } + if (log.isDebugEnabled()) { + log.debug("Set superClass = " + superclass); + } + } else if (nodeType == JavaParserTreeConstants.JJTCLASSORINTERFACEBODY) { + scanClassNode(child); + } + } + } + + // scans class body nodes + + private void scanClassNode(SimpleNode node) { + int nodeType = node.getId(); + + switch (nodeType) { + case JavaParserTreeConstants.JJTCLASSORINTERFACEDECLARATION: + + // TODO: handle inner classes + break; + + case JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION: + + scanConstructorDeclaration(node); + break; + + case JavaParserTreeConstants.JJTMETHODDECLARATION: + + scanMethodDeclaration(node); + break; + + case JavaParserTreeConstants.JJTFIELDDECLARATION: + + scanFieldDeclaration(node); + break; + + default: + + // go throught it + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + SimpleNode child = node.getChild(i); + scanClassNode(child); + } + } + } + + + protected void scanFieldDeclaration(SimpleNode node) { + String text = node.getText(); + String declaration = text; + String value = null; + int equals = text.indexOf("="); + if (equals != -1) { + value = declaration.substring(equals + 1).trim(); + declaration = declaration.substring(0, equals); + } + declaration = declaration.trim(); + + // get modifiers of the field + + int modifiers; + if (isInterface) { + modifiers = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL; + } else { + modifiers = getModifiers(node); + } + + if (log.isDebugEnabled()) { + log.debug("field [" + declaration + "] modifiers == " + + Modifier.toString(modifiers)); + } + + String[] declarationTokens = declaration.split("\\s"); + String name = declarationTokens[declarationTokens.length - 1]; + if (name.endsWith(";")) { + name = name.substring(0, name.length() - 1).trim(); + } + String cName = declarationTokens[declarationTokens.length - 2]; + String type = TagManager.resolveClassName(cName, compiler); + + FieldDescriptor descriptor = new FieldDescriptor( + name, + modifiers, + type, + compiler.getClassLoader() + ); + + if ("$jaxxObjectDescriptor".equals(name) && value != null) { + + // we are in a jaxx object, save the value of the field + + // value have this form : = "XXX";, we just want the XXX part + int firstIndex = value.indexOf("\""); + int lastIndex = value.lastIndexOf("\""); + + jaxxObjectDescriptorValue = + value.substring(firstIndex + 1, lastIndex); + + if (log.isDebugEnabled()) { + log.debug("detected a $jaxxObjectDescriptor = " + + jaxxObjectDescriptorValue); + } + } + + if (Modifier.isPublic(modifiers)) { + + fields.add(descriptor); + } else { + + declaredFields.add(descriptor); + } + } + + protected void scanConstructorDeclaration(SimpleNode node) { + String name = null; + List<String> parameterTypes = new ArrayList<>(); + //List<String> parameterNames = new ArrayList<String>(); + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + SimpleNode child = node.getChild(i); + int type = child.getId(); + + if (type == JavaParserTreeConstants.JJTMETHODDECLARATOR) { + name = child.firstToken.image.trim(); + SimpleNode formalParameters = child.getChild(0); + assert formalParameters.getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS; + for (int j = 0; j < formalParameters.jjtGetNumChildren(); j++) { + SimpleNode parameter = formalParameters.getChild(j); + String rawParameterType = parameter.getChild(1).getText().trim().replaceAll("\\.\\.\\.", "[]"); + String parameterType = TagManager.resolveClassName(rawParameterType, compiler); + if (parameterType == null && JAXXCompiler.STRICT_CHECKS) { + throw new CompilerException("could not find class '" + rawParameterType + "'"); + } + parameterTypes.add(parameterType); + //parameterNames.add(parameter.getChild(2).getText().trim()); + } + } + } + + // determine the actual modifiers + + int modifiers = getModifiers(node); + + if (isInterface) { + + modifiers = Modifier.PUBLIC; + } + if (log.isDebugEnabled()) { + log.debug("method [" + name + "] modifiers == " + Modifier.toString(modifiers)); + } + + MethodDescriptor methodDescriptor = new MethodDescriptor( + name, + modifiers, + null, + parameterTypes.toArray(new String[parameterTypes.size()]), + compiler.getClassLoader() + ); + + constructors.add(methodDescriptor); + + } + + protected void scanMethodDeclaration(SimpleNode node) { + String returnType = null; + String name = null; + List<String> parameterTypes = new ArrayList<>(); + //List<String> parameterNames = new ArrayList<String>(); + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + SimpleNode child = node.getChild(i); + int type = child.getId(); + if (type == JavaParserTreeConstants.JJTRESULTTYPE) { +// returnType = TagManager.resolveClassName(child.getText().trim(), compiler); + //tchemit 2011-04-21 Remove anything before return type (like javadoc and other comments) + returnType = TagManager.resolveClassName(child.firstToken.image.trim(), compiler); + } else if (type == JavaParserTreeConstants.JJTMETHODDECLARATOR) { + name = child.firstToken.image.trim(); + SimpleNode formalParameters = child.getChild(0); + assert formalParameters.getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS; + for (int j = 0; j < formalParameters.jjtGetNumChildren(); j++) { + SimpleNode parameter = formalParameters.getChild(j); + String rawParameterType = parameter.getChild(1).getText().trim().replaceAll("\\.\\.\\.", "[]"); + String parameterType = TagManager.resolveClassName(rawParameterType, compiler); + if (parameterType == null && JAXXCompiler.STRICT_CHECKS) { + throw new CompilerException("could not find class '" + rawParameterType + "'"); + } + parameterTypes.add(parameterType); + //parameterNames.add(parameter.getChild(2).getText().trim()); + } + } + } + + // determine the actual modifiers + + int modifiers = getModifiers(node); + + if (isInterface) { + + modifiers = Modifier.PUBLIC; + } + if (log.isDebugEnabled()) { + log.debug("method [" + name + "] modifiers == " + Modifier.toString(modifiers)); + } + + MethodDescriptor methodDescriptor = new MethodDescriptor( + name, + modifiers, + returnType, + parameterTypes.toArray(new String[parameterTypes.size()]), + compiler.getClassLoader() + ); + + if (Modifier.isPublic(modifiers)) { + + methods.add(methodDescriptor); + } else { + + //TODO At the moment, do not deal with it... +// declaredMethods.add(methodDescriptor); + } + } + + protected void addInterface(String rawName) { + if (rawName.contains("<")) { + + // generic type + rawName = rawName.substring(0, rawName.indexOf("<")); + } + if (log.isDebugEnabled()) { + log.debug("[" + className + "] try to obtain type of interface " + rawName); + } + + String myInterface = resolveFullyQualifiedName(rawName); + if (myInterface == null) { + throw new CompilerException("Could not find interface: " + myInterface); + } + if (!interfaces.contains(myInterface)) { + if (log.isDebugEnabled()) { + log.debug("[" + className + "] add interface " + myInterface); + } + interfaces.add(myInterface); + } + } + + protected String resolveFullyQualifiedName(String rawName) { + String result; + + String realRawName = null; + String realParentRawName = null; + if (rawName.contains(".")) { + // this is a inner class + int index = rawName.lastIndexOf("."); + realParentRawName = rawName.substring(0, index); + realRawName = rawName.substring(index + 1); + + if (log.isDebugEnabled()) { + log.debug("inner class detected ? " + realParentRawName + "//" + realRawName); + } + } + + if (log.isDebugEnabled()) { + log.debug("try fqn = " + rawName); + } + result = TagManager.resolveClassName(rawName, compiler); + + if (result != null) { + // interface is detected fine (fqn was used or in good package ?) + return result; + } + + String suffix = "." + rawName; + + if (realParentRawName != null) { + suffix = "." + realParentRawName; + } + + for (String aClass : compiler.getImportedClasses()) { + + if (aClass.endsWith(suffix)) { + + // found the class as an already knwon class + + if (realRawName != null) { + aClass += "." + realRawName; + } + + return aClass; + } + } + + // try on packages + + Set<String> importedPackages = compiler.getImportedPackages(); + + for (String aClass : importedPackages) { + String fqn = aClass + rawName; + + if (log.isDebugEnabled()) { + log.debug("try fqn = " + fqn); + } + result = TagManager.resolveClassName(fqn, compiler); + if (result != null) { + return result; + } + } + + // nothing was found + return null; + } + + protected int getModifiers(SimpleNode node) { + SimpleNode parentNode = node.getParent(); + for (int i = 0; i < parentNode.jjtGetNumChildren(); i++) { + SimpleNode child = parentNode.getChild(i); + if (child.getId() == JavaParserTreeConstants.JJTMODIFIERS) { + String modifiersStr = child.getText().trim(); + return scanModifiers(modifiersStr); + } + } + return 0; + } + + protected int scanModifiers(String modifiersStr) { + int modifiers = 0; + if (modifiersStr.contains("public")) { + modifiers |= Modifier.PUBLIC; + } + if (modifiersStr.contains("protected")) { + modifiers |= Modifier.PROTECTED; + } + if (modifiersStr.contains("private")) { + modifiers |= Modifier.PRIVATE; + } + if (modifiersStr.contains("static")) { + modifiers |= Modifier.STATIC; + } + if (modifiersStr.contains("final")) { + modifiers |= Modifier.FINAL; + } + if (modifiersStr.contains("volatile")) { + modifiers |= Modifier.VOLATILE; + } + if (modifiersStr.contains("transient")) { + modifiers |= Modifier.TRANSIENT; + } + if (modifiersStr.contains("synchronized")) { + modifiers |= Modifier.SYNCHRONIZED; + } + if (modifiersStr.contains("abstract")) { + modifiers |= Modifier.ABSTRACT; + } + return modifiers; + } + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJaxxFile.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJaxxFile.java new file mode 100644 index 0000000..653bc23 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJaxxFile.java @@ -0,0 +1,199 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.reflect.resolvers; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXEngine; +import org.nuiton.jaxx.compiler.JAXXFactory; +import org.nuiton.jaxx.compiler.SymbolTable; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorResolver; +import org.nuiton.jaxx.compiler.reflect.FieldDescriptor; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.JAXXObjectDescriptor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +/** + * To obtain a class descriptor from a java source file. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class ClassDescriptorResolverFromJaxxFile extends ClassDescriptorResolver { + + /** Logger */ + private static final Log log = + LogFactory.getLog(ClassDescriptorResolverFromJaxxFile.class); + + public ClassDescriptorResolverFromJaxxFile() { + super(ClassDescriptorHelper.ResolverType.JAXX_FILE); + } + + @Override + public ClassDescriptor resolvDescriptor(String className, URL source) throws ClassNotFoundException { + + JAXXEngine engine = JAXXFactory.getEngine(); + + JAXXCompiler compiler = engine.getJAXXCompiler(className); + + SymbolTable symbolTable = compiler.getSymbolTable(); + + if (symbolTable == null) { + throw new CompilerException("Internal error: no symbol table was generated for class '" + className + "'"); + } + + if (log.isDebugEnabled()) { + log.debug("for compiler " + compiler.getOutputClassName()); + } + + ClassLoader classLoader = getClassLoader(); + + ClassDescriptor superclass = + ClassDescriptorHelper.getClassDescriptor( + symbolTable.getSuperclassName(), classLoader); + // tchemit 2011-02-18 Be ware!!! + // this is nearly impossible to obtain consturctors from symbol table. + // let says for the moment this data is not available here and must be found in other places... + // Anyway, the only reason of finding constructor is when we want to generate a jaxx file + // If it inheritate from another jaxx file, we will mkae sure order is ok for this... + + List<MethodDescriptor> constructors = new ArrayList<>(); + List<MethodDescriptor> publicMethods = symbolTable.getScriptMethods(); + List<FieldDescriptor> publicFields = symbolTable.getScriptFields(); + //List<MethodDescriptor> declaredMethods = new ArrayList<MethodDescriptor>(publicMethods); + //List<FieldDescriptor> declaredFields = new ArrayList<FieldDescriptor>(publicFields); + Iterator<MethodDescriptor> methods = publicMethods.iterator(); + while (methods.hasNext()) { + MethodDescriptor method = methods.next(); + if (!Modifier.isPublic(method.getModifiers())) { + methods.remove(); + } + } + Iterator<FieldDescriptor> fields = publicFields.iterator(); + while (fields.hasNext()) { + FieldDescriptor field = fields.next(); + if (!Modifier.isPublic(field.getModifiers())) { + fields.remove(); + } + } + Set<String> interfaces = new HashSet<>(); + if (symbolTable.getInterfaces() != null) { + // having interfaces + for (String anInterface : symbolTable.getInterfaces()) { + int genericIndex = anInterface.indexOf("<"); + if (genericIndex > -1) { + // remove generic type + anInterface = anInterface.substring(0, genericIndex); + } + if (log.isDebugEnabled()) { + log.debug("getting interface " + anInterface + " descriptor for class " + className); + } + interfaces.add(anInterface); + ClassDescriptor interfaceclass = ClassDescriptorHelper.getClassDescriptor(anInterface, classLoader); + publicMethods.addAll(Arrays.asList(interfaceclass.getMethodDescriptors())); + publicFields.addAll(Arrays.asList(interfaceclass.getFieldDescriptors())); + } + } + publicMethods.addAll(Arrays.asList(superclass.getMethodDescriptors())); + publicFields.addAll(Arrays.asList(superclass.getFieldDescriptors())); + int dotPos = className.lastIndexOf("."); + String packageName = dotPos != -1 ? className.substring(0, dotPos) : null; + + ClassDescriptor[] superclassInterfaces = superclass.getInterfaces(); + for (ClassDescriptor superclassInterface : superclassInterfaces) { + interfaces.add(superclassInterface.getName()); + } + interfaces.add(JAXXObject.class.getName()); + return new JaxxFileClassDescriptor( + compiler, + className, + packageName, + interfaces, + classLoader, + constructors.toArray(new MethodDescriptor[constructors.size()]), + publicMethods.toArray(new MethodDescriptor[publicMethods.size()]), + publicFields.toArray(new FieldDescriptor[publicFields.size()]) + ); + } + + private class JaxxFileClassDescriptor extends ClassDescriptor { + + private final JAXXCompiler compiler; + + public JaxxFileClassDescriptor(JAXXCompiler compiler, + String className, + String packageName, + Set<String> interfaces, + ClassLoader classLoader, + MethodDescriptor[] constructors, + MethodDescriptor[] publicMethods, + FieldDescriptor[] publicFields) { + super(ClassDescriptorResolverFromJaxxFile.this.getResolverType(), + className, + packageName, + compiler.getSymbolTable().getSuperclassName(), + interfaces.toArray(new String[interfaces.size()]), + false, + false, + null, + null, + classLoader, + constructors, + publicMethods, + publicFields + ); + this.compiler = compiler; + } + + @Override + public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { + String type = compiler.getSymbolTable().getClassTagIds().get(name); + if (type != null) { + return new FieldDescriptor(name, Modifier.PROTECTED, type, compiler.getClassLoader()); + } + throw new NoSuchFieldException(name); + } + + @Override + public MethodDescriptor getDeclaredMethodDescriptor(String name, ClassDescriptor... parameterTypes) throws NoSuchMethodException { + throw new NoSuchMethodException(name); + } + + @Override + public JAXXObjectDescriptor getJAXXObjectDescriptor() { + return compiler.getJAXXObjectDescriptor(); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/script/ScriptInitializer.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/script/ScriptInitializer.java new file mode 100644 index 0000000..ca608b6 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/script/ScriptInitializer.java @@ -0,0 +1,42 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.script; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; + +/** + * A dummy CompiledObject which serves to initialize scripted field. This is handled by + * a CompiledObject rather than (say) simply inlining the initialization code in order to + * ensure that the field is initialized in document order. + */ +public class ScriptInitializer extends CompiledObject { + + public ScriptInitializer(String initializer, JAXXCompiler compiler) { +// super(compiler.getAutoId(ClassDescriptorHelper.getClassDescriptor(ScriptInitializer.class)), + super(compiler.getAutoId(ScriptInitializer.class.getSimpleName()), + ClassDescriptorHelper.getClassDescriptor(ScriptInitializer.class), compiler, false); + appendInitializationCode(initializer); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/script/ScriptManager.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/script/ScriptManager.java new file mode 100644 index 0000000..5587f82 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/script/ScriptManager.java @@ -0,0 +1,482 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.script; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.java.JavaArgument; +import org.nuiton.jaxx.compiler.java.JavaConstructor; +import org.nuiton.jaxx.compiler.java.JavaElementFactory; +import org.nuiton.jaxx.compiler.java.parser.JavaParser; +import org.nuiton.jaxx.compiler.java.parser.JavaParserTreeConstants; +import org.nuiton.jaxx.compiler.java.parser.SimpleNode; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.FieldDescriptor; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; +import org.nuiton.jaxx.compiler.tags.TagManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.StringReader; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ScriptManager { + + private JAXXCompiler compiler; + + public ScriptManager(JAXXCompiler compiler) { + this.compiler = compiler; + } + + /** + * Strips unnecessary curly braces from around the script, generating a warning if they are found. + * + * @param script script to trim + * @return the trimed script + */ + public String trimScript(String script) { + script = script.trim(); + if (script.startsWith("{") && script.endsWith("}")) { + compiler.reportWarning("curly braces are unnecessary for script '" + script + "'"); + script = script.substring(1, script.length() - 1); + } + return script; + } + + public void checkParse(String script) throws CompilerException { + script = trimScript(script); + JavaParser p = new JavaParser(new StringReader(script)); + while (!p.Line()) { + // ??? + } + } + + public String preprocessScript(String script) throws CompilerException { + script = trimScript(script); + StringBuilder result = new StringBuilder(); + JavaParser p = new JavaParser(new StringReader(script)); + while (!p.Line()) { + SimpleNode node = p.popNode(); + if (node != null) { + preprocessScriptNode(node, false); + result.append(node.getText()); + } + } + return result.toString(); + } + + /** + * Scans through a compound symbol (foo.bar.baz) to identify and compile + * the JAXX class it refers to, if any. + * + * @param symbol symbol to scan + */ + private void scanCompoundSymbol(String symbol) { + String[] tokens = symbol.split("\\."); + StringBuilder currentSymbol = new StringBuilder(); + for (String token : tokens) { + if (currentSymbol.length() > 0) { + currentSymbol.append('.'); + } + currentSymbol.append(token.trim()); + + String contextClass = TagManager.resolveClassName( + currentSymbol.toString(), compiler); + if (contextClass != null) { + compiler.addDependencyClass(contextClass); + } + } + } + + private void preprocessScriptNode(SimpleNode node, + boolean staticContext) throws CompilerException { + // identify static methods and initializers -- we can't fire events statically + if (node.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION) { + if (node.getParent().getChild(0).getText().contains("static")) { + staticContext = true; + } + } else if (node.getId() == JavaParserTreeConstants.JJTINITIALIZER) { + if (node.getText().trim().startsWith("static")) { + staticContext = true; + } + } + + int count = node.jjtGetNumChildren(); + for (int i = 0; i < count; i++) { + preprocessScriptNode(node.getChild(i), staticContext); + } + + int id = node.getId(); + if (id == JavaParserTreeConstants.JJTNAME || + id == JavaParserTreeConstants.JJTCLASSORINTERFACETYPE) { + scanCompoundSymbol(node.getText()); + } + //tchemit 2011-02-02 I never understand this code + //Doing at each assignment a ifre with a called "dummy value" is a none sense + // Since JAXX can handle pretty well with javaBeans I remove this code +// if (!staticContext) { +// String lhs = null; +// if (id == JavaParserTreeConstants.JJTASSIGNMENTEXPRESSION || +// id == JavaParserTreeConstants.JJTPOSTFIXEXPRESSION && node.jjtGetNumChildren() == 2) { +// lhs = ((SimpleNode) node.jjtGetChild(0)).getText().trim(); +// } else if (id == JavaParserTreeConstants.JJTPREINCREMENTEXPRESSION || +// id == JavaParserTreeConstants.JJTPREDECREMENTEXPRESSION) { +// lhs = ((SimpleNode) node.jjtGetChild(0)).getText().trim(); +// } +// if (lhs != null) { +// FieldDescriptor[] fields = compiler.getScriptFields(); +// for (FieldDescriptor field : fields) { +// if (field.getName().equals(lhs)) { +// //lhs.substring(lhs.lastIndexOf(".") + 1); +// String prefix = compiler.getImportedType(JAXXUtil.class); +// node.firstToken.image = prefix + ".assignment(" + node.firstToken.image; +// String outputClassName = compiler.getImportedType(compiler.getOutputClassName()); +// node.lastToken.image = node.lastToken.image + ", \"" + lhs + "\", " + outputClassName + ".this)"; +// } +// } +// } +// } + } + + /** + * Examines a Line to determine its real type. As all tokens returned by the parser are Lines, and + * they are just a tiny wrapper around the real node, this method strips off the wrapper layers to identify + * the real type of a node. + * + * @param line line to scan + * @return the line type + */ + private int getLineType(SimpleNode line) { + if (line.jjtGetNumChildren() == 1) { + SimpleNode node = line.getChild(0); + if (node.getId() == JavaParserTreeConstants.JJTBLOCKSTATEMENT) { + if (node.jjtGetNumChildren() == 1) { + return node.getChild(0).getId(); + } + } else if (node.getId() == JavaParserTreeConstants.JJTCLASSORINTERFACEBODYDECLARATION) { + int id = node.getChild(0).getId(); + if (id == JavaParserTreeConstants.JJTMODIFIERS) { + return node.getChild(1).getId(); + } + if (id == JavaParserTreeConstants.JJTINITIALIZER) { + return id; + } + } + return node.getId(); + } + return JavaParserTreeConstants.JJTLINE; // generic value implying that it's okay to put into the initializer block + } + + private SimpleNode findExplicitConstructorInvocation(SimpleNode parent) { + if (parent.getId() == JavaParserTreeConstants.JJTEXPLICITCONSTRUCTORINVOCATION) { + return parent; + } + + int count = parent.jjtGetNumChildren(); + for (int i = 0; i < count; i++) { + SimpleNode result = findExplicitConstructorInvocation(parent.getChild(i)); + if (result != null) { + return result; + } + } + return null; + } + + private void processConstructor(String modifiers, SimpleNode node) { + assert node.getId() == JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION : "expected node to be ConstructorDeclaration, found " + JavaParserTreeConstants.jjtNodeName[node.getId()] + " instead"; + assert node.getChild(0).getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS : "expected node 0 to be FormalParameters, found " + JavaParserTreeConstants.jjtNodeName[node.getChild(1).getId()] + " instead"; + String code = ""; + if (node.getChild(0).jjtGetNumChildren() == 0) { + compiler.reportError("The default no-argument constructor may not be redefined"); + } else { + SimpleNode explicitConstructorInvocation = findExplicitConstructorInvocation(node); + if (explicitConstructorInvocation == null || explicitConstructorInvocation.getText().trim().startsWith("super(")) { + code = "$initialize();" + JAXXCompiler.getLineSeparator(); + if (explicitConstructorInvocation == null) { + node.getChild(1).firstToken.image = node.getChild(1).firstToken.image; + } else { + explicitConstructorInvocation.lastToken.image += code; + } + } + } + + compiler.appendBodyCode(modifiers + " " + node.getText().substring(0, node.getText().length() - 1) + code + "}"); + } + + private void processConstructor(SimpleNode mainNode) { + + compiler.registerInitializer(new RegisterConstructor(mainNode)); + } + + + /** Logger */ + static private final Log log = LogFactory.getLog(ScriptManager.class); + + private void scanScriptNode(SimpleNode node) throws CompilerException { + int nodeType = getLineType(node); + if (nodeType == JavaParserTreeConstants.JJTIMPORTDECLARATION) { + // have to handle imports early so the preprocessing takes them into account + String text = node.getChild(0).getText().trim(); + if (text.startsWith("import")) { + text = text.substring("import".length()).trim(); + } + if (text.endsWith(";")) { + text = text.substring(0, text.length() - 1); + } + compiler.addImport(text); + } + + preprocessScriptNode(node, false); + + if (nodeType == JavaParserTreeConstants.JJTIMPORTDECLARATION) { + // do nothing, already handled above + } else if (nodeType == JavaParserTreeConstants.JJTMETHODDECLARATION) { + String returnType = null; + String name = null; + List<String> parameterTypes = new ArrayList<>(); + //List<String> parameterNames = new ArrayList<String>(); + SimpleNode methodDeclaration = node.getChild(0).getChild(1); + assert methodDeclaration.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION; + for (int i = 0; i < methodDeclaration.jjtGetNumChildren(); i++) { + SimpleNode child = methodDeclaration.getChild(i); + int type = child.getId(); + if (type == JavaParserTreeConstants.JJTRESULTTYPE) { + String rawReturnType = child.getText().trim(); + returnType = TagManager.resolveClassName(rawReturnType, compiler); + // FIXME: this check fails for inner classes defined in this file + //if (returnType == null) + // throw new CompilerException("could not find class '" + rawReturnType + "'"); + } else if (type == JavaParserTreeConstants.JJTMETHODDECLARATOR) { + name = child.firstToken.image.trim(); + SimpleNode formalParameters = child.getChild(0); + assert formalParameters.getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS; + for (int j = 0; j < formalParameters.jjtGetNumChildren(); j++) { + SimpleNode parameter = formalParameters.getChild(j); + String rawParameterType = parameter.getChild(1).getText().trim().replaceAll("\\.\\.\\.", "[]"); + String parameterType = TagManager.resolveClassName(rawParameterType, compiler); + // FIXME: this check fails for inner classes defined in this file + //if (parameterType == null) + // throw new CompilerException("could not find class '" + rawParameterType + "'"); + parameterTypes.add(parameterType); + //parameterNames.add(parameter.getChild(2).getText().trim()); + } + } + } + compiler.appendBodyCode(node.getText()); + compiler.addScriptMethod(new MethodDescriptor(name, Modifier.PUBLIC, returnType, parameterTypes.toArray(new String[parameterTypes.size()]), compiler.getClassLoader())); + } else if (nodeType == JavaParserTreeConstants.JJTCLASSORINTERFACEDECLARATION || + nodeType == JavaParserTreeConstants.JJTINITIALIZER) { + String str = node.getText().trim(); + if (str.endsWith(";")) { + str += ";"; + } + compiler.appendBodyCode(str); + } else if (nodeType == JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION) { + processConstructor(node); +// processConstructor(node.getChild(0).getChild(0).getText(), node.getChild(0).getChild(1)); + } else if (nodeType == JavaParserTreeConstants.JJTLOCALVARIABLEDECLARATION || nodeType == JavaParserTreeConstants.JJTFIELDDECLARATION) { + // the "local" variable declarations in this expression aren't actually local -- they are flagged local + // just because there isn't an enclosing class scope visible to the parser. "Real" local variable + // declarations won't show up here, because they will be buried inside of methods. + String text = node.getText().trim(); + if (!text.endsWith(";")) { + text += ";"; + } + String declaration = text; + int equals = text.indexOf("="); + if (equals != -1) { + declaration = declaration.substring(0, equals); + } + declaration = declaration.trim(); + if (declaration.contains("<")) { + + // generic declaration detected + + if (log.isDebugEnabled()) { + log.debug("Found a declaration with generics : " + declaration); + } + + int last = declaration.lastIndexOf('>'); + + // copy everything before first '<' + String newDeclaration = declaration.substring(0, declaration.indexOf('<')); + if (last < declaration.length()) { + + // copy everithing after last '>' + newDeclaration += declaration.substring(last + 1); + } + + if (log.isDebugEnabled()) { + log.debug("==> declaration without generics : " + newDeclaration); + } + declaration = newDeclaration; + } + + String[] declarationTokens = declaration.split("\\s"); + boolean isFinal = Arrays.asList(declarationTokens).contains("final"); + boolean isStatic = Arrays.asList(declarationTokens).contains("static"); + String name = declarationTokens[declarationTokens.length - 1]; + if (name.endsWith(";")) { + name = name.substring(0, name.length() - 1).trim(); + } + String className = declarationTokens[declarationTokens.length - 2]; + if (log.isDebugEnabled()) { + log.debug("Found type : " + className + " : " + + Arrays.toString(declarationTokens)); + } + String type = TagManager.resolveClassName(className, compiler); + if (type == null) { + + throw new CompilerException( + "Could not find type of " + className + + " for expression " + text); + } + compiler.addScriptField(new FieldDescriptor(name, + Modifier.PUBLIC, + type, + compiler.getClassLoader()) + ); + // TODO: determine the actual modifiers + if (equals != -1 && !isFinal && !isStatic) { + + // declare the field in the class body, but wait to actually initialize it + compiler.appendBodyCode(text.substring(0, equals).trim() + ";"); + String initializer = text.substring(equals + 1).trim(); + if (type.endsWith("[]")) { + initializer = "new " + type + " " + initializer; + } + final String finalInitializer = name + " = " + initializer; + compiler.registerInitializer(new Runnable() { + + @Override + public void run() { + compiler.registerCompiledObject(new ScriptInitializer( + finalInitializer, compiler)); + } + }); + } else { + compiler.appendBodyCode(text); + } + compiler.appendBodyCode("\n"); + } else { + String text = node.getText().trim(); + if (text.length() > 0) { + if (!text.endsWith(";")) { + text += ";"; + } + compiler.appendInitializerCode(text); + } + } + } + + public void registerScript(String script) throws CompilerException { + JavaParser p = new JavaParser(new StringReader(script)); + while (!p.Line()) { + SimpleNode node = p.popNode(); + if (node != null) { + scanScriptNode(node); + } + } + } + + class RegisterConstructor implements Runnable { + + final SimpleNode mainNode; + + public RegisterConstructor(SimpleNode mainNode) { + this.mainNode = mainNode; + } + + @Override + public void run() { + + String className = mainNode.getChild(0).getChild(1).firstToken.image; + String modifiers = mainNode.getChild(0).getChild(0).getText(); + + SimpleNode node = mainNode.getChild(0).getChild(1); + int nbArguments = node.getChild(0).jjtGetNumChildren(); + if (log.isDebugEnabled()) { + log.debug("Constructor found with " + nbArguments + " arguments : " + node.getText()); + } + assert node.getId() == JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION : "expected node to be ConstructorDeclaration, found " + JavaParserTreeConstants.jjtNodeName[node.getId()] + " instead"; + assert node.getChild(0).getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS : "expected node 0 to be FormalParameters, found " + JavaParserTreeConstants.jjtNodeName[node.getChild(1).getId()] + " instead"; + SimpleNode params = node.getChild(0); + StringBuilder bodyC = new StringBuilder(); + for (int i = 1; i < node.jjtGetNumChildren(); i++) { + bodyC.append(node.getChild(i).getText()); + } + String bodyContent = bodyC.toString().trim(); + JavaArgument[] arguments = new JavaArgument[nbArguments]; + for (int i = 0; i < nbArguments; i++) { + SimpleNode param = params.getChild(i); + String paramType = param.getChild(0).firstToken.image; + ClassDescriptor type = TagManager.resolveClass(paramType, compiler); + String paramName = param.getChild(2).firstToken.image; + if (log.isDebugEnabled()) { + log.debug("Parameter n°" + i + " --> [" + type + " : " + paramName + "]"); + } + JavaArgument arg = JavaElementFactory.newArgument(type.getName(), paramName); + arguments[i] = arg; + } + String[] modifierSplit = modifiers.trim().split("\\s"); + if (log.isDebugEnabled()) { + log.debug("Modifiers = " + Arrays.toString(modifierSplit)); + } + int finalModifiers = 0; + for (String mod : modifierSplit) { + mod = mod.trim(); + if ("public".equals(mod)) { + finalModifiers = Modifier.PUBLIC; + break; + } + if ("protected".equals(mod)) { + finalModifiers = Modifier.PROTECTED; + break; + } + if ("private".equals(mod)) { + finalModifiers = Modifier.PRIVATE; + break; + } + } + + if (!bodyContent.endsWith("$initialize();")) { + bodyContent += JAXXCompiler.getLineSeparator() + " $initialize();"; + } + if (log.isDebugEnabled()) { + log.debug("Final modifier to use : " + Modifier.toString(finalModifiers)); + log.debug("Constructor body :\n" + bodyContent); + } + JavaConstructor constructorMethod = JavaElementFactory.newConstructor( + finalModifiers, + className, + bodyContent, + arguments + ); + + compiler.getJavaFile().addConstructor(constructorMethod); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/spi/DefaultInitializer.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/spi/DefaultInitializer.java new file mode 100644 index 0000000..19bddb8 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/spi/DefaultInitializer.java @@ -0,0 +1,228 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.spi; + +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.beans.BeanInfoUtil; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.nuiton.jaxx.compiler.tags.DefaultObjectHandler; +import org.nuiton.jaxx.compiler.tags.ImportHandler; +import org.nuiton.jaxx.compiler.tags.ScriptHandler; +import org.nuiton.jaxx.compiler.tags.StyleHandler; +import org.nuiton.jaxx.compiler.tags.TagHandler; +import org.nuiton.jaxx.compiler.tags.TagManager; +import org.nuiton.jaxx.compiler.tags.swing.ApplicationHandler; +import org.nuiton.jaxx.compiler.tags.swing.CellHandler; +import org.nuiton.jaxx.compiler.tags.swing.ItemHandler; +import org.nuiton.jaxx.compiler.tags.swing.JAXXComboBoxHandler; +import org.nuiton.jaxx.compiler.tags.swing.JAXXListHandler; +import org.nuiton.jaxx.compiler.tags.swing.JAXXTabHandler; +import org.nuiton.jaxx.compiler.tags.swing.JAXXTreeHandler; +import org.nuiton.jaxx.compiler.tags.swing.JCheckBoxHandler; +import org.nuiton.jaxx.compiler.tags.swing.JComboBoxHandler; +import org.nuiton.jaxx.compiler.tags.swing.JInternalFrameHandler; +import org.nuiton.jaxx.compiler.tags.swing.JListHandler; +import org.nuiton.jaxx.compiler.tags.swing.JMenuHandler; +import org.nuiton.jaxx.compiler.tags.swing.JPasswordFieldHandler; +import org.nuiton.jaxx.compiler.tags.swing.JPopupMenuHandler; +import org.nuiton.jaxx.compiler.tags.swing.JProgressBarHandler; +import org.nuiton.jaxx.compiler.tags.swing.JRadioButtonHandler; +import org.nuiton.jaxx.compiler.tags.swing.JScrollPaneHandler; +import org.nuiton.jaxx.compiler.tags.swing.JSliderHandler; +import org.nuiton.jaxx.compiler.tags.swing.JSpinnerHandler; +import org.nuiton.jaxx.compiler.tags.swing.JSplitPaneHandler; +import org.nuiton.jaxx.compiler.tags.swing.JTabbedPaneHandler; +import org.nuiton.jaxx.compiler.tags.swing.JTextComponentHandler; +import org.nuiton.jaxx.compiler.tags.swing.JToolBarHandler; +import org.nuiton.jaxx.compiler.tags.swing.JTreeHandler; +import org.nuiton.jaxx.compiler.tags.swing.JWindowHandler; +import org.nuiton.jaxx.compiler.tags.swing.JXLayerHandler; +import org.nuiton.jaxx.compiler.tags.swing.RowHandler; +import org.nuiton.jaxx.compiler.tags.swing.TabHandler; +import org.nuiton.jaxx.compiler.tags.swing.TableHandler; +import org.nuiton.jaxx.compiler.tags.validator.BeanValidatorHandler; +import org.nuiton.jaxx.compiler.tags.validator.ExcludeFieldValidatorHandler; +import org.nuiton.jaxx.compiler.tags.validator.FieldValidatorHandler; +import org.nuiton.jaxx.runtime.swing.Application; +import org.nuiton.jaxx.runtime.swing.JAXXButtonGroup; +import org.nuiton.jaxx.runtime.swing.JAXXComboBox; +import org.nuiton.jaxx.runtime.swing.JAXXList; +import org.nuiton.jaxx.runtime.swing.JAXXTab; +import org.nuiton.jaxx.runtime.swing.JAXXTree; +import org.nuiton.jaxx.runtime.swing.Table; +import org.nuiton.jaxx.runtime.swing.editor.EnumEditor; +import org.nuiton.jaxx.runtime.swing.editor.LocaleEditor; +import org.nuiton.jaxx.validator.swing.SwingValidator; +import org.jdesktop.jxlayer.JXLayer; + +import javax.swing.JCheckBox; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JEditorPane; +import javax.swing.JFormattedTextField; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JPasswordField; +import javax.swing.JPopupMenu; +import javax.swing.JProgressBar; +import javax.swing.JRadioButton; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JScrollPane; +import javax.swing.JSlider; +import javax.swing.JSpinner; +import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.JTextPane; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import javax.swing.JTree; +import javax.swing.JWindow; +import javax.swing.text.JTextComponent; +import java.awt.Component; + +/** + * Initializes support provided from JAXX (java, swing and validation). + * + * @plexus.component role-hint="default" role="org.nuiton.jaxx.compiler.spi.Initializer" + */ +public class DefaultInitializer implements Initializer { + + @Override + public void initialize() { + + BeanInfoUtil.addJaxxBeanInfoPath("org.nuiton.jaxx.runtime.swing"); + + registerDefaultNamespace("javax.swing.*", + JEditorPane.class, + JFormattedTextField.class, + JPasswordField.class, + JTextArea.class, + JTextField.class, + JTextPane.class + ); + + // + // Register tags + // + + registerTag(JAXXCompiler.JAXX_NAMESPACE, ScriptHandler.TAG_NAME, new ScriptHandler()); + registerTag(JAXXCompiler.JAXX_NAMESPACE, StyleHandler.TAG_NAME, new StyleHandler()); + registerTag(JAXXCompiler.JAXX_NAMESPACE, ImportHandler.TAG_NAME, new ImportHandler()); + + //TC-20091005 why the namespace was on awt ? ButtonGroup is from javax.swing + registerTag("javax.swing.*", "ButtonGroup", new DefaultObjectHandler(ClassDescriptorHelper.getClassDescriptor(JAXXButtonGroup.class))); + + registerTag(JAXXCompiler.JAXX_NAMESPACE, TabHandler.TAG_NAME, new TabHandler()); + registerTag(JAXXCompiler.JAXX_NAMESPACE, RowHandler.TAG_NAME, new RowHandler()); + registerTag(JAXXCompiler.JAXX_NAMESPACE, CellHandler.TAG_NAME, new CellHandler()); + registerTag(JAXXCompiler.JAXX_NAMESPACE, ItemHandler.TAG_NAME, new ItemHandler()); + + + registerTag(JAXXCompiler.JAXX_NAMESPACE, BeanValidatorHandler.TAG, new BeanValidatorHandler(ClassDescriptorHelper.getClassDescriptor(SwingValidator.class))); + registerTag(JAXXCompiler.JAXX_NAMESPACE, FieldValidatorHandler.TAG, new FieldValidatorHandler()); + registerTag(JAXXCompiler.JAXX_NAMESPACE, ExcludeFieldValidatorHandler.TAG, new FieldValidatorHandler()); + + // + // Register beans + // + + registerBean(Object.class, DefaultObjectHandler.class); + registerBean(Component.class, DefaultComponentHandler.class); + + // check boxes + registerBean(JCheckBox.class, JCheckBoxHandler.class); + registerBean(JCheckBoxMenuItem.class, JCheckBoxHandler.class); + + // combo boxes + registerBean(JComboBox.class, JComboBoxHandler.class); + registerBean(EnumEditor.class, JComboBoxHandler.class); + registerBean(LocaleEditor.class, JComboBoxHandler.class); + registerBean(JAXXComboBox.class, JAXXComboBoxHandler.class); + + // radio boxes + registerBean(JRadioButton.class, JRadioButtonHandler.class); + registerBean(JRadioButtonMenuItem.class, JRadioButtonHandler.class); + registerBean(JToggleButton.class, JRadioButtonHandler.class); + + // Lists + registerBean(JList.class, JListHandler.class); + registerBean(JAXXList.class, JAXXListHandler.class); + + // Trees + registerBean(JTree.class, JTreeHandler.class); + registerBean(JAXXTree.class, JAXXTreeHandler.class); + + // Windows + registerBean(JDialog.class, JWindowHandler.class); + registerBean(JFrame.class, JWindowHandler.class); + registerBean(JWindow.class, JWindowHandler.class); + + // JXLayer + registerBean(JXLayer.class, JXLayerHandler.class); + + registerBean(Application.class, ApplicationHandler.class); + + registerBean(JInternalFrame.class, JInternalFrameHandler.class); + registerBean(JMenu.class, JMenuHandler.class); + registerBean(JPasswordField.class, JPasswordFieldHandler.class); + registerBean(JPopupMenu.class, JPopupMenuHandler.class); + registerBean(JProgressBar.class, JProgressBarHandler.class); + registerBean(JScrollPane.class, JScrollPaneHandler.class); + registerBean(JSlider.class, JSliderHandler.class); + registerBean(JSpinner.class, JSpinnerHandler.class); + registerBean(JSplitPane.class, JSplitPaneHandler.class); + registerBean(JTabbedPane.class, JTabbedPaneHandler.class); + registerBean(JTextComponent.class, JTextComponentHandler.class); + registerBean(JToolBar.class, JToolBarHandler.class); + + registerBean(Table.class, TableHandler.class); + registerBean(JAXXTab.class, JAXXTabHandler.class); + + registerBean(SwingValidator.class, BeanValidatorHandler.class); + + } + + protected void registerBean(Class<?> beanClass, Class<? extends TagHandler> handlerClass) { + ClassDescriptor classDescriptor = ClassDescriptorHelper.getClassDescriptor(beanClass); + + TagManager.registerBean(classDescriptor, handlerClass); + } + + protected void registerTag(String namespace, String tagName, TagHandler handler) { + TagManager.registerTag(namespace, tagName, handler); + } + + protected void registerDefaultNamespace(String namespace, Class<?>... beanClass) { + + for (Class<?> c : beanClass) { + TagManager.registerDefaultNamespace(c.getSimpleName(), namespace); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/spi/Initializer.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/spi/Initializer.java new file mode 100644 index 0000000..009ca70 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/spi/Initializer.java @@ -0,0 +1,41 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.spi; + +import java.util.ServiceLoader; + +/** + * Performs SPI initialization, typically to register new tags, beans and converter. + * + * <b>Note:</b> To load such Initializer, we use the {@link ServiceLoader} mecanism. + * + * @see DefaultInitializer + */ +public interface Initializer { + + /** + * Performs SPI initialization, typically to register new + * tags, beans and converter. + */ + void initialize(); +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/DefaultComponentHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/DefaultComponentHandler.java new file mode 100644 index 0000000..31d0d10 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/DefaultComponentHandler.java @@ -0,0 +1,465 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.I18nHelper; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.UnsupportedAttributeException; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; + +import javax.swing.BorderFactory; +import javax.swing.border.TitledBorder; +import java.awt.Component; +import java.awt.Container; +import java.awt.Font; +import java.awt.event.ComponentListener; +import java.awt.event.ContainerListener; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.beans.IntrospectionException; +import java.io.IOException; +import java.lang.reflect.Field; + +public class DefaultComponentHandler extends DefaultObjectHandler { + + + public static final String BORDER_ATTRIBUTE = "border"; + + public static final String ACTION_ICON_ATTRIBUTE = "actionIcon"; + + public static final String I18N_MNEMONIC_ATTRIBUTE = "i18nMnemonic"; + + public static final String CONTAINER_DELEGATE_ATTRIBUTE = "containerDelegate"; + + public static final String FONT_FACE_ATTRIBUTE = "font-face"; + + public static final String FONT_SIZE_ATTRIBUTE = "font-size"; + + public static final String FONT_STYLE_ATTRIBUTE = "font-style"; + + public static final String FONT_WEIGHT_ATTRIBUTE = "font-weight"; + + public static final String HEIGHT_ATTRIBUTE = "height"; + + public static final String ICON_ATTRIBUTE = "icon"; + + public static final String ICON_IMAGE_ATTRIBUTE = "iconImage"; + + public static final String NAME_ATTRIBUTE = "name"; + + public static final String WIDTH_ATTRIBUTE = "width"; + + public static final String X_ATTRIBUTE = "x"; + + public static final String Y_ATTRIBUTE = "y"; + + /** Logger */ + protected static final Log log = + LogFactory.getLog(DefaultComponentHandler.class); + + public static final String BORDER_FACTORY_PREFIX = BorderFactory.class.getSimpleName() + "."; + + public static final String TITLED_BORDER_PREFIX = TitledBorder.class.getSimpleName() + "("; + + /** container delegate (if any) */ + private String containerDelegate; + + public DefaultComponentHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, Component.class); + } + + @Override + protected void init() throws IntrospectionException { + if (jaxxBeanInfo == null) { + super.init(); + + containerDelegate = (String) getJAXXBeanInfo().getJAXXBeanDescriptor().getValue(CONTAINER_DELEGATE_ATTRIBUTE); + if (containerDelegate == null && ClassDescriptorHelper.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass().getSuperclass())) { + containerDelegate = ((DefaultComponentHandler) TagManager.getTagHandler(getBeanClass().getSuperclass())).getContainerDelegate(); + } + } + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("hasFocus", FocusListener.class); + addProxyEventInfo("isVisible", ComponentListener.class); + addProxyEventInfo("getBounds", ComponentListener.class); + addProxyEventInfo("getLocation", ComponentListener.class); + addProxyEventInfo("getLocationOnScreen", ComponentListener.class); + addProxyEventInfo("getSize", ComponentListener.class); + addProxyEventInfo("getX", ComponentListener.class); + addProxyEventInfo("getY", ComponentListener.class); + addProxyEventInfo("getWidth", ComponentListener.class); + addProxyEventInfo("getHeight", ComponentListener.class); + if (ClassDescriptorHelper.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass())) { + addProxyEventInfo("getComponentCount", ContainerListener.class); + } + } + + @Override + protected void setDefaults(CompiledObject object, + Element tag, + JAXXCompiler compiler) throws CompilerException { + super.setDefaults(object, tag, compiler); + setAttribute(object, NAME_ATTRIBUTE, object.getId(), false, compiler); + openComponent(object, tag, compiler); + } + + @Override + public void compileFirstPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + super.compileFirstPass(tag, compiler); + } + + @Override + public void compileSecondPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + super.compileSecondPass(tag, compiler); + closeComponent(compiler.getOpenComponent(), tag, compiler); + } + + protected void openComponent(CompiledObject object, + Element tag, + JAXXCompiler compiler) throws CompilerException { + String constraints = tag.getAttribute(CONSTRAINTS_ATTRIBUTE); + if (constraints != null && constraints.length() > 0) { + compiler.openComponent(object, constraints); + } else { + compiler.openComponent(object); + } + } + + protected void closeComponent(CompiledObject object, + Element tag, + JAXXCompiler compiler) throws CompilerException { + compiler.closeComponent(object); + } + + @Override + public boolean isPropertyInherited(String property) throws UnsupportedAttributeException { + return property.equals("font") || property.startsWith("font-") || property.equals("foreground") || property.equals("enabled"); + } + + @Override + public ClassDescriptor getPropertyType(CompiledObject object, + String propertyName, + JAXXCompiler compiler) throws CompilerException { + if (X_ATTRIBUTE.equals(propertyName) || + Y_ATTRIBUTE.equals(propertyName) || + WIDTH_ATTRIBUTE.equals(propertyName) || + HEIGHT_ATTRIBUTE.equals(propertyName) || + FONT_SIZE_ATTRIBUTE.equals(propertyName)) { + return ClassDescriptorHelper.getClassDescriptor(Integer.class); + } + if (FONT_FACE_ATTRIBUTE.equals(propertyName) || + FONT_STYLE_ATTRIBUTE.equals(propertyName) || + FONT_WEIGHT_ATTRIBUTE.equals(propertyName)) { + return ClassDescriptorHelper.getClassDescriptor(String.class); + } + return super.getPropertyType(object, propertyName, compiler); + } + + @Override + public String getGetPropertyCode(String id, + String name, + JAXXCompiler compiler) throws CompilerException { + if (FONT_FACE_ATTRIBUTE.equals(name)) { + return id + ".getFont().getFontName()"; + } + if (FONT_SIZE_ATTRIBUTE.equals(name)) { + return id + ".getFont().getSize()"; + } + if (FONT_WEIGHT_ATTRIBUTE.equals(name)) { + compiler.addImport(Font.class); + return "(" + id + ".getFont().getStyle() & Font.BOLD) != 0 ? \"bold\" : \"normal\""; + } + if (FONT_STYLE_ATTRIBUTE.equals(name)) { + compiler.addImport(Font.class); + return "(" + id + ".getFont().getStyle() & Font.ITALIC) != 0 ? \"italic\" : \"normal\""; + } + return super.getGetPropertyCode(id, name, compiler); + } + + @Override + public String getSetPropertyCode(String id, + String name, + String valueCode, + JAXXCompiler compiler) throws CompilerException { + if (X_ATTRIBUTE.equals(name)) { + return id + ".setLocation(" + valueCode + ", " + id + ".getY());"; + } + if (Y_ATTRIBUTE.equals(name)) { + return id + ".setLocation(" + id + ".getX(), " + valueCode + ");"; + } + if (WIDTH_ATTRIBUTE.equals(name)) { + String type = compiler.getImportedType(SwingUtil.class); +// compiler.setNeedSwingUtil(true); + // need to optimize case when both width and height are being assigned + return type + ".setComponentWidth(" + id + "," + valueCode + ");"; + } + if (HEIGHT_ATTRIBUTE.equals(name)) { +// compiler.setNeedSwingUtil(true); + String type = compiler.getImportedType(SwingUtil.class); + return type + ".setComponentHeight(" + id + "," + valueCode + ");"; + } + if (FONT_FACE_ATTRIBUTE.equals(name)) { + return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(new Font(" + valueCode + ", " + id + ".getFont().getStyle(), " + id + ".getFont().getSize()));\n}"; + } + if (FONT_SIZE_ATTRIBUTE.equals(name)) { + return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont((float) " + valueCode + "));\n}"; + } + if (FONT_WEIGHT_ATTRIBUTE.equals(name)) { + if (valueCode.equals("\"bold\"")) { + String type = compiler.getImportedType(Font.class); + return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | " + type + ".BOLD));\n}"; + } + if (valueCode.equals("\"normal\"")) { + String type = compiler.getImportedType(Font.class); + return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~" + type + ".BOLD));\n}"; + } + if (!valueCode.startsWith("\"")) { + String type = compiler.getImportedType(Font.class); + return "if (" + id + ".getFont() != null) {\n if ((" + valueCode + ").equals(\"bold\")) {\n " + + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | " + type + ".BOLD));\n } else {\n " + + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~" + type + ".BOLD));\n }\n}"; + } + compiler.reportError("font-weight must be either \"normal\" or \"bold\", found " + valueCode); + return ""; + } + if (FONT_STYLE_ATTRIBUTE.equals(name)) { + if (valueCode.equals("\"italic\"")) { + String type = compiler.getImportedType(Font.class); + return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | " + type + ".ITALIC));\n}"; + } + if (valueCode.equals("\"normal\"")) { + String type = compiler.getImportedType(Font.class); + return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~" + type + ".ITALIC));\n}"; + } + if (!valueCode.startsWith("\"")) { + String type = compiler.getImportedType(Font.class); + return "if (" + id + ".getFont() != null) {\n if ((" + valueCode + ").equals(\"italic\")) {\n " + + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | " + type + ".ITALIC));\n } else {\n " + + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~" + type + ".ITALIC));\n }\n}"; + } + compiler.reportError("font-style must be either \"normal\" or \"italic\", found " + valueCode); + return ""; + } + if (ClassDescriptorHelper.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass()) && name.equals(LAYOUT_ATTRIBUTE)) { + // handle containerDelegate (e.g. contentPane on JFrame) + String cDelegate = (String) getJAXXBeanInfo().getJAXXBeanDescriptor().getValue(CONTAINER_DELEGATE_ATTRIBUTE); + if (cDelegate != null) { + return id + '.' + cDelegate + "().setLayout(" + valueCode + ");"; + } + } + // ajout du support i18n + if (I18nHelper.isI18nableAttribute(name, compiler)) { + valueCode = I18nHelper.addI18nInvocation(id, name, valueCode, compiler); + } + + return super.getSetPropertyCode(id, name, valueCode, compiler); + } + + @Override + public void setAttribute(CompiledObject object, + String propertyName, + String stringValue, + boolean inline, + JAXXCompiler compiler) { + + if (propertyName.startsWith("_")) { + // client property + if (stringValue.startsWith("{")) { + stringValue = stringValue.substring(1, stringValue.length() - 1); + } + object.addClientProperty(propertyName.substring(1), stringValue); + //TC-20090327 rather not generating code here + //object.appendAdditionCode(object.getJavaCode() + ".putClientProperty(\"" + propertyName.substring(1) + "\", " + stringValue + ");"); + return; + } + if (BORDER_ATTRIBUTE.equals(propertyName)) { + if (stringValue.contains(BORDER_FACTORY_PREFIX)) { + compiler.addImport(BorderFactory.class); + } else if (stringValue.contains(TITLED_BORDER_PREFIX)) { + compiler.addImport(TitledBorder.class); + } + } + if (ICON_ATTRIBUTE.equals(propertyName)) { + if (!(stringValue.startsWith("{") || stringValue.endsWith("}"))) { + // this is a customized icon, add the icon creation code +// compiler.setNeedSwingUtil(true); + String type = compiler.getImportedType(SwingUtil.class); + + if (compiler.getConfiguration().isUseUIManagerForIcon()) { + stringValue = "{" + type + ".getUIManagerIcon(\"" + stringValue + "\")}"; + } else { + stringValue = "{" + type + ".createImageIcon(\"" + stringValue + "\")}"; + } + } + } else if (ICON_IMAGE_ATTRIBUTE.equals(propertyName)) { + if (!(stringValue.startsWith("{") || stringValue.endsWith("}"))) { + // this is a customized icon, add the icon creation code +// compiler.setNeedSwingUtil(true); + String type = + compiler.getImportedType(SwingUtil.class); + + if (compiler.getConfiguration().isUseUIManagerForIcon()) { + stringValue = "{" + type + ".getUIManagerIcon(\"" + stringValue + "\").getImage()}"; + } else { + stringValue = "{" + type + ".createImageIcon(\"" + stringValue + "\").getImage()}"; + } + } + } else if (ACTION_ICON_ATTRIBUTE.equals(propertyName)) { + // customized actionIcon property + if (stringValue.startsWith("{") && stringValue.endsWith("}")) { + // there is a script to define the action icon, this is forbidden + compiler.reportError("the actionIcon does not support script, remove braces..., fix the file " + compiler.getOutputClassName()); + return; + } + propertyName = ICON_ATTRIBUTE; +// compiler.setNeedSwingUtil(true); + String type = compiler.getImportedType(SwingUtil.class); + if (compiler.getConfiguration().isUseUIManagerForIcon()) { + stringValue = "{" + type + ".getUIManagerActionIcon(\"" + stringValue + "\")}"; + } else { + stringValue = "{" + type + ".createActionIcon(\"" + stringValue + "\")}"; + } + inline = true; + } else if (I18N_MNEMONIC_ATTRIBUTE.equals(propertyName)) { + propertyName = MNEMONIC_ATTRIBUTE; + stringValue = I18nHelper.addI18nMnemonicInvocation( + object, + I18N_MNEMONIC_ATTRIBUTE, + TypeManager.getJavaCode(stringValue), + compiler); + } + super.setAttribute(object, propertyName, stringValue, inline, compiler); + } + + @Override + protected void scanAttributesForDependencies(Element tag, + JAXXCompiler compiler) { + super.scanAttributesForDependencies(tag, compiler); + // check for clientProperty attributes + //FIXME make this works,... it seems jaxx compiler does not come here ? + //FIXME see the the firstPassHandler in JAXXCompiler ? + NamedNodeMap children = tag.getAttributes(); + for (int i = 0, max = children.getLength(); i < max; i++) { + Attr attr = (Attr) children.item(i); + String name = attr.getName(); + if (!name.startsWith("_")) { + continue; + } + String value = attr.getValue(); + if (value.startsWith("{")) { + compiler.reportWarning(tag, "an clientProperty attribute " + name.substring(1) + " does not required curly value but was : " + value, 0); + } + } + + } + + /** + * Maps string values onto integers, so that int-valued enumeration properties can be specified by strings. For + * example, when passed a key of 'alignment', this method should normally map the values 'left', 'center', and + * 'right' onto SwingConstants.LEFT, SwingConstants.CENTER, and SwingConstants.RIGHT respectively. + * + * You do not normally need to call this method yourself; it is invoked by {@link #convertFromString} when an + * int-valued property has a value which is not a valid number. By default, this method looks at the + * <code>enumerationValues</code> value of the <code>JAXXPropertyDescriptor</code>. + * + * @param key the name of the int-typed property + * @param value the non-numeric value that was specified for the property + * @throws IllegalArgumentException if the property is an enumeration, but the value is not valid + * @throws NumberFormatException if the property is not an enumeration + */ + @Override + protected int constantValue(String key, String value) { + if (key.equals(MNEMONIC_ATTRIBUTE) || + key.equals(DISPLAYED_MNEMONIC_ATTRIBUTE)) { + if (value.length() == 1) { + return value.charAt(0); + } + try { + Field vk = KeyEvent.class.getField(value); + return (Integer) vk.get(null); + } catch (NoSuchFieldException e) { + throw new IllegalArgumentException("mnemonics must be either a single character or the name of a field in KeyEvent (found: '" + value + "')"); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + return super.constantValue(key, value); + } + + /** + * Returns <code>true</code> if this component can contain other components. For children to be + * allowed, the component must be a subclass of <code>Container</code> and its <code>JAXXBeanInfo</code> + * must not have the value <code>false</code> for its <code>isContainer</code> value. + * + * @return <code>true</code> if children are allowed + */ + public boolean isContainer() { + boolean container = ClassDescriptorHelper.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass()); +// if (container) { +// try { +// init(); +// if (Boolean.FALSE.equals(getJAXXBeanInfo().getJAXXBeanDescriptor().getValue("isContainer"))) { +// container = false; +// } +// } catch (IntrospectionException e) { +// throw new RuntimeException(e); +// } +// } + safeInit(); + if (container) { + if (Boolean.FALSE.equals(getJAXXBeanInfo().getJAXXBeanDescriptor().getValue("isContainer"))) { + container = false; + } + } + return container; + } + + public String getContainerDelegate() { +// try { +// init(); +// return containerDelegate; +// } catch (IntrospectionException e) { +// throw new RuntimeException(e); +// } + safeInit(); + return containerDelegate; + + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/DefaultObjectHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/DefaultObjectHandler.java new file mode 100644 index 0000000..ae403ce --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/DefaultObjectHandler.java @@ -0,0 +1,1350 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompiledObjectDecorator; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.I18nHelper; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.UnsupportedAttributeException; +import org.nuiton.jaxx.compiler.beans.JAXXBeanInfo; +import org.nuiton.jaxx.compiler.beans.JAXXEventSetDescriptor; +import org.nuiton.jaxx.compiler.beans.JAXXIntrospector; +import org.nuiton.jaxx.compiler.beans.JAXXPropertyDescriptor; +import org.nuiton.jaxx.compiler.binding.DataBindingHelper; +import org.nuiton.jaxx.compiler.css.StylesheetHelper; +import org.nuiton.jaxx.compiler.java.parser.ParseException; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.reflect.FieldDescriptor; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.ComponentDescriptor; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.JAXXObjectDescriptor; +import org.nuiton.jaxx.runtime.bean.BeanTypeAware; +import org.nuiton.jaxx.runtime.css.Stylesheet; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.io.IOException; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + +/** + * Default handler for class tags. Class tags are tags which represent instances of Java classes, + * such as <code><JButton label='Close'/></code>. <code>DefaultObjectHandler</code> + * provides support for attributes and events which adhere to JavaBeans naming conventions as + * well as basic JAXX features like the <code>id</code> attribute and data binding by means of + * curly braces. + * + * Throughout this class, the word "member" refers to the name of a field or method (e.g. + * <code>"getDocument"</code>) and the word "property" refers to the JavaBeans-style simple + * name of a property (e.g. <code>"document"</code>). + */ +public class DefaultObjectHandler implements TagHandler { + + /** Logger. */ + private static final Log log = LogFactory.getLog(DefaultObjectHandler.class); + + public static final String HANDLER_ATTRIBUTE = "handler"; + + public static final String ABSTRACT_ATTRIBUTE = "abstract"; + + public static final String CONSTRAINTS_ATTRIBUTE = "constraints"; + + public static final String CONSTRUCTOR_PARAMS_ATTRIBUTE = "constructorParams"; + + public static final String DECORATOR_ATTRIBUTE = "decorator"; + + public static final String DISPLAYED_MNEMONIC_ATTRIBUTE = "displayedMnemonic"; + + public static final String DISPLAYED_MNEMONIC_INDEX_ATTRIBUTE = "displayedMnemonicIndex"; + + public static final String GENERIC_TYPE_ATTRIBUTE = "genericType"; + + public static final String ID_ATTRIBUTE = "id"; + + public static final String IMPLEMENTS_ATTRIBUTE = "implements"; + + public static final String INITIALIZER_ATTRIBUTE = "initializer"; + + public static final String JAVA_BEAN_ATTRIBUTE = "javaBean"; + + public static final String LAYOUT_ATTRIBUTE = "layout"; + + public static final String MNEMONIC_ATTRIBUTE = "mnemonic"; + + public static final String STYLE_CLASS_ATTRIBUTE = "styleClass"; + + public static final String SUPER_GENERIC_TYPE_ATTRIBUTE = "superGenericType"; + + public static final String GRID_LAYOUT_PREFIX = GridLayout.class.getSimpleName() + "("; + + public static final String BORDER_LAYOUT_PREFIX = BorderLayout.class.getSimpleName() + "("; + + /** The class that this handler provides support for. */ + private ClassDescriptor beanClass; + + /** The JAXXBeanInfo for the beanClass. */ + protected JAXXBeanInfo jaxxBeanInfo; + + /** Maps property names to their respective JAXXPropertyDescriptors. */ + private Map<String, JAXXPropertyDescriptor> properties; + + /** Maps event names to their respective JAXXEventSetDescriptors. */ + private Map<String, JAXXEventSetDescriptor> events; + + /** Maps property names to their respective ProxyEventInfos. */ + private Map<String, ProxyEventInfo> eventInfos; + + /** Maps XML tags to the CompiledObjects created from them. */ + protected static Map<Element, CompiledObject> objectMap = new WeakHashMap<>(); + + public ProxyEventInfo getEventInfo(String memberName) { + return eventInfos != null ? eventInfos.get(memberName) : null; + } + + /** + * Encapsulates information about a "proxy event handler", which is an event handler that + * fires PropertyChangeEvents when it is triggered. ProxyEventInfos simplify the data binding + * system by allowing all dependencies to fire the same kind of event even if they would + * normally throw something else, like <code>DocumentEvent</code>. + */ + public static class ProxyEventInfo { + + /** The name of the method or field being proxied, e.g. "getText". */ + String memberName; + + /** The "actual" event listener for the property in question, e.g. DocumentListener. */ + ClassDescriptor listenerClass; + + /** + * In cases where a different object (such as a model) is more directly responsible for + * managing the property, this is the name of the property where that object can be + * found, e.g. "document" (which is turned into a call to "getDocument()"). This property + * is also treated as a dependency of the data binding expression, and any updates to it + * (assuming it is bound) will cause the listener to be removed from the old value and + * attached to the new value, and the data binding to be processed. + */ + String modelName; + + /** The name of the method used to add the "native" event listener, e.g. "addDocumentListener". */ + String addMethod; + + /** The name of the method used to remove the "native" event listener, e.g. "removeDocumentListener". */ + String removeMethod; + + public String getAddMethod() { + return addMethod; + } + + public ClassDescriptor getListenerClass() { + return listenerClass; + } + + public String getMemberName() { + return memberName; + } + + public String getModelName() { + return modelName; + } + + public String getRemoveMethod() { + return removeMethod; + } + } + + /** + * Creates a new <code>DefaultObjectHandler</code> which provides support for the specified class. The + * class is not actually introspected until the {@link #compileFirstPass} method is invoked. + * + * @param beanClass the class which this handler supports + */ + public DefaultObjectHandler(ClassDescriptor beanClass) { + this.beanClass = beanClass; + } + + /** + * Performs introspection on the beanClass and stores the results. + * + * @throws IntrospectionException if any pb + */ + protected void init() throws IntrospectionException { + if (jaxxBeanInfo == null) { + // perform introspection & cache the results + jaxxBeanInfo = getJAXXBeanInfo(beanClass); + + JAXXPropertyDescriptor[] propertiesArray = + jaxxBeanInfo.getJAXXPropertyDescriptors(); + properties = new HashMap<>(); + for (int i = propertiesArray.length - 1; i >= 0; i--) { + properties.put(propertiesArray[i].getName(), propertiesArray[i]); + } + + JAXXEventSetDescriptor[] eventsArray = + jaxxBeanInfo.getJAXXEventSetDescriptors(); + events = new HashMap<>(); + for (int i = eventsArray.length - 1; i >= 0; i--) { + MethodDescriptor[] methods = eventsArray[i].getListenerMethods(); + for (MethodDescriptor method : methods) { + events.put(method.getName(), eventsArray[i]); + } + } + + configureProxyEventInfo(); + } + } + + /** @return the class which this <code>DefaultObjectHandler</code> supports. */ + public ClassDescriptor getBeanClass() { + return beanClass; + } + + /** + * @return the <code>JAXXBeanInfo</code> for the class which this <code>DefaultObjectHandler</code> + * supports. + */ + public JAXXBeanInfo getJAXXBeanInfo() { + try { + init(); + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + return jaxxBeanInfo; + } + + /** + * Returns the <code>JAXXBeanInfo</code> for the specified class. + * + * @param beanClass the bean class for which to retrieve <code>JAXXBeanInfo</code> + * @return the class' <code>JAXXBeanInfo</code> + * @throws IntrospectionException if any pb + */ + public static JAXXBeanInfo getJAXXBeanInfo(ClassDescriptor beanClass) throws IntrospectionException { + return JAXXIntrospector.getJAXXBeanInfo(beanClass); + } + + /** + * Returns the type of the named property. This is the return type of the property's <code>get</code> method; + * for instance <code>JLabel</code>'s <code>text</code> property is a <code>String</code>. + * + * @param object the object being compiled + * @param propertyName the simple JavaBeans-style name of the property + * @param compiler the current <code>JAXXCompiler</code> + * @return the property's type + * @throws CompilerException if the type cannot be determined + */ + public ClassDescriptor getPropertyType(CompiledObject object, + String propertyName, + JAXXCompiler compiler) { + safeInit(); + + JAXXPropertyDescriptor property = properties.get(propertyName); + if (property != null) { + return property.getPropertyType(); + } + throw new UnsupportedAttributeException( + "property '" + propertyName + "' not found in " + object); + } + + /** + * @param name name of the property + * @return <code>true</code> if the named member is <i>bound</i> (fires <code>PropertyChangeEvent</code> + * when modified). Members are either fields (represented by the simple name of the field) or <code>get/is</code> + * methods (represented by the simple name of the method, <b>not</b> the simplified JavaBeans-style name). + * Methods which are not actually bound in their native class, but for which proxy events have been + * configured (such as <code>JTextField.getText</code>, return <code>true</code>. + * @throws UnsupportedAttributeException if attribute is not supported + */ + public boolean isMemberBound(String name) throws UnsupportedAttributeException { + safeInit(); + + if (eventInfos != null && eventInfos.containsKey(name)) { + return true; + } + + if (name.equals("getClass")) { + return false; + } + + String propertyName = null; + if (name.startsWith("get")) { + propertyName = Introspector.decapitalize(name.substring("get".length())); + } else if (name.startsWith("is")) { + propertyName = Introspector.decapitalize(name.substring("is".length())); + } + JAXXPropertyDescriptor property = propertyName != null ? + properties.get(propertyName) : null; + if (property != null) { + return property.isBound(); + } + try { + FieldDescriptor field = getBeanClass().getFieldDescriptor(name); + return Modifier.isFinal(field.getModifiers()); // final fields might as well be considered bound -- they can't be modified anyway + } catch (NoSuchFieldException e) { + throw new UnsupportedAttributeException("cannot find property '" + name + "' of " + getBeanClass()); + } + } + + public static ClassDescriptor getEventClass(ClassDescriptor listenerClass) { + return listenerClass.getMethodDescriptors()[0].getParameterTypes()[0]; + } + + /** + * Configures the event handling for members which do not fire <code>PropertyChangeEvent</code> when + * modified. The default implementation does nothing. Subclasses should override this method to call + * <code>addProxyEventInfo</code> for each member which requires special handling. + */ + protected void configureProxyEventInfo() { + } + + /** + * Configures a proxy event handler which fires <code>PropertyChangeEvents</code> when a non-bound + * member is updated. This is necessary for all fields (which cannot be bound) and for methods that are + * not bound property <code>get</code> methods. The proxy event handler will attach the specified kind + * of listener to the class and fire a <code>PropertyChangeEvent</code> whenever the listener receives + * any kind of event. + * + * Even though this method can theoretically be applied to fields (in addition to methods), it would be an + * unusual situation in which that would actually work -- as fields cannot fire events when modified, it would + * be difficult to have a listener that was always notified when a field value changed. + * + * @param memberName the name of the field or method being proxied + * @param listenerClass the type of listener which receives events when the field or method is updated + */ + public void addProxyEventInfo(String memberName, Class<?> listenerClass) { + addProxyEventInfo(memberName, listenerClass, null); + } + + /** + * Configures a proxy event handler which fires <code>PropertyChangeEvents</code> when a non-bound + * member is updated. This is necessary for all fields (which cannot be bound) and for methods that are + * not bound property <code>get</code> methods. This variant attaches a listener to a property of the + * object (such as <code>model</code>) and not the object itself, which is useful when there is a model + * that is the "real" container of the information. The proxy event handler will attach the specified kind + * of listener to the property's value (retrieved using the property's <code>get</code> method) and fire + * a <code>PropertyChangeEvent</code> whenever the listener receives any kind of event. + * + * If the property is itself bound (typically the case with models), any updates to the property's value will + * cause the listener to be removed from the old property value and reattached to the new property value, + * as well as cause a <code>PropertyChangeEvent</code> to be fired. + * + * Even though this method can theoretically be applied to fields (in addition to methods), it would be an + * unusual situation in which that would actually work -- as fields cannot fire events when modified, it would + * be difficult to have a listener that was always notified when a field value changed. + * + * @param memberName the name of the field or method being proxied + * @param listenerClass the type of listener which receives events when the field or method is updated + * @param modelName the JavaBeans-style name of the model property + */ + public void addProxyEventInfo(String memberName, + Class<?> listenerClass, + String modelName) { + String listenerName = listenerClass.getName(); + listenerName = + listenerName.substring(listenerName.lastIndexOf(".") + 1); + addProxyEventInfo(memberName, + listenerClass, + modelName, + "add" + listenerName, + "remove" + listenerName + ); + } + + // TODO: remove this temporary method, complete switchover to ClassDescriptors + + public void addProxyEventInfo(String memberName, + Class<?> listenerClass, + String modelName, + String addMethod, + String removeMethod) { + try { + ClassDescriptor classDescriptor = + ClassDescriptorHelper.getClassDescriptor( + listenerClass.getName() + ); + + addProxyEventInfo(memberName, + classDescriptor, + modelName, + addMethod, + removeMethod + ); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + /** + * Configures a proxy event handler which fires <code>PropertyChangeEvents</code> when a non-bound + * member is updated. This is necessary for all fields (which cannot be bound) and for methods that are + * not bound property <code>get</code> methods. This variant attaches a listener to a property of the + * object (such as <code>model</code>) and not the object itself, which is useful when there is a model + * that is the "real" container of the information. The proxy event handler will attach the specified kind + * of listener to the property's value (retrieved using the property's <code>get</code> method) and fire + * a <code>PropertyChangeEvent</code> whenever the listener receives any kind of event. + * + * If the property is itself bound (typically the case with models), any updates to the property's value will + * cause the listener to be removed from the old property value and reattached to the new property value, + * as well as cause a <code>PropertyChangeEvent</code> to be fired. + * + * This variant of <code>addProxyEventInfo</code> allows the names of the methods that add and remove + * the event listener to be specified, in cases where the names are not simply <code>add<listenerClassName></code> + * and <code>remove<listenerClassName></code>. + * + * Even though this method can theoretically be applied to fields (in addition to methods), it would be an + * unusual situation in which that would actually work -- as fields cannot fire events when modified, it would + * be difficult to have a listener that was always notified when a field value changed. + * + * @param memberName the name of the field or method being proxied + * @param listenerClass the type of listener which receives events when the field or method is updated + * @param modelName the JavaBeans-style name of the model property + * @param addMethod add method name + * @param removeMethod remove method name + */ + public void addProxyEventInfo(String memberName, + ClassDescriptor listenerClass, + String modelName, + String addMethod, + String removeMethod) { + ProxyEventInfo info = new ProxyEventInfo(); + info.memberName = memberName; + info.listenerClass = listenerClass; + info.modelName = modelName; + info.addMethod = addMethod; + info.removeMethod = removeMethod; + if (eventInfos == null) { + eventInfos = new HashMap<>(); + } + eventInfos.put(memberName, info); + } + + @Override + public void compileFirstPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + scanAttributesForDependencies(tag, compiler); + compileChildrenFirstPass(tag, compiler); + } + + @Override + public void compileSecondPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + safeInit(); + CompiledObject object = objectMap.get(tag); + if (object == null) { + throw new IllegalStateException( + "unable to find CompiledObject associated with tag <" + + tag.getTagName() + ">; should have been registered " + + "before second pass" + ); + } + compiler.checkOverride(object); + String constructorParams = + tag.getAttribute(CONSTRUCTOR_PARAMS_ATTRIBUTE); + if (StringUtils.isNotEmpty(constructorParams)) { + object.setConstructorParams( + compiler.getScriptManager().trimScript(constructorParams)); + } + + setDefaults(object, tag, compiler); + setAttributes(object, tag, compiler); + //TC-20091105, can apply genericType everyWhere, should just test that class is generic (not possible actually) +// if (object.getGenericTypesLength() > 0 && !(object == compiler.getRootObject() || object.isJavaBean())) { +// // can ony be apply to root object or javaBean object +// compiler.reportWarning("'genericType' attribute can only be found on root, or a javaBean object tag but was found on tag " + tag); +// object.setGenericTypes(null); +// return; +// } + compileChildrenSecondPass(tag, compiler); + } + + public void registerCompiledObject(Element tag, JAXXCompiler compiler) { + String id = tag.getAttribute(ID_ATTRIBUTE); + if (id == null || id.length() == 0) { + id = compiler.getAutoId(getBeanClass().getSimpleName()); +// id = compiler.getAutoId(getBeanClass()); + } + CompiledObject object = createCompiledObject(id, compiler); + objectMap.put(tag, object); + String styleClass = tag.getAttribute(STYLE_CLASS_ATTRIBUTE).trim(); + if (styleClass.length() > 0) { + object.setStyleClass(styleClass); + } + compiler.registerCompiledObject(object); + } + + /** + * Creates the <code>CompiledObject</code> which will represent the object + * created by this <code>TagHandler</code>. + * + * @param id the <code>CompiledObject's</code> ID. + * @param compiler compiler to use + * @return the <code>CompiledObject</code> to use + */ + protected CompiledObject createCompiledObject(String id, + JAXXCompiler compiler) { + return new CompiledObject(id, getBeanClass(), compiler); + } + + /** + * Initializes the default settings of the object, prior to setting its + * attribute values. The default implementation does nothing. + * + * @param object the object to initialize + * @param tag the tag being compiled + * @param compiler the current <code>JAXXCompiler</code> + */ + protected void setDefaults(CompiledObject object, + Element tag, + JAXXCompiler compiler) { + } + + /** + * @param property property name to test + * @return <code>true</code> if the specified property should be inherited by child components when specified + * via CSS. + * @throws UnsupportedAttributeException if attribute is not supported + */ + public boolean isPropertyInherited(String property) throws UnsupportedAttributeException { + return false; + } + + /** + * @param name name of event + * @return <code>true</code> if the specified name has the form of an event handler attribute + * (e.g. "onActionPerformed"). + */ + public boolean isEventHandlerName(String name) { + return name.length() > 2 && + name.startsWith("on") && + Character.isUpperCase(name.charAt(2)); + } + + /** + * Scans all attributes for any dependency classes and adds them to the current compilation + * set. Called by <code>compileFirstPass()</code> (it is an error to add dependencies after + * pass 1 is complete). + * + * @param tag tag to scan + * @param compiler compiler to use + */ + protected void scanAttributesForDependencies(Element tag, + JAXXCompiler compiler) { + List<Attr> attributes = new ArrayList<>(); + NamedNodeMap children = tag.getAttributes(); + for (int i = 0; i < children.getLength(); i++) { + attributes.add((Attr) children.item(i)); + } + Collections.sort(attributes, getAttributeComparator()); + + for (Attr attribute : attributes) { + String name = attribute.getName(); + String value = attribute.getValue(); + if (name.equals(JAVA_BEAN_ATTRIBUTE)) { + //compiler.preprocessScript(value); + continue; + } + if (name.equals(CONSTRAINTS_ATTRIBUTE) || + isEventHandlerName(name)) { + // adds dependencies as a side effect + compiler.preprocessScript(value); + } else if (name.equals(CONSTRUCTOR_PARAMS_ATTRIBUTE)) { + //fix bug 178 : if a constructor parameter contains a comma + // the split will not works. + // using this hack will always works :) (but still a hack) + compiler.preprocessScript("java.util.Arrays.toString(" + value + ")"); +// for (String param : value.split("\\s*,\\s*")) { +// compiler.preprocessScript(param); +// } + } else if (value.startsWith("{") && value.endsWith("}")) { + compiler.preprocessScript(value.substring(1, value.length() - 1)); + } + } + } + + /** + * Processes the attributes of an XML tag. Four kinds of attributes are supported: simple property values (of any + * datatype supported by {@link #convertFromString}), data binding expressions (attributes containing curly-brace + * pairs), event listeners (attributes starting with 'on', such as 'onActionPerformed'), and JAXX-defined properties + * such as 'id'. + * + * @param object the object to be modified + * @param tag the tag from which to pull attributes + * @param compiler the current <code>JAXXCompiler</code> + */ + public void setAttributes(CompiledObject object, + Element tag, + JAXXCompiler compiler) { + List<Attr> attributes = new ArrayList<>(); + NamedNodeMap children = tag.getAttributes(); + + for (int i = 0; i < children.getLength(); i++) { + attributes.add((Attr) children.item(i)); + } + Collections.sort(attributes, getAttributeComparator()); + + CompiledObject rootObject = compiler.getRootObject(); + + Attr genericTypeAttribute = null; + for (Attr attribute : attributes) { + String name = attribute.getName(); + String value = attribute.getValue().trim(); + if (name.equals(ID_ATTRIBUTE) || + name.equals(CONSTRAINTS_ATTRIBUTE) || + name.equals(CONSTRUCTOR_PARAMS_ATTRIBUTE) || + name.equals(STYLE_CLASS_ATTRIBUTE) || + name.startsWith(XMLNS_ATTRIBUTE) || + JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { + // ignore, already handled + continue; + } + + if (compiler.isUseHandler()) { + if (name.startsWith(HANDLER_ATTRIBUTE)) { + // ignore, already handled + continue; + } + } + if (name.equals(JAVA_BEAN_ATTRIBUTE)) { + object.setJavaBean(true); + if (!value.isEmpty()) { + object.setJavaBeanInitCode(value); + } + continue; + } + if (name.equals(INITIALIZER_ATTRIBUTE)) { + if (!value.isEmpty()) { + object.setInitializer(value); + } else { + object.setInitializer("null"); + } + continue; + } + + if (name.equals(IMPLEMENTS_ATTRIBUTE)) { + if (object != rootObject) { + // can ony be apply to root object + compiler.reportError("'" + IMPLEMENTS_ATTRIBUTE + "' attribute can only be found on root tag but was found on tag " + tag); + return; + } + //tchemit 2011-01-29 reuse what was filled in symbols table + String[] interfaces = compiler.getSymbolTable().getInterfaces(); +// String[] interfaces = value.split(","); + compiler.setExtraInterfaces(interfaces); + continue; + } + + if (name.equals(ABSTRACT_ATTRIBUTE)) { + if (object != rootObject) { + // can ony be apply to root object + compiler.reportError("'" + ABSTRACT_ATTRIBUTE + "' attribute can only be found on root tag but was found on tag " + tag); + return; + } + compiler.setAbstractClass(true); + continue; + } + + if (name.equals(GENERIC_TYPE_ATTRIBUTE)) { + //TC-20090313 check after all attributes been processed + genericTypeAttribute = attribute; + continue; + } + + if (name.equals(SUPER_GENERIC_TYPE_ATTRIBUTE)) { + if (object != rootObject) { + // can ony be apply to root object + compiler.reportError("'" + SUPER_GENERIC_TYPE_ATTRIBUTE + "' attribute can only be found on root tag but was found on tag " + tag); + return; + } + compiler.setSuperGenericType(value); + continue; + } + + if (name.equals(DECORATOR_ATTRIBUTE)) { + if (!value.isEmpty()) { + CompiledObjectDecorator decorator = + compiler.getEngine().getDecorator(value); + object.setDecorator(decorator); + } + continue; + } + + if (isEventHandlerName(name)) { + // event handler + if (!value.endsWith(";") && !value.endsWith("}")) { + value += ";"; + } + addEventHandler(object, + Introspector.decapitalize(name.substring(2)), + value, + compiler + ); + continue; + } + // simple property + setAttribute(object, name, value, true, compiler); + } + + if (genericTypeAttribute != null) { + String name = genericTypeAttribute.getName(); + String value = genericTypeAttribute.getValue().trim(); + if (object == rootObject) { + compiler.setGenericType(value); + } else { + object.setGenericTypes(value.split(",")); + if (object.getSimpleType() != null) { + + // reload the simpleType + object.setSimpleType(object.getSimpleType() + "<" + value + ">"); + } + } + if (ClassDescriptorHelper.getClassDescriptor(BeanTypeAware.class).isAssignableFrom(object.getObjectClass())) { + String fqn = compiler.getImportedTypeForSimpleName(value); + if (fqn != null) { + // add beanType from genericType + if (log.isDebugEnabled()) { + log.debug("Add beanType property: " + value + " to " + object); + } + + setAttribute(object, BeanTypeAware.PROPERTY_BEAN_TYPE, "{" + value + ".class}", true, compiler); + } + + + } + } + + } + + /** + * Returns a <code>Comparator</code> which defines the ordering in which the tag's attributes should be processed. The + * default implementation sorts the attributes according to the order defined by the {@link #getAttributeOrdering} method. + * + * @return a <code>Comparator</code> defining the order of attribute processing + */ + protected Comparator<Attr> getAttributeComparator() { + return new Comparator<Attr>() { + + @Override + public int compare(Attr a, Attr b) { + int aOrder = getAttributeOrdering(a); + int bOrder = getAttributeOrdering(b); + + return aOrder - bOrder; + } + }; + } + + /** + * Returns the priority with which a particular attribute should be processed. Lower numbers should be processed before + * higher numbers. This value is used by the {@link #getAttributeComparator} method to define the sort ordering. + * + * @param attr the attribute to treate + * @return the attribute's priority + */ + protected int getAttributeOrdering(Attr attr) { + if (attr.getName().equals(DISPLAYED_MNEMONIC_INDEX_ATTRIBUTE) || + attr.getName().equals(DISPLAYED_MNEMONIC_ATTRIBUTE) || + attr.getName().equals(MNEMONIC_ATTRIBUTE)) { + return 1; + } + return 0; + } + + /** + * Set a single property on an object. The value may be either a simple value or contain data binding expressions. + * Simple values are first converted to the property's type using {@link #convertFromString(String, String, Class)}. + * + * @param object the object on which to set the property + * @param propertyName the name of the property to set + * @param stringValue the raw string value of the property from the XML + * @param compiler the current <code>JAXXCompiler</code> + */ + public void setAttributeFromCss(CompiledObject object, + String propertyName, + String stringValue, + JAXXCompiler compiler) { + + try { + + object.addProperty(propertyName, stringValue); + ClassDescriptor type = getPropertyType(object, propertyName, compiler); + String binding = DataBindingHelper.processDataBindings(stringValue); + boolean withBinding = binding != null; + + if (!withBinding) { + // no bindings, convert from string + + // add support for i18n attributes (otherwise already done in DefaultComponentHandler) + if (I18nHelper.isI18nableAttribute(propertyName, compiler)) { + stringValue = I18nHelper.addI18nInvocation(object.getId(), propertyName, stringValue, compiler); + } + + try { + Class<?> typeClass = type != null ? + ClassDescriptorHelper.getClass(type.getName(), type.getClassLoader()) : + null; + Object value = convertFromString(propertyName, + stringValue, + typeClass + ); + setProperty(object, propertyName, value, compiler); + return; + } catch (NumberFormatException e) { + compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); + } catch (IllegalArgumentException e) { + compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); + } catch (ClassNotFoundException e) { + compiler.reportError("could not find class " + type.getName()); + } + } + String setPropertyCode = getSetPropertyCode(object.getJavaCode(), propertyName, binding, compiler); + if (propertyName.equals(LAYOUT_ATTRIBUTE)) { + + // try to add the layout class in imports + if (setPropertyCode.contains(BORDER_LAYOUT_PREFIX)) { + compiler.addImport(BorderLayout.class); + } else if (setPropertyCode.contains(GRID_LAYOUT_PREFIX)) { + compiler.addImport(GridLayout.class); + } + // handle containerDelegate (e.g. contentPane on JFrame) + // have to set layout early, before children are added + object.appendInitializationCode(setPropertyCode); + } + compiler.getBindingHelper().registerDataBinding( + object.getId() + "." + propertyName, + binding, + setPropertyCode + ); + } catch (UnsupportedAttributeException e) { + compiler.reportError("class " + object.getObjectClass().getName() + " does not support attribute '" + propertyName + "'"); + } + } + + /** + * Set a single property on an object. The value may be either a simple value or contain data binding expressions. + * Simple values are first converted to the property's type using {@link #convertFromString(String, String, Class)}. + * + * @param object the object on which to set the property + * @param propertyName the name of the property to set + * @param stringValue the raw string value of the property from the XML + * @param inline <code>true</code> if the value was directly specified as an inline class tag attribute, <code>false</code> otherwise (a default value, specified in CSS, etc.) + * @param compiler the current <code>JAXXCompiler</code> + */ + public void setAttribute(CompiledObject object, + String propertyName, + String stringValue, + boolean inline, + JAXXCompiler compiler) { + try { + //--------------------------------------------------------------------- + // BE WARE, Test if removing this code hurts..., anyway we have a bug on it: + // For some component (example : jaxx.runtime.swing.editor.NumberEditor) we do not have one component + // This is disturbing, must find how why... And this happens only on a mvn clean install on all project + // Everything is fine otherwise... + // + // With new binding design, we will know if there is a binding on the property + // of the jaxxObject, and could add it only if required... + //--------------------------------------------------------------------- + //FIXME TC-20091105 we should to this later when all binding are compiled + // because we don't know yet if this is a databinding +// if (ClassDescriptorHelper.getClassDescriptor(JAXXObject.class).isAssignableFrom(object.getObjectClass())) { +// // check for data binding & remove if found +// JAXXObjectDescriptor jaxxObjectDescriptor = object.getObjectClass().getJAXXObjectDescriptor(); +// if (jaxxObjectDescriptor.getComponentDescriptors().length == 0) { +// compiler.reportWarning("JAXXObject component " + object.getObjectClass() + " should have at least one component!"); +//// throw new IllegalStateException("JAXXObject component " + object.getObjectClass() + " should have at least one component!"); +// } else { +// ComponentDescriptor root = jaxxObjectDescriptor.getComponentDescriptors()[0]; +// //TC-20091026 do not prefix binding by object id if on root object +// String prefix; +// if (object == compiler.getRootObject()) { +// prefix = ""; +// } else { +// prefix = object.getJavaCode() + "."; +// } +// object.appendInitializationCode(prefix + "removeDataBinding(" + compiler.getJavaCode(root.getId() + "." + propertyName) + ");"); +// } +// } + object.addProperty(propertyName, stringValue); + ClassDescriptor type = getPropertyType(object, propertyName, compiler); + String binding = DataBindingHelper.processDataBindings(stringValue); + boolean withBinding = binding != null; + + if (inline) { + compiler.addInlineStyle(object, propertyName, withBinding); + } + if (!withBinding) { + // no bindings, convert from string + try { + Class<?> typeClass = type != null ? + ClassDescriptorHelper.getClass(type.getName(), type.getClassLoader()) : + null; + Object value = convertFromString(propertyName, + stringValue, + typeClass + ); + setProperty(object, propertyName, value, compiler); + return; + } catch (NumberFormatException e) { + compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); + } catch (IllegalArgumentException e) { + compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); + } catch (ClassNotFoundException e) { + compiler.reportError("could not find class " + type.getName()); + } + } + String setPropertyCode = getSetPropertyCode(object.getJavaCode(), propertyName, binding, compiler); + if (propertyName.equals(LAYOUT_ATTRIBUTE)) { + + // try to add the layout class in imports + if (setPropertyCode.contains(BORDER_LAYOUT_PREFIX)) { + compiler.addImport(BorderLayout.class); + } else if (setPropertyCode.contains(GRID_LAYOUT_PREFIX)) { + compiler.addImport(GridLayout.class); + } + // handle containerDelegate (e.g. contentPane on JFrame) + // have to set layout early, before children are added + object.appendInitializationCode(setPropertyCode); + } + compiler.getBindingHelper().registerDataBinding( + object.getId() + "." + propertyName, + binding, + setPropertyCode + ); + } catch (UnsupportedAttributeException e) { + compiler.reportError("class " + object.getObjectClass().getName() + " does not support attribute '" + propertyName + "'"); + } + } + + public void applyStylesheets(CompiledObject object, JAXXCompiler compiler) { + applyStylesheets(object, compiler, null); + } + + private void applyStylesheets(CompiledObject object, + JAXXCompiler compiler, + Stylesheet overrides) { + applyStylesheets(object, compiler, overrides, true); + } + + private void applyStylesheets(CompiledObject object, + JAXXCompiler compiler, + Stylesheet overrides, + boolean recurse) { + + Stylesheet stylesheet = compiler.getStylesheet(); + + ClassDescriptor objectClass = object.getObjectClass(); + ClassDescriptor jaxxObjectClassDescriptor = + ClassDescriptorHelper.getClassDescriptor(JAXXObject.class); + + // to apply styleSheet to a jaxx object, + // since 2.0.2, this process can be skip if configuration + // autoRecurseInCss is set to false since this does not work + boolean applyInside = + recurse && + jaxxObjectClassDescriptor.isAssignableFrom(objectClass) && + // new since 2.0.2 to skip old buggy mode + compiler.getConfiguration().isAutoRecurseInCss(); + + try { + + if (!applyInside) { + + // this is the safe mode to use, just apply stlySheet to object + if (stylesheet != null) { + StylesheetHelper.applyTo(object, + compiler, + stylesheet, + overrides + ); + } + return; + } + + //FIXME TC-20100430 This is an old mode which try to apply inside a + // detected jaxx object stysheets (cascade) : + // It does not work in fact and must be repair... + + JAXXObjectDescriptor jaxxObjectDescriptor = + objectClass.getJAXXObjectDescriptor(); + ComponentDescriptor[] descriptors = + jaxxObjectDescriptor.getComponentDescriptors(); + for (ComponentDescriptor descriptor : descriptors) { + ClassDescriptor classDescriptor = + ClassDescriptorHelper.getClassDescriptor( + descriptor.getJavaClassName() + ); + boolean isRoot = classDescriptor != objectClass; + String id = isRoot ? object.getId() + ' ' + descriptor.getId() : "( " + object.getId() + " ) " + descriptor.getId(); + CompiledObject child = new CompiledObject(id, + "((" + JAXXCompiler.getCanonicalName(classDescriptor) + ") " + + object.getJavaCode() + ".getObjectById(" + TypeManager.getJavaCode(descriptor.getId()) + "))", + classDescriptor, + compiler, + true); + ComponentDescriptor parentDescriptor = descriptor.getParent(); + CompiledObject currentObject = child; + while (parentDescriptor != null) { + CompiledObject parent = new CompiledObject("internal", ClassDescriptorHelper.getClassDescriptor(parentDescriptor.getJavaClassName()), compiler); + currentObject.setParent(parent); + currentObject = parent; + parentDescriptor = parentDescriptor.getParent(); + } + currentObject.setParent(object); + String styleClass = object.getStyleClass(); + if (styleClass == null) { + styleClass = descriptor.getStyleClass(); + } + child.setStyleClass(styleClass); + Stylesheet mergedStylesheet = overrides; + Stylesheet childOverrides = jaxxObjectDescriptor.getStylesheet(); + if (childOverrides != null) { + if (mergedStylesheet == null) { + mergedStylesheet = childOverrides; + } else { + mergedStylesheet.add(childOverrides.getRules()); + } + } + TagManager.getTagHandler(objectClass).applyStylesheets(child, compiler, mergedStylesheet, isRoot); + object.appendInitializationCode(child.getInitializationCode(compiler)); + } + } catch (ParseException e) { + compiler.reportError("Java parser exception on "+object+" in his css rules: "+e.getMessage()); + } catch (ClassNotFoundException e) { + throw new CompilerException(e); + } catch (IllegalArgumentException e) { + compiler.reportError(e.getMessage()); + } + } + + /** + * Adds the necessary Java code to a <code>CompiledObject</code> to add an event listener at runtime. + * + * @param object the <code>CompiledObject</code> to which the event listener should be added + * @param name the name of the event listener, such as <code>"actionPerformed"</code> + * @param value the Java code snippet to execute when the event is fired + * @param compiler the current <code>JAXXCompiler</code> + */ + public void addEventHandler(CompiledObject object, + String name, + String value, + JAXXCompiler compiler) { + JAXXEventSetDescriptor descriptorSet = events.get(name); + if (descriptorSet != null) { + MethodDescriptor[] listenerMethods = + descriptorSet.getListenerMethods(); + MethodDescriptor listenerMethod = null; + for (MethodDescriptor listenerMethod1 : listenerMethods) { + if (listenerMethod1.getName().equals(name)) { + listenerMethod = listenerMethod1; + break; + } + } + if (listenerMethod == null) { + throw new RuntimeException("expected to find method '" + name + "' in JAXXEventSetDescriptor.getListenerMethods()"); + } + try { + value = compiler.preprocessScript(value); + object.addEventHandler( + name, + descriptorSet.getAddListenerMethod(), + listenerMethod, + value, + compiler + ); + } catch (CompilerException e) { + compiler.reportError("While parsing event handler for '" + name + "': " + e.getMessage()); + } + } else { + compiler.reportError("could not find event '" + name + "' for object " + object); + } + } + + /** + * Returns a snippet of Java code which will retrieve an object property at runtime. Typically the code is + * just a call to the property's <code>get</code> method, but it can be arbitrarily complex. + * + * @param javaCode Java code for the object whose property is being retrieved + * @param name the name of the property to retrieve + * @param compiler the current <code>JAXXCompiler</code> + * @return the snippet + * @throws CompilerException if a compilation error occurs + */ + public String getGetPropertyCode(String javaCode, + String name, + JAXXCompiler compiler) { + safeInit(); + + JAXXPropertyDescriptor property = properties.get(name); + if (property != null) { + if (property.getReadMethodDescriptor() != null) { + return javaCode + '.' + property.getReadMethodDescriptor().getName() + "()"; + } + throw new UnsupportedAttributeException("property '" + name + "' of " + getBeanClass().getName() + " has no read method"); + } + throw new UnsupportedAttributeException("property '" + name + "' could not be found in class " + getBeanClass().getName()); + } + + /** + * Returns a snippet of Java code which will set an object property at runtime. Typically the code is + * just a call to the property's <code>set</code> method, but it can be arbitrarily complex. + * + * @param javaCode Java code for the object whose property is being set + * @param name the name of the property to set + * @param valueCode Java expression representing the value to set the property to + * @param compiler the current <code>JAXXCompiler</code> + * @return the snippet + * @throws CompilerException if a compilation error occurs + */ + public String getSetPropertyCode(String javaCode, + String name, + String valueCode, + JAXXCompiler compiler) { + JAXXPropertyDescriptor property = properties.get(name); + if (property != null) { + if (property.getWriteMethodDescriptor() != null) { + //TC-20091026 do not prefix by javaCode if on root object + String prefix; + if (compiler.getRootObject().getJavaCode().equals(javaCode)) { + prefix = ""; + } else { + prefix = javaCode + "."; + } + return prefix + property.getWriteMethodDescriptor().getName() + '(' + valueCode + ");"; + } + throw new UnsupportedAttributeException("property '" + name + "' of " + getBeanClass().getName() + " is read-only"); + } + throw new UnsupportedAttributeException("property '" + name + "' could not be found in class " + getBeanClass().getName()); + } + + /** + * Appends Java code to a <code>CompiledObject</code> in order to implement a property assignment. + * <code>setProperty</code> is invoked in response to most XML attributes (those which are not more + * complicated cases, like data bindings or event handlers). + * + * By the time it reaches this method, the <code>value</code> has already been converted from its XML + * string representation to the appropriate destination type for the property (i.e. if + * <code>JLabel.foreground</code> is being set, <code>value</code> will be a <code>Color</code>). + * + * @param object the object being modified + * @param name the name of the property to set + * @param value the value to set the property to + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if a compilation error occurs + */ + public void setProperty(CompiledObject object, + String name, + Object value, + JAXXCompiler compiler) { + object.appendInitializationCode( + getSetPropertyCode(object.getJavaCodeForProperty(name), + name, + TypeManager.getJavaCode(value), + compiler + ) + ); + } + + /** + * Maps string values onto integers, so that int-valued enumeration properties can be specified by strings. For + * example, when passed a key of 'alignment', this method should normally map the values 'left', 'center', and + * 'right' onto SwingConstants.LEFT, SwingConstants.CENTER, and SwingConstants.RIGHT respectively. + * + * You do not normally need to call this method yourself; it is invoked by {@link #convertFromString} when an + * int-valued property has a value which is not a valid number. By default, this method looks at the + * <code>enumerationValues</code> value of the <code>JAXXPropertyDescriptor</code>. + * + * @param key the name of the int-typed property + * @param value the non-numeric value that was specified for the property + * @return the constant integer value + * @throws IllegalArgumentException if the property is an enumeration, but the value is not valid + * @throws NumberFormatException if the property is not an enumeration + */ + protected int constantValue(String key, String value) { + JAXXBeanInfo JAXXBeanInfo = getJAXXBeanInfo(); + JAXXPropertyDescriptor[] props = + JAXXBeanInfo.getJAXXPropertyDescriptors(); + String lowercaseValue = value.toLowerCase(); + for (JAXXPropertyDescriptor property : props) { + if (property.getName().equals(key)) { + Object[] values = (Object[]) + property.getValue("enumerationValues"); + if (values != null) { + for (int j = 0; j < values.length - 2; j += 3) { + if (((String) values[j]).toLowerCase().equals(lowercaseValue)) { + return (Integer) values[j + 1]; + } + } + + StringBuilder message = + new StringBuilder("value of '" + + key + "' must be one of: ["); + for (int j = 0; j < values.length - 2; j += 3) { + if (j != 0) { + message.append(", "); + } + message.append(((String) values[j]).toLowerCase()); + } + message.append("] (found '").append(value).append("')"); + throw new IllegalArgumentException(message.toString()); + } + } + } + throw new NumberFormatException(value); + } + + /** + * As {@link TypeManager#convertFromString(String, Class)}, except that it additionally supports constant names + * for <code>int</code>-valued types. + * + * @param key the name of the property whose value is being converted + * @param value the raw string value of the property as it appears in the XML + * @param type the datatype to convert the string into + * @return the converted object + * @see #constantValue + */ + protected Object convertFromString(String key, String value, Class<?> type) { + if (type == null || Object.class.equals(type)) { + return value; + } + + try { + return TypeManager.convertFromString(value, type); + } catch (NumberFormatException e) { + if (int.class.equals(type) || Integer.class.equals(type)) { + return constantValue(key, value); + } + throw e; + } + } + + /** + * Compiles the child tags of the current tag. The default implementation invokes {@link #compileChildTagFirstPass} + * for each child tag. + * + * @param tag the tag whose children to run + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if a compilation error occurs + * @throws IOException if an I/O error occurs + */ + protected void compileChildrenFirstPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node node = children.item(i); + int nodeType = node.getNodeType(); + if (nodeType == Node.ELEMENT_NODE) { + Element child = (Element) node; + compileChildTagFirstPass(child, compiler); + } + } + } + + /** + * Compiles the child tags of the current tag. The default implementation invokes {@link #compileChildTagFirstPass} + * for each child tag. + * + * @param tag the tag whose children to run + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if a compilation error occurs + * @throws IOException if an I/O error occurs + */ + protected void compileChildrenSecondPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node node = children.item(i); + int nodeType = node.getNodeType(); + if (nodeType == Node.ELEMENT_NODE) { + Element child = (Element) node; + compileChildTagSecondPass(child, compiler); + } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { + String text = ((Text) node).getData().trim(); + if (text.length() > 0) { + compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); + } + } + } + } + + /** + * Compiles a child of the current tag. The default implementation calls {@link JAXXCompiler#compileFirstPass + * JAXXCompiler.compileFirstPass}. + * + * @param tag the child tag to run + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if a compilation error occurs + * @throws IOException if an I/O error occurs + */ + protected void compileChildTagFirstPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileFirstPass(tag); + } + + /** + * Compiles a child of the current tag. The default implementation calls {@link JAXXCompiler#compileFirstPass + * JAXXCompiler.compileSecondPass}. + * + * @param tag the child tag to run + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if a compilation error occurs + * @throws IOException if an I/O error occurs + */ + protected void compileChildTagSecondPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileSecondPass(tag); + } + + @Override + public String toString() { + return getClass().getName() + "[" + getBeanClass().getName() + "]"; + } + + protected void safeInit() { + try { + init(); + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/ImportHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/ImportHandler.java new file mode 100644 index 0000000..6929ff9 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/ImportHandler.java @@ -0,0 +1,101 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags; + +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.io.IOException; +import java.io.LineNumberReader; +import java.io.StringReader; + +/** + * Handles the <code><import></code> tag. + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Id$ + * @since 2.1 + */ +public class ImportHandler implements TagHandler { + + /** Logger */ + protected static final Log log = LogFactory.getLog(ImportHandler.class); + + public static final String TAG_NAME = "import"; + + @Override + public void compileFirstPass(Element tag, + JAXXCompiler compiler) throws IOException { + + StringBuilder script = new StringBuilder(); + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + switch (child.getNodeType()) { + case Node.ELEMENT_NODE: + compiler.reportError( + "<import> tag may not contain child elements: " + + tag); + case Node.TEXT_NODE: // fall through + case Node.CDATA_SECTION_NODE: + String txt = ((Text) child).getData(); + if (log.isDebugEnabled()) { + log.debug("Will treate imports :[\n" + txt + "\n]"); + } + String eol = JAXXCompiler.getLineSeparator(); + LineNumberReader reader = new LineNumberReader(new StringReader(txt.trim())); + try { + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (line.isEmpty()) { + continue; + } + script.append("import ").append(line); + if (!line.endsWith(";")) { + script.append(';'); + } + script.append(eol); + } + } finally { + reader.close(); + } + } + } + + String scriptString = script.toString().trim(); + if (!scriptString.isEmpty()) { + compiler.registerScript(script.toString()); + } + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) { + // nothing to do + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/ScriptHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/ScriptHandler.java new file mode 100644 index 0000000..e337b28 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/ScriptHandler.java @@ -0,0 +1,115 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.UnsupportedAttributeException; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.io.File; +import java.io.IOException; + +/** + * Handles the <code><script></code> tag. + * + * @author Ethan Nicholas + */ +public class ScriptHandler implements TagHandler { + + public static final String TAG_NAME = "script"; + + public static final String SOURCE_ATTRIBUTE = "source"; + + @Override + public void compileFirstPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + File scriptFile = null; + NamedNodeMap attributes = tag.getAttributes(); + for (int i = 0; i < attributes.getLength(); i++) { + Attr attribute = (Attr) attributes.item(i); + String name = attribute.getName(); + String attrValue = attribute.getValue(); + if (name.equals(SOURCE_ATTRIBUTE)) { + String filename = attrValue.replace('/', File.separatorChar); + scriptFile = new File(compiler.getBaseDir(), filename); + String content = compiler.loadFile(scriptFile); + compiler.registerScript(content, scriptFile); +// StringWriter scriptBuffer = new StringWriter(); +// FileReader in = new FileReader(scriptFile); +// try { +// char[] readBuffer = new char[2048]; +// int c; +// while ((c = in.read(readBuffer)) > 0) { +// scriptBuffer.write(readBuffer, 0, c); +// } +// } catch (FileNotFoundException e) { +// compiler.reportError( +// "script file not found: " + scriptFile); +// } finally { +// in.close(); +// } +// compiler.registerScript(scriptBuffer.toString(), scriptFile); + } else if (!name.startsWith(XMLNS_ATTRIBUTE) && + !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals( + attribute.getNamespaceURI())) { + throw new UnsupportedAttributeException(name); + } + } + + StringBuilder script = new StringBuilder(); + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + switch (child.getNodeType()) { + case Node.ELEMENT_NODE: + compiler.reportError( + "<script> tag may not contain child elements: " + + tag); + case Node.TEXT_NODE: // fall through + case Node.CDATA_SECTION_NODE: + script.append(((Text) child).getData()); + } + } + + String scriptString = script.toString().trim(); + if (scriptString.length() > 0) { + if (scriptFile != null) { + compiler.reportError( + "<script> tag has both a source attribute and an " + + "inline script"); + } + compiler.registerScript(script.toString()); + } + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + // nothing to do + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/StyleHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/StyleHandler.java new file mode 100644 index 0000000..7495070 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/StyleHandler.java @@ -0,0 +1,110 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.UnsupportedAttributeException; +import org.nuiton.jaxx.compiler.css.StylesheetHelper; +import org.nuiton.jaxx.runtime.css.Stylesheet; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.io.File; +import java.io.IOException; + +/** + * Handles the <code><style></code> tag. + * + * @author Ethan Nicholas + */ +public class StyleHandler implements TagHandler { + + public static final String TAG_NAME = "style"; + + public static final String SOURCE_ATTRIBUTE = "source"; + + @Override + public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + boolean source = false; + NamedNodeMap attributes = tag.getAttributes(); + for (int i = 0; i < attributes.getLength(); i++) { + Attr attribute = (Attr) attributes.item(i); + String name = attribute.getName(); + String attrValue = attribute.getValue(); + if (name.equals(SOURCE_ATTRIBUTE)) { + source = true; + File styleFile = new File(compiler.getBaseDir(), attrValue.replace('/', File.separatorChar)); + if (!styleFile.exists()) { + compiler.reportError("stylesheet file not found: " + styleFile); + } else { + compiler.registerStyleSheetFile(styleFile, true); + } + } else if (!name.startsWith(XMLNS_ATTRIBUTE) && + !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { + throw new UnsupportedAttributeException(name); + } + } + + StringBuilder style = new StringBuilder(); + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + switch (child.getNodeType()) { + case Node.ELEMENT_NODE: + compiler.reportError("<style> tag may not contain child elements: " + tag); + case Node.TEXT_NODE: // fall through + case Node.CDATA_SECTION_NODE: + style.append(((Text) child).getData()); + } + } + + String styleString = style.toString().trim(); + if (styleString.length() > 0) { + if (source) { + compiler.reportError("<style> tag has both a source attribute and an inline stylesheet"); + } + try { + Stylesheet stylesheet = StylesheetHelper.processStylesheet(style.toString()); + compiler.registerStylesheet(stylesheet); + } catch (CompilerException e) { + String message = "Inline Css content is not valid"; + if (e instanceof org.nuiton.jaxx.compiler.css.parser.ParseException) { + org.nuiton.jaxx.compiler.css.parser.ParseException parseException = (org.nuiton.jaxx.compiler.css.parser.ParseException) e; + + message += " (line: " + parseException.getLine() + " - col:" + parseException.getColumn() + ") "; + } + compiler.reportError(message, e); + } + } + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/TagHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/TagHandler.java new file mode 100644 index 0000000..1e6d078 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/TagHandler.java @@ -0,0 +1,68 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.w3c.dom.Element; + +import java.io.IOException; + +/** + * Implementations of <code>TagHandler</code> produce Java source code from XML tags. + * <code>TagHandlers</code> are mapped to particular XML tags (such as <JFrame>) in {@link JAXXCompiler}. + * There is only one <code>TagHandler</code> for any given XML tag, and therefore implementations must be + * stateless. + * + * @author Ethan Nicholas + */ +public interface TagHandler { + + String XMLNS_ATTRIBUTE = "xmlns"; + + /** + * Performs the first pass of compilation on an XML tag from a JAXX source file. + * <code>TagHandler</code> implementations affect the generated <code>.java</code> + * file by calling methods in the <code>JAXXCompiler</code>. + * + * @param tag the XML tag to compile + * @param compiler the active JAXXCompiler + * @throws CompilerException if a compilation error occurs + * @throws IOException if an I/O error occurs + */ + void compileFirstPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException; + + /** + * Performs the second pass of compilation on an XML tag from a JAXX source file. + * <code>TagHandler</code> implementations affect the generated <code>.java</code> + * file by calling methods in the <code>JAXXCompiler</code>. + * + * @param tag the XML tag to compile + * @param compiler the active JAXXCompiler + * @throws CompilerException if a compilation error occurs + * @throws IOException if an I/O error occurs + */ + void compileSecondPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException; +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/TagManager.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/TagManager.java new file mode 100644 index 0000000..8a5d123 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/TagManager.java @@ -0,0 +1,646 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags; + +import org.nuiton.jaxx.compiler.ClassMap; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Manages TagHandlers, including automatically compiling .jaxx files + * corresponding to class tags. + */ +public class TagManager { + + /** Logger */ + protected static final Log log = LogFactory.getLog(TagManager.class); + + /** Maps simple tag names to their default namespaces (package names). */ + private static Map<String, String> defaultNamespaces = + new HashMap<>(); + + /** Maps qualified tag names to the TagHandlers responsible for processing them. */ + private static Map<QName, TagHandler> registeredTags = + new HashMap<>(); + + /** Keeps track of whether or not named classes exist. */ + private static Map<String, Boolean> classExistenceCache = + new HashMap<>(); + + /** + * Maps bean classes to their TagHandler classes. The mapping is to + * TagHandler classes, rather than to TagHandler instances, + * because subclasses of the bean class should be handled by the same + * TagHandler (assuming no more specific mappings exist), which requires + * creating a new instance of the TagHandler. + */ + private static ClassMap<Class<? extends TagHandler>> registeredBeans = + new ClassMap<>(); + + // still targeting 1.4, so I can't use javax.xml.namespace.QName + + private static class QName { + + private String namespaceURI; + + private String localPart; + + public QName(String namespaceURI, String localPart) { + if (localPart == null) { + throw new NullPointerException(); + } + this.namespaceURI = namespaceURI; + this.localPart = localPart; + } + + public String getNamespaceURI() { + return namespaceURI; + } + + public String getLocalPart() { + return localPart; + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof QName)) { + return false; + } + QName qname = (QName) o; + return qname.getNamespaceURI().equals(getNamespaceURI()) && + qname.getLocalPart().equals(getLocalPart()); + } + + @Override + public int hashCode() { + return (namespaceURI != null ? namespaceURI.hashCode() : 0) ^ + getLocalPart().hashCode(); + } + } + + private TagManager() { /* not instantiable */ } + + public static void reset() { + registeredBeans.clear(); + registeredTags.clear(); + defaultNamespaces.clear(); + } + + /** + * Maps a class tag to a specific <code>TagHandler</code>. + * + * When a tag representing the bean class is encountered (either the + * class' simple name, if it is unambiguous, or its fully-qualified name), + * the specified <code>TagHandler</code> will be invoked to run it. + * + * @param <T> type of handler + * @param beanClass the class to associate with a <code>TagHandler</code> + * @param handler the <code>TagHandler</code> class, which must descend + * from <code>DefaultObjectHandler</code> + * @throws IllegalArgumentException if the handler class does not descend + * from <code>DefaultObjectHandler</code> + */ + public static <T extends TagHandler> void registerBean(ClassDescriptor beanClass, + Class<T> handler) { + if (!DefaultObjectHandler.class.isAssignableFrom(handler)) { + throw new IllegalArgumentException( + "handler class must be a subclass of DefaultObjectHandler"); + } + registeredBeans.put(beanClass, handler); + if (log.isDebugEnabled()) { + log.debug(beanClass + " : " + handler); + } + String name = beanClass.getName(); + int dotPos = name.lastIndexOf("."); + String namespace = name.substring(0, dotPos + 1) + "*"; + name = name.substring(dotPos + 1); + registerDefaultNamespace(name, namespace); + } + + /** + * Sets the default namespace for a tag. + * + * When the tag is encountered with no namespace specified, the specified + * namespace will be assumed. Mapping the same tag to two or more default + * namespaces removes the mapping and marks the entry as being ambiguous + * (by putting a <code>null</code> value into the map); this causes an + * error to be thrown if the tag is used without a namespace being specified. + * + * Java package names on tags are automatically converted into namespaces + * (e.g. <javax.swing.JButton/> and + * <JButton xmlns="javax.swing.*"/> are equivalent), so tags with + * package names are considered to have namespaces specified. + * + * @param tag tag name + * @param namespace namespace + */ + public static void registerDefaultNamespace(String tag, String namespace) { + if (defaultNamespaces.containsKey(tag) && + !defaultNamespaces.get(tag).equals(namespace)) { + defaultNamespaces.put(tag, null); // tag name is now ambiguous + } else { + defaultNamespaces.put(tag, namespace); + } + } + + /** + * Registers a <code>TagHandler</code> for a tag. + * + * When a tag with the given name and namespace is encountered, the + * <code>TagHandler's compileFirstPass</code> and <code>compileSecondPass</code> + * methods will be invoked to handle it. + * + * It is not an error to register an already-registered tag and namespace + * combination. The new mapping will replace the old mapping. + * + * @param <T> type of handler + * @param namespace the tag's namespace + * @param tag the simple name of the tag + * @param handler the <code>TagHandler</code> which should process the tag + */ + public static <T extends TagHandler> void registerTag(String namespace, + String tag, + T handler) { + if (namespace == null) { + namespace = "*"; + } + //System.out.println("registerTag "+namespace+" : "+tag+" : "+handler); + if (log.isDebugEnabled()) { + log.debug(tag + " : " + handler); + } + registeredTags.put(new QName(namespace, tag), handler); + registerDefaultNamespace(tag, namespace); + } + + /** + * Returns the <code>TagHandler</code> that should be used to process the + * specified tag. + * + * If the tag represents the class name of an uncompiled <code>.jaxx</code> + * file, the <code>.jaxx</code> is first compiled. + * + * @param namespace the tag's namespace (may be <code>null</code>) + * @param tag the tag's simple name + * @param compiler the current <code>JAXXCompiler</code> + * @return the <code>TagHandler</code> for the tag + * @throws CompilerException ? + */ + public static TagHandler getTagHandler(String namespace, + String tag, + JAXXCompiler compiler) throws CompilerException { + return getTagHandler(namespace, tag, false, compiler); + } + + private static String getNamespace(ClassDescriptor beanClass) { + String packageName = beanClass.getPackageName(); + return packageName != null ? packageName + ".*" : "*"; + + } + + private static String getSimpleName(ClassDescriptor beanClass) { + String packageName = beanClass.getPackageName(); + if (packageName != null) { + assert beanClass.getName().startsWith(packageName); + return beanClass.getName().substring(packageName.length() + 1); + } + return beanClass.getName(); + } + + /** + * @param klass the java class + * @return the <code>TagHandler</code> that should be used to process the + * specified class. + * Only <code>TagHandlers</code> previously registered with + * <code>registerBean</code> are considered. + * @throws CompilerException ? + */ + public static DefaultObjectHandler getTagHandler(Class<?> klass) throws CompilerException { + + ClassDescriptor beanClass = ClassDescriptorHelper.getClassDescriptor(klass); + return getTagHandler(beanClass); + } + + /** + * @param beanClass the tag class + * @return the <code>TagHandler</code> that should be used to process the + * specified class. + * + * Only <code>TagHandlers</code> previously registered with + * <code>registerBean</code> are considered. + * @throws CompilerException ? + */ + public static DefaultObjectHandler getTagHandler(ClassDescriptor beanClass) throws CompilerException { + try { + if (beanClass == null) { + throw new NullPointerException( + "beanClass parameter can not be null"); + } + if (beanClass.getName() == null) { + throw new NullPointerException( + "beanClass name can not be null : " + beanClass); + } + + String namespace = getNamespace(beanClass); + String tag = getSimpleName(beanClass); + DefaultObjectHandler handler = (DefaultObjectHandler) + registeredTags.get(new QName(namespace, tag)); + if (handler == null) { + Class<? extends TagHandler> handlerClass = + registeredBeans.get(beanClass); + if (handlerClass == null) { + if (beanClass.isInterface()) { + + // if an interface is a tag, avoid big problems... + + return null; + } + throw new CompilerException( + "unable to find handler for " + beanClass); + } + Constructor<? extends TagHandler> constructor = + handlerClass.getConstructor(ClassDescriptor.class); + handler = (DefaultObjectHandler) + constructor.newInstance(beanClass); + registerTag(namespace, tag, handler); + } + return handler; + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + private static boolean classExists(String className, JAXXCompiler compiler) { + if (classExistenceCache.containsKey(className)) { + return classExistenceCache.get(className); + } + + boolean found = false; + ClassLoader classLoader = compiler.getClassLoader(); + try { + Class.forName(className, true, classLoader); + found = true; + } catch (ClassNotFoundException e) { + // ignore ? + } catch (NoClassDefFoundError e) { + // we obtain this instead of ClassNotFoundException on + // case-insensitive file systems when looking up a class with the + // wrong case + } + + if (!found) { + // couldn't find .class, check for .java + URL javaURL = classLoader.getResource(className.replace('.', '/') + ".java"); + found = javaURL != null; + } + + if (!found) { + // couldn't find .java, check for .jaxx + URL jaxxURL = classLoader.getResource(className.replace('.', '/') + ".jaxx"); + found = jaxxURL != null; + } + + classExistenceCache.put(className, found); + + return found; + } + + private static String determinePackage(String simpleClassName, + String defaultPackage, + JAXXCompiler compiler) { + String namespace = null; + Set<String> classes = compiler.getImportedClasses(); + for (String className : classes) { + // search class imports (e.g. import java.util.Date;) + if (className.equals(simpleClassName) || + className.endsWith("." + simpleClassName)) { + namespace = className.substring(0, className.lastIndexOf(".") + 1) + "*"; + } + } + if (namespace == null) { + // search package imports (e.g. import java.util.*;) + Set<String> searchList = compiler.getImportedPackages(); + if (defaultPackage != null) { + if (!defaultPackage.endsWith("*")) { + throw new IllegalArgumentException( + "defaultPackage must end in '*', found '" + + defaultPackage + "'"); + } + String fqn = defaultPackage.substring( + 0, defaultPackage.length() - 1) + simpleClassName; + if (classExists(fqn, compiler)) { + return defaultPackage; + } + } + for (String currentPackage : searchList) { + String className = currentPackage + simpleClassName; + if (classExists(className, compiler)) { + if (namespace != null) { + // we've already found the same name in another package + compiler.reportError( + "symbol '" + simpleClassName + + "' is ambiguous, found matching classes " + + namespace.substring(0, namespace.length() - 1) + + simpleClassName + " and " + currentPackage + + simpleClassName + + ". Use fully-qualified name to disambiguate." + ); + return null; + } + namespace = currentPackage + "*"; + } + } + } + + return namespace; + } + + /** + * Returns the <code>TagHandler</code> that should be used to process the + * specified tag. + * + * The <code>namespacePrefix</code> parameter is used only for error + * checking, as it is an error to specify conflicting package names using + * both a fully-qualified tag name and a namespace prefix, but it is not + * an error to specify conflicting package names using a fully-qualified + * tag name and a <i>default</i> namespace (i.e. + * <awt:javax.swing.JButton xmlns:awt='java.awt.*'/> + * is an error, whereas <javax.swing.JButton xmlns='java.awt.*'/> is not). + * + * @param namespace the tag's namespace (may be <code>null</code>) + * @param tag the tag's simple name (which can include + * fully-qualified Java class names) + * @param namespacePrefix <code>true</code> if the namespace was specified + * by means of a namespace prefix (as opposed to a + * default namespace) + * @param compiler the current <code>JAXXCompiler</code> + * @return the <code>TagHandler</code> for the tag + * @throws CompilerException ? + */ + public static TagHandler getTagHandler(String namespace, + String tag, + boolean namespacePrefix, + JAXXCompiler compiler) throws CompilerException { + if (tag == null) { + throw new NullPointerException("tag parameter can not be null"); + } + if (namespace == null && defaultNamespaces.containsKey(tag)) { + namespace = defaultNamespaces.get(tag); + if (namespace == null) { + + // defaultNamespaces map contains a null value, which is put + // there to indicate ambiguity + compiler.reportError( + "tag '" + tag + "' is ambiguous; specify " + + "fully-qualified name (package and class) to " + + "disambiguate" + ); + return null; + } + } + + TagHandler handler = registeredTags.get(new QName(namespace, tag)); + if (handler == null) { + if (namespace == null || namespace.endsWith("*")) { + String className; + if (namespace != null) { + className = resolveClassName( + namespace.substring(0, namespace.length() - 1) + tag, + compiler + ); + if (className == null) { + className = resolveClassName(tag, compiler); + if (namespacePrefix && + !className.startsWith( + namespace.substring( + 0, + namespace.length() - 1))) { + + // namespace was specified, but we found it in a + // different package - ignore + className = null; + } + } + } else { + className = resolveClassName(tag, compiler); + } + if (className != null) { + int dotPos = className.lastIndexOf("."); + namespace = className.substring(0, dotPos + 1) + "*"; + tag = className.substring(dotPos + 1); + handler = registeredTags.get(new QName(namespace, tag)); + if (handler == null) { + try { + ClassDescriptor beanClass = + ClassDescriptorHelper.getClassDescriptor( + className, + compiler.getClassLoader() + ); + handler = getTagHandler(beanClass); + } catch (ClassNotFoundException e) { + log.error(e); +// e.printStackTrace(); + } + } + } + } + } + return handler; + } + + /** + * Resolves a simple class name (like <code>Object</code> or + * <code>String</code>) to its fully-qualified name. + * + * Inner classes should be represented as they would appear in Java source + * code (e.g. JPopupMenu.Separator). Fully-qualified names, such as + * <code>java.lang.Object</code> are legal and will be returned unmodified + * (and in fact it is generally impossible to even know whether a given + * reference is fully qualified until it has been resolved). + * + * Returns <code>null</code> if no matching class could be found. + * + * @param name name to resolve + * @param compiler run to use + * @return the resolved fqn class name + */ + public static String resolveClassName(String name, JAXXCompiler compiler) { + if (name.endsWith("[]")) { + return resolveClassName( + name.substring(0, name.length() - 2), compiler) + "[]"; + } + if (name.contains("<")) { + + // strip off generic types + name = name.substring(0, name.indexOf("<")); + } + + name = name.intern(); + if (name.equals("boolean") || + name.equals("byte") || + name.equals("short") || + name.equals("int") || + name.equals("long") || + name.equals("float") || + name.equals("double") || + name.equals("char")) { + return name; + } + + String result = null; + String originalName = name; + String defaultNamespace = null; + if (defaultNamespaces.containsKey(name)) { + defaultNamespace = defaultNamespaces.get(name); + if (defaultNamespace == null) { + + // defaultNamespaces map contains a null value, which is put + // there to indicate ambiguity + compiler.reportError( + "class '" + name + "' is ambiguous; specify " + + "fully-qualified name (package and class) to " + + "disambiguate" + ); + return null; + } + } + if (defaultNamespace != null && defaultNamespace.endsWith("*")) { + result = defaultNamespace.substring( + 0, defaultNamespace.length() - 1) + name; + } + + if (result == null) { + // Inner class names (like JPopupMenu.Separator) present a special + // challenge. The name before the dot might be a package name, + // or it might be a class name. + // + // If it's a class name, it might be fully qualified, or it might + // not. And it's also not actually the correct name of the class, + // as far as the JVM is concerned -- the correct name uses a dollar + // sign instead of a dot (javax.swing.JPopupMenu$Separator). + // And there could be more than one inner class -- it's possible to + // have com.mycompany.Outer$Inner$Innerer$Innerest. + // + // The basic strategy is to run by treating the part before the + // last dot as a package name, as that is by far the most likely case. + // + // If we don't find the class there, change the last dot to a + // dollar sign and try again. + + // Suppose we have the tag + // <com.mycompany.Outer.Inner.Innerer.Innerest/>, + // matching the class above. Resolution proceeds like this: + // com.mycompany.Outer.Inner.Innerer.* : Innerest + // com.mycompany.Outer.Inner.* : Innerer$Innerest + // com.mycompany.Outer.* : Inner$Innerer$Innerest + // com.mycompany.* : Outer$Inner$Innerer$Innerest + // And at this point we have a match with the class Outer$Inner$Innerer$Innerest in package com.mycompany. + int dotPos = originalName.lastIndexOf('.'); + for (; ; ) { + String namespace = dotPos != -1 ? originalName.substring(0, dotPos) + ".*" : "*"; + name = originalName.substring(dotPos + 1).replace('.', '$'); + String packageName = determinePackage(name, namespace, compiler); + if (packageName != null) { + assert packageName.endsWith("*"); + if (packageName.equals(namespace) || + namespace.equals("*")) { + // check for an alias (like javax.swing.JComboBox actually being org.nuiton.jaxx.runtime.swing.JAXXComboBox) + TagHandler handler = + registeredTags.get(new QName(namespace, name)); + + if (handler != null) { + + // determine alias by looking at handler + ClassDescriptor alias = + ((DefaultObjectHandler) handler).getBeanClass(); + + // make sure the same handler is used for both the + // aliased and non-aliased names, in order to avoid + // "no CompiledObject has been registered" error + // the line below doesn't bother to handle the case + // where the aliased class name doesn't have a + // package, since it's a pretty safe assumption that + // that will never happen + assert alias.getPackageName() != null && alias.getPackageName().length() > 0 : "aliasing with no package name has not been implemented"; + registeredTags.put( + new QName(alias.getPackageName() + ".*", alias.getName().substring(alias.getPackageName().length() + 1)), + handler + ); + result = alias.getName(); + break; + } else { // no alias + result = packageName.substring(0, packageName.length() - 1) + name; + break; + } + } + // else we found a class by the same name, but in the wrong package + } + + if (dotPos <= 0) { + break; + } + dotPos = originalName.lastIndexOf('.', dotPos - 1); + } + } + + if (result != null && !result.equals(originalName)) { + + // check for aliases against the new name as well + result = resolveClassName(result, compiler); + } + + return result; + } + + public static ClassDescriptor resolveClass(String className, + JAXXCompiler compiler) { + try { + className = resolveClassName(className, compiler); + if (className == null) { + return null; + } + return ClassDescriptorHelper.getClassDescriptor( + className, + compiler.getClassLoader() + ); + } catch (ClassNotFoundException e) { + return null; + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/ApplicationHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/ApplicationHandler.java new file mode 100644 index 0000000..c577100 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/ApplicationHandler.java @@ -0,0 +1,82 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.swing.Application; +import org.w3c.dom.Element; + +import javax.swing.WindowConstants; + +public class ApplicationHandler extends JWindowHandler { + + public static final String ATTRIBUTE_LOOK_AND_FEEL = "lookAndFeel"; + + public static final String ATTRIBUTE_DEFAULT_CLOSE_OPERATION = "defaultCloseOperation"; + + public ApplicationHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), + beanClass, + Application.class + ); + } + + @Override + public void setAttribute(CompiledObject object, + String propertyName, + String stringValue, + boolean inline, + JAXXCompiler compiler) throws CompilerException { + if (propertyName.equals(ATTRIBUTE_LOOK_AND_FEEL) && + stringValue != null && + !stringValue.trim().startsWith("{")) { + compiler.appendBodyCode("{ " + object.getJavaCode() + ".setLookAndFeel(" + TypeManager.getJavaCode(stringValue) + "); }" + JAXXCompiler.getLineSeparator()); + } else { + super.setAttribute(object, + propertyName, + stringValue, + inline, + compiler + ); + } + } + + @Override + protected void setDefaults(CompiledObject object, + Element tag, + JAXXCompiler compiler) throws CompilerException { + super.setDefaults(object, tag, compiler); + setAttribute(object, + ATTRIBUTE_DEFAULT_CLOSE_OPERATION, + String.valueOf(WindowConstants.EXIT_ON_CLOSE), + false, + compiler + ); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/CellHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/CellHandler.java new file mode 100644 index 0000000..e5584e2 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/CellHandler.java @@ -0,0 +1,221 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.UnsupportedAttributeException; +import org.nuiton.jaxx.compiler.tags.TagHandler; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.awt.GridBagConstraints; +import java.awt.Insets; +import java.io.IOException; + +public class CellHandler implements TagHandler { + + public static final String TAG_NAME = "cell"; + + public static final String ATTRIBUTE_INSETS = "insets"; + + public static final String ATTRIBUTE_WEIGHTX = "weightx"; + + public static final String ATTRIBUTE_WEIGHTY = "weighty"; + + public static final String ATTRIBUTE_COLUMNS = "columns"; + + public static final String ATTRIBUTE_ROWS = "rows"; + + public static final String ATTRIBUTE_FILL = "fill"; + + enum Fill { + none(GridBagConstraints.NONE), + horizontal(GridBagConstraints.HORIZONTAL), + vertical(GridBagConstraints.VERTICAL), + both(GridBagConstraints.BOTH); + + private final int intValue; + + Fill(int intValue) { + this.intValue = intValue; + } + + public int getIntValue() { + return intValue; + } + } + + public static final String ATTRIBUTE_ANCHOR = "anchor"; + + enum Anchor { + north(GridBagConstraints.NORTH), + northeast(GridBagConstraints.NORTHEAST), + east(GridBagConstraints.EAST), + southeast(GridBagConstraints.SOUTHEAST), + south(GridBagConstraints.SOUTH), + southwest(GridBagConstraints.SOUTHEAST), + west(GridBagConstraints.WEST), + northwest(GridBagConstraints.NORTHWEST), + center(GridBagConstraints.CENTER); + + private final int intValue; + + Anchor(int intValue) { + this.intValue = intValue; + } + + public int getIntValue() { + return intValue; + } + } + + @Override + public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compileChildrenFirstPass(tag, compiler); + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + Node parent = tag.getParentNode(); + if (parent.getNodeType() != Node.ELEMENT_NODE || !parent.getLocalName().equals("row")) { + compiler.reportError("cell tag may only appear within row tag"); + return; + } + + TableHandler.CompiledTable table = (TableHandler.CompiledTable) compiler.getOpenComponent(); + table.newCell(); + GridBagConstraints c = table.getCellConstraints(); + setAttributes(c, tag); + compileChildrenSecondPass(tag, compiler); + } + + public static void setAttribute(GridBagConstraints c, String name, String value) throws CompilerException { + value = value.trim(); + if (name.equals(ATTRIBUTE_INSETS)) { + c.insets = (Insets) TypeManager.convertFromString(value, Insets.class); + } else if (name.equals(ATTRIBUTE_WEIGHTX)) { + c.weightx = Double.parseDouble(value); + } else if (name.equals(ATTRIBUTE_WEIGHTY)) { + c.weighty = Double.parseDouble(value); + } else if (name.equals(ATTRIBUTE_COLUMNS)) { + c.gridwidth = Integer.parseInt(value); + } else if (name.equals(ATTRIBUTE_ROWS)) { + c.gridheight = Integer.parseInt(value); + } else if (name.equals(ATTRIBUTE_FILL)) { + Fill fill = Fill.valueOf(value); + if (fill == null) { + throw new CompilerException("invalid value for fill attribute: '" + value + "'"); + } + c.fill = fill.getIntValue(); + } else if (name.equals(ATTRIBUTE_ANCHOR)) { + Anchor anchor = Anchor.valueOf(value); + if (anchor == null) { + throw new CompilerException("invalid value for anchor attribute: '" + value + "'"); + } + c.anchor = anchor.getIntValue(); +// if (value.equals(ANCHOR_VALUE_NORTH)) { +// c.anchor = GridBagConstraints.NORTH; +// } else if (value.equals(ANCHOR_VALUE_NORTHEAST)) { +// c.anchor = GridBagConstraints.NORTHEAST; +// } else if (value.equals(ANCHOR_VALUE_EAST)) { +// c.anchor = GridBagConstraints.EAST; +// } else if (value.equals(ANCHOR_VALUE_SOUTHEAST)) { +// c.anchor = GridBagConstraints.SOUTHEAST; +// } else if (value.equals(ANCHOR_VALUE_SOUTH)) { +// c.anchor = GridBagConstraints.SOUTH; +// } else if (value.equals(ANCHOR_VALUE_SOUTHWEST)) { +// c.anchor = GridBagConstraints.SOUTHWEST; +// } else if (value.equals(ANCHOR_VALUE_WEST)) { +// c.anchor = GridBagConstraints.WEST; +// } else if (value.equals(ANCHOR_VALUE_NORTHWEST)) { +// c.anchor = GridBagConstraints.NORTHWEST; +// } else if (value.equals(ANCHOR_VALUE_CENTER)) { +// c.anchor = GridBagConstraints.CENTER; +// } else { +// throw new IllegalArgumentException("invalid value for anchor attribute: '" + value + "'"); +// } + } else { + throw new UnsupportedAttributeException(name); + } + } + + public static void setAttributes(GridBagConstraints c, Element tag) throws CompilerException { + NamedNodeMap children = tag.getAttributes(); + for (int i = 0; i < children.getLength(); i++) { + Attr attribute = (Attr) children.item(i); + String name = attribute.getName(); + String value = attribute.getValue(); + if (!name.startsWith("xmlns") && !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { + setAttribute(c, name, value); + } + } + } + + protected void compileChildrenFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node node = children.item(i); + int nodeType = node.getNodeType(); + if (nodeType == Node.ELEMENT_NODE) { + Element child = (Element) node; + compileChildTagFirstPass(child, compiler); + } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { + String text = ((Text) node).getData().trim(); + if (text.length() > 0) { + compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); + } + } + } + } + + protected void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node node = children.item(i); + int nodeType = node.getNodeType(); + if (nodeType == Node.ELEMENT_NODE) { + Element child = (Element) node; + compileChildTagSecondPass(child, compiler); + } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { + String text = ((Text) node).getData().trim(); + if (text.length() > 0) { + compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); + } + } + } + } + + protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileFirstPass(tag); + } + + protected void compileChildTagSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileSecondPass(tag); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/CompiledItemContainer.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/CompiledItemContainer.java new file mode 100644 index 0000000..d732767 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/CompiledItemContainer.java @@ -0,0 +1,69 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.runtime.swing.Item; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +/** Compiled representation of a class that contains Items arranged in a list or tree structure (JComboBox, JList, JTree). */ +class CompiledItemContainer extends CompiledObject { + + private List<Item> items = new ArrayList<>(); + + private Stack<Item> openNodes = new Stack<>(); + + public CompiledItemContainer(String id, ClassDescriptor objectClass, JAXXCompiler compiler) throws CompilerException { + super(id, objectClass, compiler); + } + + public void openItem(Item item) { + if (openNodes.isEmpty()) { + items.add(item); + } else { + Item openNode = openNodes.peek(); + openNode.addChild(item); + } + openNodes.add(item); + } + + public void closeItem(Item item) { + if (!item.equals(openNodes.pop())) { + throw new IllegalArgumentException(item + " was not at the top of the item stack"); + } + } + + public List<Item> getItems() { + return items; + } + + public void setItems(List<Item> items) { + this.items = items; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/ItemHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/ItemHandler.java new file mode 100644 index 0000000..f59bf38 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/ItemHandler.java @@ -0,0 +1,174 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.UnsupportedAttributeException; +import org.nuiton.jaxx.compiler.binding.DataBindingHelper; +import org.nuiton.jaxx.compiler.tags.TagHandler; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.swing.Item; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.io.IOException; +import java.util.List; + +public class ItemHandler implements TagHandler { + + public static final String TAG_NAME = "item"; + + private String DATA_BINDING = "<data binding has not been processed yet>"; + + public static final String ATTRIBUTE_ID = "id"; + + @Override + public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compileChildrenFirstPass(tag, compiler); + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + String id = tag.getAttribute(ATTRIBUTE_ID); + if (id == null || id.length() == 0) { + id = compiler.getAutoId(Item.class.getSimpleName()); +// id = compiler.getAutoId(ClassDescriptorHelper.getClassDescriptor(Item.class)); + } + String label = null; + String value = null; + boolean selected = false; + NamedNodeMap children = tag.getAttributes(); + + for (int i = 0; i < children.getLength(); i++) { + Attr attribute = (Attr) children.item(i); + String name = attribute.getName(); + String attrValue = attribute.getValue(); + if (name.equals(ATTRIBUTE_ID)) { + // already handled + continue; + } + DataBindingHelper bindingHelper = compiler.getBindingHelper(); + if (name.equals(Item.LABEL_PROPERTY)) { + String labelBinding = DataBindingHelper.processDataBindings(attrValue); + if (labelBinding != null) { + bindingHelper.registerDataBinding(id + ".label", labelBinding, id + ".setLabel(" + labelBinding + ");"); +// bindingHelper.registerDataBinding(labelBinding, id + ".label", id + ".setLabel(" + labelBinding + ");"); + } else { + label = attrValue; + } + continue; + } + if (name.equals(Item.VALUE_PROPERTY)) { + String valueBinding = DataBindingHelper.processDataBindings(attrValue); + if (valueBinding != null) { + value = DATA_BINDING; + bindingHelper.registerDataBinding(id + ".value", valueBinding, id + ".setValue(" + valueBinding + ");"); +// bindingHelper.registerDataBinding(valueBinding, id + ".value", id + ".setValue(" + valueBinding + ");"); + } else { + value = attrValue; + } + continue; + } + if (name.equals(Item.SELECTED_PROPERTY)) { + String selectedBinding = DataBindingHelper.processDataBindings(attrValue); + if (selectedBinding != null) { + bindingHelper.registerDataBinding(id + ".selected", selectedBinding, id + ".setSelected(" + selectedBinding + ");"); +// bindingHelper.registerDataBinding(selectedBinding, id + ".selected", id + ".setSelected(" + selectedBinding + ");"); + } else { + selected = (Boolean) TypeManager.convertFromString(attrValue, Boolean.class); + } + continue; + } + + if (!name.startsWith("xmlns") && !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { + throw new UnsupportedAttributeException(name); + } + } + + Item item = new Item(id, label, value, selected); + CompiledItemContainer list = (CompiledItemContainer) compiler.getOpenComponent(); + if (value == null) { + compiler.reportError("<item> tag is missing required 'value' attribute"); + } else { + if (!value.equals(DATA_BINDING)) { + List<Item> items = list.getItems(); + for (Item item1 : items) { + if (item1.getValue().equals(value)) { + compiler.reportError("This container already has an <item> tag with the value '" + value + "'"); + break; + } + } + } + list.openItem(item); + compileChildrenSecondPass(tag, compiler); + list.closeItem(item); + } + } + + protected void compileChildrenFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node node = children.item(i); + int nodeType = node.getNodeType(); + if (nodeType == Node.ELEMENT_NODE) { + Element child = (Element) node; + compileChildTagFirstPass(child, compiler); + } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { + String text = ((Text) node).getData().trim(); + if (text.length() > 0) { + compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); + } + } + } + } + + protected void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node node = children.item(i); + int nodeType = node.getNodeType(); + if (nodeType == Node.ELEMENT_NODE) { + Element child = (Element) node; + compileChildTagSecondPass(child, compiler); + } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { + String text = ((Text) node).getData().trim(); + if (text.length() > 0) { + compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); + } + } + } + } + + protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileFirstPass(tag); + } + + protected void compileChildTagSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileSecondPass(tag); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JAXXComboBoxHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JAXXComboBoxHandler.java new file mode 100644 index 0000000..02e8a81 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JAXXComboBoxHandler.java @@ -0,0 +1,80 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.swing.Item; +import org.nuiton.jaxx.runtime.swing.JAXXComboBox; +import org.w3c.dom.Element; + +import java.awt.event.ItemListener; +import java.io.IOException; +import java.util.List; + +public class JAXXComboBoxHandler extends DefaultComponentHandler { + + public JAXXComboBoxHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JAXXComboBox.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getSelectedIndex", ItemListener.class); + addProxyEventInfo("getSelectedItem", ItemListener.class); + } + + @Override + protected CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledItemContainer(id, getBeanClass(), compiler); + } + + @Override + public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + super.compileChildrenSecondPass(tag, compiler); + CompiledItemContainer list = (CompiledItemContainer) compiler.getOpenComponent(); + List<Item> items = list.getItems(); + if (items != null && !items.isEmpty()) { + String listName = list.getId() + "$items"; + list.appendAdditionCode("java.util.List<org.nuiton.jaxx.runtime.swing.Item> " + listName + " = new java.util.ArrayList<org.nuiton.jaxx.runtime.swing.Item>();"); + for (Item item : items) { + String id = item.getId(); + CompiledObject compiledItem = new CompiledObject(id, ClassDescriptorHelper.getClassDescriptor(Item.class), compiler); + compiledItem.setConstructorParams(TypeManager.getJavaCode(id) + ", " + TypeManager.getJavaCode(item.getLabel()) + ", " + TypeManager.getJavaCode(item.getValue()) + ", " + item.isSelected()); + compiler.registerCompiledObject(compiledItem); + list.appendAdditionCode(listName + ".add(" + id + ");"); + } + list.appendAdditionCode(list.getId() + ".setItems(" + listName + ");"); + } + } +} + + + diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JAXXListHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JAXXListHandler.java new file mode 100644 index 0000000..fe8adb2 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JAXXListHandler.java @@ -0,0 +1,83 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.swing.Item; +import org.nuiton.jaxx.runtime.swing.JAXXList; +import org.w3c.dom.Element; + +import javax.swing.event.ListSelectionListener; +import java.io.IOException; +import java.util.List; + +public class JAXXListHandler extends DefaultComponentHandler { + + public JAXXListHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JAXXList.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getSelectedIndex", ListSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectedIndices", ListSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectedValue", ListSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectedValues", ListSelectionListener.class, "selectionModel"); + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledItemContainer(id, getBeanClass(), compiler); + } + + @Override + public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + super.compileChildrenSecondPass(tag, compiler); + CompiledItemContainer list = (CompiledItemContainer) compiler.getOpenComponent(); + List<Item> items = list.getItems(); + if (items != null && !items.isEmpty()) { + String listName = list.getId() + "$items"; + //TODO Add the correct generic type + list.appendAdditionCode("java.util.List<org.nuiton.jaxx.runtime.swing.Item> " + listName + " = new java.util.ArrayList<org.nuiton.jaxx.runtime.swing.Item>();"); + for (Item item : items) { + String id = item.getId(); + CompiledObject compiledItem = new CompiledObject(id, ClassDescriptorHelper.getClassDescriptor(Item.class), compiler); + compiledItem.setConstructorParams(TypeManager.getJavaCode(id) + ", " + TypeManager.getJavaCode(item.getLabel()) + ", " + TypeManager.getJavaCode(item.getValue()) + ", " + item.isSelected()); + compiler.registerCompiledObject(compiledItem); + list.appendAdditionCode(listName + ".add(" + id + ");"); + } + list.appendAdditionCode(list.getId() + ".setItems(" + listName + ");"); + } + } +} + + + diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JAXXTabHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JAXXTabHandler.java new file mode 100644 index 0000000..02a66e3 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JAXXTabHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; + +/** @author Tony Chemit - chemit@codelutin.com */ +public class JAXXTabHandler extends TableHandler { + + public JAXXTabHandler(ClassDescriptor beanClass) { + super(beanClass); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JAXXTreeHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JAXXTreeHandler.java new file mode 100644 index 0000000..4ab3ff9 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JAXXTreeHandler.java @@ -0,0 +1,88 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.swing.Item; +import org.nuiton.jaxx.runtime.swing.JAXXTree; +import org.w3c.dom.Element; + +import javax.swing.event.TreeSelectionListener; +import java.io.IOException; +import java.util.List; + +public class JAXXTreeHandler extends DefaultComponentHandler { + + public JAXXTreeHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JAXXTree.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getSelectionCount", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionPath", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionPaths", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionRows", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionValue", TreeSelectionListener.class, "selectionModel"); + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledItemContainer(id, getBeanClass(), compiler); + } + + private void createItems(CompiledObject tree, List<Item> items, String addMethod, JAXXCompiler compiler) throws CompilerException { + for (Item item : items) { + String id = item.getId(); + CompiledObject compiledItem = new CompiledObject(id, ClassDescriptorHelper.getClassDescriptor(Item.class), compiler); + compiledItem.setConstructorParams(TypeManager.getJavaCode(id) + ", " + TypeManager.getJavaCode(item.getLabel()) + ", " + TypeManager.getJavaCode(item.getValue()) + ", " + item.isSelected()); + compiler.registerCompiledObject(compiledItem); + tree.appendAdditionCode(addMethod + "(" + id + ");"); + createItems(tree, item.getChildren(), id + ".addChild", compiler); + } + } + + @Override + public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + super.compileChildrenSecondPass(tag, compiler); + CompiledItemContainer tree = (CompiledItemContainer) compiler.getOpenComponent(); + List<Item> items = tree.getItems(); + if (items != null && !items.isEmpty()) { + String listName = tree.getId() + "$items"; + tree.appendAdditionCode("java.util.List<org.nuiton.jaxx.runtime.swing.Item> " + listName + " = new java.util.ArrayList<org.nuiton.jaxx.runtime.swing.Item>();"); + createItems(tree, items, listName + ".add", compiler); + tree.appendAdditionCode(tree.getId() + ".setItems(" + listName + ");"); + } + } +} + + + diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JCheckBoxHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JCheckBoxHandler.java new file mode 100644 index 0000000..a7c314e --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JCheckBoxHandler.java @@ -0,0 +1,44 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; + +import javax.swing.AbstractButton; +import javax.swing.event.ChangeListener; + +public class JCheckBoxHandler extends DefaultComponentHandler { + + public JCheckBoxHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, AbstractButton.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("isSelected", ChangeListener.class, "model"); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JComboBoxHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JComboBoxHandler.java new file mode 100644 index 0000000..6207f58 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JComboBoxHandler.java @@ -0,0 +1,62 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import javax.swing.JComboBox; +import java.awt.event.ItemListener; +import java.io.IOException; + +public class JComboBoxHandler extends DefaultComponentHandler { + + public JComboBoxHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JComboBox.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getSelectedIndex", ItemListener.class); + addProxyEventInfo("getSelectedItem", ItemListener.class); + } + + @Override + public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + if (children.getLength() > 0) { + compiler.reportError("JComboBox does not accept childs"); + throw new CompilerException("JComboBox does not accept childs"); + } + } +} + + + diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JInternalFrameHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JInternalFrameHandler.java new file mode 100644 index 0000000..7b2694d --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JInternalFrameHandler.java @@ -0,0 +1,72 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Element; + +import javax.swing.JInternalFrame; +import javax.swing.JMenuBar; +import javax.swing.WindowConstants; + +public class JInternalFrameHandler extends DefaultComponentHandler { + + public JInternalFrameHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JInternalFrame.class); + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledObject(id, getBeanClass(), compiler) { + + @Override + public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { + if (ClassDescriptorHelper.getClassDescriptor(JMenuBar.class).isAssignableFrom(child.getObjectClass())) { + appendAdditionCode(getId() + ".setJMenuBar(" + child.getId() + ");"); + } else { + super.addChild(child, constraints, compiler); + } + } + }; + } + + @Override + protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + super.setDefaults(object, tag, compiler); + setAttribute(object, "visible", "true", false, compiler); + setAttribute(object, "closable", "true", false, compiler); + setAttribute(object, "defaultCloseOperation", String.valueOf(WindowConstants.DISPOSE_ON_CLOSE), false, compiler); + } + + @Override + public void setAttributes(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + super.setAttributes(object, tag, compiler); + compiler.appendInitializerCode(object.getId() + ".pack();\n"); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JListHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JListHandler.java new file mode 100644 index 0000000..fbc4779 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JListHandler.java @@ -0,0 +1,64 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import javax.swing.JList; +import javax.swing.event.ListSelectionListener; +import java.io.IOException; + +public class JListHandler extends DefaultComponentHandler { + + public JListHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JList.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getSelectedIndex", ListSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectedIndices", ListSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectedValue", ListSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectedValues", ListSelectionListener.class, "selectionModel"); + } + + @Override + public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + if (children.getLength() > 0) { + compiler.reportError("JList does not accept childs"); + throw new CompilerException("JList does not accept childs"); + } + } +} + + + diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JMenuHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JMenuHandler.java new file mode 100644 index 0000000..5a64b3b --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JMenuHandler.java @@ -0,0 +1,44 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; + +import javax.swing.JMenu; +import javax.swing.event.MenuListener; + +public class JMenuHandler extends DefaultComponentHandler { + + public JMenuHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JMenu.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("isSelected", MenuListener.class); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JPasswordFieldHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JPasswordFieldHandler.java new file mode 100644 index 0000000..3b42edd --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JPasswordFieldHandler.java @@ -0,0 +1,43 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; + +import javax.swing.JPasswordField; +import javax.swing.event.DocumentListener; + +public class JPasswordFieldHandler extends JTextComponentHandler { + + public JPasswordFieldHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JPasswordField.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getPassword", DocumentListener.class, "document"); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JPopupMenuHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JPopupMenuHandler.java new file mode 100644 index 0000000..cd3c363 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JPopupMenuHandler.java @@ -0,0 +1,50 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Element; + +import javax.swing.JPopupMenu; + +public class JPopupMenuHandler extends DefaultComponentHandler { + + public JPopupMenuHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JPopupMenu.class); + } + + @Override + public boolean isContainer() { + return true; + } + + @Override + protected void openComponent(CompiledObject object, Element tag, JAXXCompiler compiler) { + compiler.openInvisibleComponent(object); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JProgressBarHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JProgressBarHandler.java new file mode 100644 index 0000000..41caad3 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JProgressBarHandler.java @@ -0,0 +1,44 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; + +import javax.swing.JProgressBar; +import javax.swing.event.ChangeListener; + +public class JProgressBarHandler extends DefaultComponentHandler { + + public JProgressBarHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JProgressBar.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getValue", ChangeListener.class, "change"); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JRadioButtonHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JRadioButtonHandler.java new file mode 100644 index 0000000..1e0260d --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JRadioButtonHandler.java @@ -0,0 +1,106 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.UnsupportedAttributeException; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.swing.JAXXButtonGroup; + +import javax.swing.AbstractButton; +import javax.swing.ButtonGroup; +import javax.swing.event.ChangeListener; + +public class JRadioButtonHandler extends DefaultComponentHandler { + + private static final String VALUE_PROPERTY = JAXXButtonGroup.VALUE_CLIENT_PROPERTY.substring(1); + + private static final String BUTTON_GROUP_PROPERTY = JAXXButtonGroup.BUTTON8GROUP_CLIENT_PROPERTY.substring(1); + + public JRadioButtonHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, AbstractButton.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("isSelected", ChangeListener.class, "model"); + } + + @Override + public ClassDescriptor getPropertyType(CompiledObject object, String name, JAXXCompiler compiler) throws CompilerException { + if (name.equals(BUTTON_GROUP_PROPERTY)) { + return null; // accepts either a String or a ButtonGroup + } else if (name.equals(VALUE_PROPERTY)) { + return ClassDescriptorHelper.getClassDescriptor(Object.class); + } else { + return super.getPropertyType(object, name, compiler); + } + } + + @Override + public boolean isMemberBound(String name) throws UnsupportedAttributeException { + return !(name.equals(BUTTON_GROUP_PROPERTY) || name.equals(VALUE_PROPERTY)) && super.isMemberBound(name); + } + + // handle buttonGroup assignment in addition block rather than initialization block + @Override + public void setProperty(CompiledObject object, String name, Object value, JAXXCompiler compiler) { + if (name.equals(BUTTON_GROUP_PROPERTY)) { + object.appendAdditionCode(getSetPropertyCode(object.getJavaCode(), name, TypeManager.getJavaCode(value), compiler)); + } else { + super.setProperty(object, name, value, compiler); + } + } + + @Override + public String getSetPropertyCode(String id, String name, String valueCode, JAXXCompiler compiler) throws CompilerException { + if (name.equals(BUTTON_GROUP_PROPERTY)) { + if (valueCode.startsWith("\"") && valueCode.endsWith("\"")) { + valueCode = valueCode.substring(1, valueCode.length() - 1); + CompiledObject buttonGroup = compiler.getCompiledObject(valueCode); + if (buttonGroup == null) { + buttonGroup = new CompiledObject(valueCode, ClassDescriptorHelper.getClassDescriptor(JAXXButtonGroup.class), compiler); + compiler.registerCompiledObject(buttonGroup); + } + } + String type = compiler.getImportedType( + ButtonGroup.class.getName()); + + return "{ " + type + " $buttonGroup = " + valueCode + "; " + id + ".putClientProperty(\"$buttonGroup\", $buttonGroup); $buttonGroup.add(" + id + "); }\n"; + } else if (name.equals(VALUE_PROPERTY)) { + String type = compiler.getImportedType( + JAXXButtonGroup.class.getName()); + return "{ " + id + ".putClientProperty(\"" + JAXXButtonGroup.VALUE_CLIENT_PROPERTY + "\", " + valueCode + "); Object $buttonGroup = " + id + ".getClientProperty(\"" + JAXXButtonGroup.BUTTON8GROUP_CLIENT_PROPERTY + "\");" + + " if ($buttonGroup instanceof " + type + ") { ((" + type + ") $buttonGroup).updateSelectedValue(); } }\n"; + } else { + return super.getSetPropertyCode(id, name, valueCode, compiler); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JScrollPaneHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JScrollPaneHandler.java new file mode 100644 index 0000000..2d2155a --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JScrollPaneHandler.java @@ -0,0 +1,101 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.apache.commons.lang3.StringUtils; + +import javax.swing.JScrollPane; + +public class JScrollPaneHandler extends DefaultComponentHandler { + + public static class JScrollPaneCompiledObject extends CompiledObject { + + boolean hasChild; + + boolean hasColumnViewHeader; + + public static final String COLUMN_HEADER_VIEW = "columnHeaderView"; + + public JScrollPaneCompiledObject(String id, + ClassDescriptor beanclass, + JAXXCompiler compiler) { + super(id, beanclass, compiler); + } + + @Override + public void addChild(CompiledObject child, + String constraints, + JAXXCompiler compiler) throws CompilerException { + if (constraints != null) { + compiler.reportError("JScrollPane does not accept constraints"); + } + + if (!hasChild) { + // first child is always the view port component + super.addChild(child, constraints, compiler); + hasChild = true; + return; + } + + if (!hasColumnViewHeader) { + + // try to add a column view header + String property = + (String) getProperties().get(COLUMN_HEADER_VIEW); + + if (log.isDebugEnabled()) { + log.info("property to match " + property + " against child " + child.getId()); + } + if (!StringUtils.isEmpty(property) && + ("{" + child.getId() + "}").equals(property)) { + hasColumnViewHeader = true; + return; + } + } + + compiler.reportError( + "JScrollPane may only have one child (found another child : " + child.getId() + ")."); + + } + } + + public JScrollPaneHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), + beanClass, + JScrollPane.class + ); + } + + @Override + public CompiledObject createCompiledObject(String id, + JAXXCompiler compiler) throws CompilerException { + return new JScrollPaneCompiledObject(id, getBeanClass(), compiler); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JSliderHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JSliderHandler.java new file mode 100644 index 0000000..9b0ab2a --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JSliderHandler.java @@ -0,0 +1,67 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; + +import javax.swing.JSlider; +import javax.swing.event.ChangeListener; + +public class JSliderHandler extends DefaultComponentHandler { + public static final String ATTRIBUTE_VALUE = "value"; + + public JSliderHandler(ClassDescriptor beanClass) { + super(beanClass); + if (!ClassDescriptorHelper.getClassDescriptor(JSlider.class).isAssignableFrom(beanClass)) { + throw new IllegalArgumentException(getClass().getName() + " does not support the class " + beanClass.getName()); + } + } + + @Override + protected int getAttributeOrdering(Attr attr) { + if (attr.getName().equals(ATTRIBUTE_VALUE)) { + return 1; + } else { + return super.getAttributeOrdering(attr); + } + } + + @Override + protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + super.setDefaults(object, tag, compiler); + setAttribute(object, ATTRIBUTE_VALUE, "0", false, compiler); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getValue", ChangeListener.class, "model"); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JSpinnerHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JSpinnerHandler.java new file mode 100644 index 0000000..e87fea8 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JSpinnerHandler.java @@ -0,0 +1,121 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Element; + +import javax.swing.JSpinner; +import javax.swing.SpinnerNumberModel; +import javax.swing.event.ChangeListener; + +public class JSpinnerHandler extends DefaultComponentHandler { + + public static String MINIMUM_PROPERTY = "minimum"; + + public static String MAXIMUM_PROPERTY = "maximum"; + + public static String VALUE_PROPERTY = "value"; + + public JSpinnerHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JSpinner.class); + } + + public static class CompiledSpinner extends CompiledObject { + + Integer minimum; + + Integer maximum; + + Integer value; + + public CompiledSpinner(String id, ClassDescriptor objectClass, JAXXCompiler compiler) throws CompilerException { + super(id, objectClass, compiler); + } + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledSpinner(id, getBeanClass(), compiler); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getValue", ChangeListener.class, "model"); + } + + @Override + public ClassDescriptor getPropertyType(CompiledObject object, String propertyName, JAXXCompiler compiler) throws CompilerException { + if (propertyName.equals(MINIMUM_PROPERTY) || propertyName.equals(MAXIMUM_PROPERTY) || + propertyName.equals(VALUE_PROPERTY)) { + return ClassDescriptorHelper.getClassDescriptor(Integer.class); + } + return super.getPropertyType(object, propertyName, compiler); + } + + @Override + public void setProperty(CompiledObject object, String name, Object value, JAXXCompiler compiler) throws CompilerException { + if (name.equals(MINIMUM_PROPERTY)) { + ((CompiledSpinner) object).minimum = (Integer) value; + } else if (name.equals(MAXIMUM_PROPERTY)) { + ((CompiledSpinner) object).maximum = (Integer) value; + } else if (name.equals(VALUE_PROPERTY)) { + ((CompiledSpinner) object).value = (Integer) value; + } else { + super.setProperty(object, name, value, compiler); + } + } + + @Override + protected void closeComponent(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + CompiledSpinner spinner = (CompiledSpinner) object; + if (spinner.minimum != null || + spinner.maximum != null || + spinner.value != null) { + if (spinner.getConstructorParams() != null) { + compiler.reportError("constructorParams and minimum/maximum may not both be specified for the same JSpinner"); + } + if (spinner.minimum == null) { + spinner.minimum = Math.min(0, spinner.maximum != null ? spinner.maximum : 0); + } + if (spinner.maximum == null) { + spinner.maximum = Math.max(100, spinner.minimum.intValue()); + } + if (spinner.value == null) { + spinner.value = spinner.minimum; + } + String type = compiler.getImportedType(SpinnerNumberModel.class); + + spinner.setConstructorParams("new " + type + "(" + spinner.value + ", " + spinner.minimum + ", " + spinner.maximum + ", 1)"); + } + + super.closeComponent(object, tag, compiler); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JSplitPaneHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JSplitPaneHandler.java new file mode 100644 index 0000000..2d414df --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JSplitPaneHandler.java @@ -0,0 +1,99 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; + +import javax.swing.JSplitPane; + +public class JSplitPaneHandler extends DefaultComponentHandler { + + public static final String ATTRIBUTE_ORIENTATION = "orientation"; + + public static final String ORIENTATION_VALUE_HORIZONTAL = "horizontal"; + + public static final String ORIENTATION_VALUE_VERTICAL = "vertical"; + + public static final String ORIENTATION_VALUE_VERTICAL_SPLIT = "vertical_split"; + + public static final String ORIENTATION_VALUE_HORIZONTAL_SPLIT = "horizontal_split"; + + public JSplitPaneHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JSplitPane.class); + } + +// protected Component createRawComponent(Element tag) { +// return new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); +// } + + /** + * Add support for <code>orientation="vertical"</code> and <code>orientation="horizontal"</code>. The + * values required by the JAXXBeanInfo are the unwieldy <code>vertical_split</code> and <code>horizontal_split</code> + * (which are also recognized). + */ + @Override + protected int constantValue(String key, String value) { + if (key.equals(ATTRIBUTE_ORIENTATION)) { + value = value.trim().toLowerCase(); + if (value.equals(ORIENTATION_VALUE_HORIZONTAL) || + value.equals(ORIENTATION_VALUE_HORIZONTAL_SPLIT)) { + return JSplitPane.HORIZONTAL_SPLIT; + } + if (value.equals(ORIENTATION_VALUE_VERTICAL) || + value.equals(ORIENTATION_VALUE_VERTICAL_SPLIT)) { + return JSplitPane.VERTICAL_SPLIT; + } + throw new IllegalArgumentException("orientation must be 'horizontal' or 'vertical', found '" + value + "'"); + } + return super.constantValue(key, value); + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledObject(id, getBeanClass(), compiler) { + + private int count; + + @Override + public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { + if (constraints != null) { + compiler.reportError("JSplitPane does not accept constraints"); + } + if (count == 0) { + super.addChild(child, "JSplitPane.LEFT", compiler); + } else if (count == 1) { + super.addChild(child, "JSplitPane.RIGHT", compiler); + } else { + compiler.reportError("JSplitPane is limited to two children"); + } + count++; + } + }; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JTabbedPaneHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JTabbedPaneHandler.java new file mode 100644 index 0000000..242bd69 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JTabbedPaneHandler.java @@ -0,0 +1,168 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.I18nHelper; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.swing.TabInfo; +import org.nuiton.jaxx.runtime.swing.TabInfoPropertyChangeListener; + +import javax.swing.Icon; +import javax.swing.JTabbedPane; +import javax.swing.event.ChangeListener; +import java.awt.Color; +import java.awt.event.ContainerListener; + +public class JTabbedPaneHandler extends DefaultComponentHandler { + + public static final String ATTRIBUTE_TITLE = "title"; + + public static final String ATTRIBUTE_TOOL_TIP_TEXT = "toolTipText"; + + public JTabbedPaneHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JTabbedPane.class); + } + + public static class CompiledTabbedPane extends CompiledObject { + + private static final TabInfo USED = new TabInfo("ALREADY USED"); + + int tabCount; + + TabInfo tabInfo; + + + public CompiledTabbedPane(String id, ClassDescriptor objectClass, JAXXCompiler compiler) throws CompilerException { + super(id, objectClass, compiler); + } + + @Override + public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { + if (constraints != null) { + compiler.reportError("JTabbedPane tabs may not have constraints"); + } + + super.addChild(child, constraints, compiler); + + if (tabInfo == null) { + compiler.reportError("JTabbedPaneHandler may only have 'tab' tags as children (found " + child.getObjectClass() + ")"); + return; + } else if (USED.equals(tabInfo)) { + compiler.reportError("<tab> tags may only have one child component"); + return; + } + + int tabIndex = ++tabCount - 1; + String type = compiler.getImportedType(TabInfoPropertyChangeListener.class); + appendAdditionCode(tabInfo.getId() + ".addPropertyChangeListener(new " + type + "(" + getId() + ", " + tabIndex + "));"); + + String title = tabInfo.getTitle(); + if (title != null) { + if (I18nHelper.isI18nAttribute(ATTRIBUTE_TITLE)) { + if (!title.startsWith("t(\"")) { + // we did not have the invocation code, add it + title = I18nHelper.addI18nInvocation(getId(), ATTRIBUTE_TITLE, TypeManager.getJavaCode(title), compiler); + } + } else { + title = TypeManager.getJavaCode(title); + } + appendAdditionCode(getId() + ".setTitleAt(" + tabIndex + ", " + title + ");"); + } + + String toolTipText = tabInfo.getToolTipText(); + if (toolTipText != null) { + if (I18nHelper.isI18nAttribute(ATTRIBUTE_TOOL_TIP_TEXT)) { + if (!toolTipText.startsWith("t(\"")) { + // we did not have the invocation code, add it + toolTipText = I18nHelper.addI18nInvocation(getId(), ATTRIBUTE_TOOL_TIP_TEXT, TypeManager.getJavaCode(toolTipText), compiler); + } + } else { + toolTipText = TypeManager.getJavaCode(toolTipText); + } + appendAdditionCode(getId() + ".setToolTipTextAt(" + tabIndex + ", " + toolTipText + ");"); + } + + boolean enabled = tabInfo.isEnabled(); + if (!enabled) { + appendAdditionCode(getId() + ".setEnabledAt(" + tabIndex + ", false);"); + } + + Color foreground = tabInfo.getForeground(); + if (foreground != null) { + appendAdditionCode(getId() + ".setForegroundAt(" + tabIndex + ", " + TypeManager.getJavaCode(foreground) + ");"); + } + + Color background = tabInfo.getBackground(); + if (background != null) { + appendAdditionCode(getId() + ".setBackgroundAt(" + tabIndex + ", " + TypeManager.getJavaCode(background) + ");"); + } + + int mnemonic = tabInfo.getMnemonic(); + if (mnemonic != -1) { + appendAdditionCode(getId() + ".setMnemonicAt(" + tabIndex + ", " + mnemonic + ");"); + } + + int displayedMnemonicIndex = tabInfo.getDisplayedMnemonicIndex(); + if (displayedMnemonicIndex != -1) { + appendAdditionCode(getId() + ".setDisplayedMnemonicIndexAt(" + tabIndex + ", " + displayedMnemonicIndex + ");"); + } + + Icon icon = tabInfo.getIcon(); + if (icon != null) { + appendAdditionCode(getId() + ".setIconAt(" + tabIndex + ", " + icon + ");"); + } + + Icon disabledIcon = tabInfo.getDisabledIcon(); + if (disabledIcon != null) { + appendAdditionCode(getId() + ".setDisabledIconAt(" + tabIndex + ", " + disabledIcon + ");"); + } + + String tabComponent = tabInfo.getTabComponentStr(); + if (tabComponent != null) { + appendAdditionCode(getId() + ".setTabComponentAt(" + tabIndex + ", " + tabComponent + ");"); + } + + tabInfo = USED; + } + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledTabbedPane(id, getBeanClass(), compiler); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getSelectedIndex", ChangeListener.class); + addProxyEventInfo("getSelectedComponent", ChangeListener.class); + addProxyEventInfo("getTabCount", ContainerListener.class); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JTextComponentHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JTextComponentHandler.java new file mode 100644 index 0000000..54f6dba --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JTextComponentHandler.java @@ -0,0 +1,112 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; + +import javax.swing.JTextArea; +import javax.swing.event.DocumentListener; +import javax.swing.text.JTextComponent; + +public class JTextComponentHandler extends DefaultComponentHandler { + + private static final int DEFAULT_COLUMNS = 15; + + public static final String ATTRIBUTE_LINE_WRAP = "lineWrap"; + + public static final String ATTRIBUTE_WRAP_STYLE_WORD = "wrapStyleWord"; + + public static final String ATTRIBUTE_COLUMNS = "columns"; + + public static final String ATTRIBUTE_TEXT = "text"; + + public JTextComponentHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), + beanClass, + JTextComponent.class); + } + + @Override + protected void setDefaults(CompiledObject object, + Element tag, + JAXXCompiler compiler) throws CompilerException { + super.setDefaults(object, tag, compiler); + try { + object.getObjectClass().getMethodDescriptor("setColumns", + ClassDescriptorHelper.getClassDescriptor(int.class) + ); + setAttribute(object, + ATTRIBUTE_COLUMNS, + String.valueOf(DEFAULT_COLUMNS), + false, + compiler + ); + } catch (NoSuchMethodException e) { + // ignore ? + } + + if (ClassDescriptorHelper.getClassDescriptor(JTextArea.class).isAssignableFrom(object.getObjectClass())) { + setAttribute(object, ATTRIBUTE_LINE_WRAP, "true", false, compiler); + setAttribute(object, ATTRIBUTE_WRAP_STYLE_WORD, "true", false, compiler); + } + } + + @Override + public String getSetPropertyCode(String id, + String name, + String valueCode, + JAXXCompiler compiler) throws CompilerException { + if (name.equals(ATTRIBUTE_TEXT)) { + String prefix = compiler.getImportedType(SwingUtil.class); + return prefix + ".setText(" + + id + ", " + valueCode + ");" + + JAXXCompiler.getLineSeparator(); + } + return super.getSetPropertyCode(id, name, valueCode, compiler); + } + + @Override + protected int getAttributeOrdering(Attr attr) { + // delay text in case other attributes affect how it's processed, as is the case + // with JEditorPane's contentType + if (ATTRIBUTE_TEXT.equals(attr.getName())) { + return 1; + } + return super.getAttributeOrdering(attr); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getText", DocumentListener.class, "document"); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JToolBarHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JToolBarHandler.java new file mode 100644 index 0000000..a9c2cff --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JToolBarHandler.java @@ -0,0 +1,78 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; + +import javax.swing.JToolBar; + +public class JToolBarHandler extends DefaultComponentHandler { + + public static final String ATTRIBUTE_ORIENTATION = "orientation"; + + enum Orientation { + horizontal(JToolBar.HORIZONTAL), + vertical(JToolBar.VERTICAL); + + private final int intValue; + + Orientation(int intValue) { + this.intValue = intValue; + } + + public int getIntValue() { + return intValue; + } + } + + public JToolBarHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), + beanClass, + JToolBar.class + ); + } + + /** + * Add support for <code>orientation="vertical"</code> and <code>orientation="horizontal"</code>. These values should + * have been supported without any special effort on my part, but JToolBar's BeanInfo doesn't contain the enum attribute + * for the orientation property. + */ + @Override + protected int constantValue(String key, String value) { + if (ATTRIBUTE_ORIENTATION.equals(key)) { + value = value.trim().toLowerCase(); + Orientation fill = Orientation.valueOf(value); + if (fill == null) { + throw new CompilerException( + "invalid value for orientation attribute: '" + value + + "'"); + } + return fill.getIntValue(); + } + return super.constantValue(key, value); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JTreeHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JTreeHandler.java new file mode 100644 index 0000000..08080b8 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JTreeHandler.java @@ -0,0 +1,65 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import javax.swing.JTree; +import javax.swing.event.TreeSelectionListener; +import java.io.IOException; + +public class JTreeHandler extends DefaultComponentHandler { + + public JTreeHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JTree.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getSelectionCount", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionPath", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionPaths", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionRows", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionValue", TreeSelectionListener.class, "selectionModel"); + } + + @Override + public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + if (children.getLength() > 0) { + compiler.reportError("JTree does not accept childs"); + throw new CompilerException("JTree does not accept childs"); + } + } +} + + + diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JWindowHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JWindowHandler.java new file mode 100644 index 0000000..183b80d --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JWindowHandler.java @@ -0,0 +1,80 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Element; + +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JMenuBar; +import javax.swing.JWindow; +import java.io.IOException; +import java.util.Map; + +public class JWindowHandler extends DefaultComponentHandler { + + public JWindowHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JWindow.class, JFrame.class, JDialog.class); + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledObject(id, getBeanClass(), compiler) { + + @Override + public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { + if (ClassDescriptorHelper.getClassDescriptor(JMenuBar.class).isAssignableFrom(child.getObjectClass())) { + appendAdditionCode(getId() + ".setJMenuBar(" + child.getId() + ");"); + } else { + super.addChild(child, constraints, compiler); + } + } + }; + } + + @Override + protected void openComponent(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + if (compiler.getOpenComponent() != null) { + compiler.openInvisibleComponent(object); + } else { + super.openComponent(object, tag, compiler); + } + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + super.compileSecondPass(tag, compiler); + CompiledObject object = objectMap.get(tag); + Map<?, ?> properties = object.getProperties(); + if (!properties.containsKey("width") && !properties.containsKey("height")) { + compiler.appendLateInitializer(object.getId() + ".pack();\n"); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JXLayerHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JXLayerHandler.java new file mode 100644 index 0000000..5a063c9 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/JXLayerHandler.java @@ -0,0 +1,108 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.apache.commons.collections4.CollectionUtils; +import org.jdesktop.jxlayer.JXLayer; + +import java.awt.Component; + +/** + * To deal with JXLayer, since from version 3.0.4, we can not use any longer + * the {@link JXLayer#add(Component)} ! but must now use the + * method {@link JXLayer#setView(Component)}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.4 + */ +public class JXLayerHandler extends DefaultComponentHandler { + + public static final String ATTRIBUTE_ORIENTATION = "orientation"; + + public static final String ORIENTATION_VALUE_HORIZONTAL = "horizontal"; + + public static final String ORIENTATION_VALUE_VERTICAL = "vertical"; + + public static final String ORIENTATION_VALUE_VERTICAL_SPLIT = "vertical_split"; + + public static final String ORIENTATION_VALUE_HORIZONTAL_SPLIT = "horizontal_split"; + + public JXLayerHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JXLayer.class); + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledObject(id, getBeanClass(), compiler) { + + @Override + public void addChild(CompiledObject child, + String constraints, + JAXXCompiler compiler) throws CompilerException { + + if (constraints != null) { + compiler.reportError("JXLayer does not accept constraints"); + return; + } + if (CollectionUtils.isNotEmpty(getChilds())) { + + // already one child, authrozied only one child... + compiler.reportError("JXLayer is limited to one children"); + return; + } + super.addChild(child, constraints, compiler); + + } + + @Override + protected ChildRef newChildRef(CompiledObject child, String constraints, String delegateCode) { + return new ChildRef(child, + constraints, + child.getJavaCode(), + delegateCode) { + @Override + public void addToAdditionCode(StringBuilder buffer, boolean isRootObject) { + //TC-20091026 do not prefix if on root object + String prefix; + if (isRootObject) { + prefix = ""; + } else { + prefix = getJavaCode() + getDelegateCode() + "."; + } + buffer.append(prefix); + buffer.append("setView("); + buffer.append(getChildJavaCode()); + buffer.append(");"); + buffer.append(JAXXCompiler.getLineSeparator()); + } + }; + } + }; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/RowHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/RowHandler.java new file mode 100644 index 0000000..4f22689 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/RowHandler.java @@ -0,0 +1,108 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.TagHandler; +import org.nuiton.jaxx.runtime.swing.Table; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.awt.GridBagConstraints; +import java.io.IOException; + +public class RowHandler implements TagHandler { + + public static final String TAG_NAME = "row"; + + @Override + public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compileChildrenFirstPass(tag, compiler); + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + if (!ClassDescriptorHelper.getClassDescriptor(Table.class).isAssignableFrom(compiler.getOpenComponent().getObjectClass())) { + compiler.reportError("row tag may only appear within Table tag"); + return; + } + + TableHandler.CompiledTable table = (TableHandler.CompiledTable) compiler.getOpenComponent(); + table.newRow(); + GridBagConstraints c = table.getRowConstraints(); + CellHandler.setAttributes(c, tag); + compileChildrenSecondPass(tag, compiler); + } + + public void compileChildrenFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node node = children.item(i); + int nodeType = node.getNodeType(); + if (nodeType == Node.ELEMENT_NODE) { + Element child = (Element) node; + if (!child.getLocalName().equals(CellHandler.TAG_NAME)) { + compiler.reportError("tag '" + tag.getLocalName() + "' may only contain cell tags as children"); + } + compileChildTagFirstPass(child, compiler); + } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { + String text = ((Text) node).getData().trim(); + if (text.length() > 0) { + compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); + } + } + } + } + + public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node node = children.item(i); + int nodeType = node.getNodeType(); + if (nodeType == Node.ELEMENT_NODE) { + Element child = (Element) node; + if (!child.getLocalName().equals(CellHandler.TAG_NAME)) { + compiler.reportError("tag '" + tag.getLocalName() + "' may only contain cell tags as children"); + } + compileChildTagSecondPass(child, compiler); + } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { + String text = ((Text) node).getData().trim(); + if (text.length() > 0) { + compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); + } + } + } + } + + protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileFirstPass(tag); + } + + protected void compileChildTagSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileSecondPass(tag); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/TabHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/TabHandler.java new file mode 100644 index 0000000..a6201db --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/TabHandler.java @@ -0,0 +1,218 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.I18nHelper; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.binding.DataBindingHelper; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.TagHandler; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.swing.TabInfo; +import org.apache.commons.lang3.StringUtils; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import javax.swing.Icon; +import javax.swing.JTabbedPane; +import java.awt.Color; +import java.io.IOException; + +public class TabHandler implements TagHandler { + + public static final String TAG_NAME = "tab"; + + public static final String ATTRIBUTE_ID = "id"; + + public static final String ATTRIBUTE_TITLE = "title"; + + public static final String ATTRIBUTE_TOOL_TIP_TEXT = "toolTipText"; + + public static final String ATTRIBUTE_ICON = "icon"; + + public static final String ATTRIBUTE_ENABLED = "enabled"; + + public static final String ATTRIBUTE_DISABLED_ICON = "disabledIcon"; + + public static final String ATTRIBUTE_MNEMONIC = "mnemonic"; + + public static final String ATTRIBUTE_DISPLAYED_MNEMONIC_INDEX = "displayedMnemonicIndex"; + + public static final String ATTRIBUTE_FOREGROUND = "foreground"; + + public static final String ATTRIBUTE_BACKGROUND = "background"; + + public static final String ATTRIBUTE_TAB_COMPONENT = "tabComponent"; + + @Override + public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compileChildrenFirstPass(tag, compiler); + } + + @Override + public void compileSecondPass(Element tag, final JAXXCompiler compiler) throws CompilerException, IOException { + if (!ClassDescriptorHelper.getClassDescriptor(JTabbedPane.class).isAssignableFrom(compiler.getOpenComponent().getObjectClass())) { + compiler.reportError("tab tag may only appear within JTabbedPane tag"); + return; + } + + JTabbedPaneHandler.CompiledTabbedPane tabs = (JTabbedPaneHandler.CompiledTabbedPane) compiler.getOpenComponent(); + + String id = tag.getAttribute(ATTRIBUTE_ID); + if (id == null || id.length() == 0) { + id = compiler.getAutoId(TabInfo.class.getSimpleName()); +// id = compiler.getAutoId(ClassDescriptorHelper.getClassDescriptor(TabInfo.class)); + } + TabInfo tabInfo = new TabInfo(id); + CompiledObject compiledTabInfo = new CompiledObject(id, ClassDescriptorHelper.getClassDescriptor(TabInfo.class), compiler); + compiler.registerCompiledObject(compiledTabInfo); + //id = tabInfo.getId(); + tabs.tabInfo = tabInfo; + setAttributes(compiledTabInfo, tabs, tag, compiler); + compileChildrenSecondPass(tag, compiler); + tabs.tabInfo = null; + } + + public static void setAttribute(CompiledObject compiledTabInfo, JTabbedPaneHandler.CompiledTabbedPane tabs, String name, String value, JAXXCompiler compiler) throws CompilerException { + value = value.trim(); + TabInfo tabInfo = tabs.tabInfo; + String id = tabInfo.getId(); + String binding = DataBindingHelper.processDataBindings(value); + if (binding != null) { + compiler.getBindingHelper().registerDataBinding(id + "." + name, binding, id + ".set" + StringUtils.capitalize(name) + "(" + binding + ");"); +// compiler.getBindingHelper().registerDataBinding(binding, id + "." + name, id + ".set" + StringUtils.capitalize(name) + "(" + binding + ");"); + return; + } + + String valueCode = TypeManager.getJavaCode(value); + + // add i18n support + if (I18nHelper.isI18nableAttribute(name, compiler)) { + value = valueCode = I18nHelper.addI18nInvocation(id, name, valueCode, compiler); + } + if (name.equals(ATTRIBUTE_ID)) { + // ignore, already handled + } else if (name.equals(ATTRIBUTE_TITLE)) { + tabInfo.setTitle(value); + compiledTabInfo.appendInitializationCode(id + ".setTitle(" + valueCode + ");"); + //compiledTabInfo.appendInitializationCode(id + ".setTitle(" + TypeManager.getJavaCode(value) + ");"); + } else if (name.equals(ATTRIBUTE_TOOL_TIP_TEXT)) { + tabInfo.setToolTipText(value); + compiledTabInfo.appendInitializationCode(id + ".setToolTipText(" + valueCode + ");"); + //compiledTabInfo.appendInitializationCode(id + ".setToolTipText(" + TypeManager.getJavaCode(value) + ");"); + } else if (name.equals(ATTRIBUTE_ICON)) { + Icon icon = (Icon) TypeManager.convertFromString(value, Icon.class); + tabInfo.setIcon(icon); + compiledTabInfo.appendInitializationCode(id + ".setIcon(" + TypeManager.getJavaCode(icon) + ");"); + } else if (name.equals(ATTRIBUTE_ENABLED)) { + boolean enabled = (Boolean) TypeManager.convertFromString(value, Boolean.class); + tabInfo.setEnabled(enabled); + compiledTabInfo.appendInitializationCode(id + ".setEnabled(" + enabled + ");"); + } else if (name.equals(ATTRIBUTE_DISABLED_ICON)) { + Icon disabledIcon = (Icon) TypeManager.convertFromString(value, Icon.class); + tabInfo.setDisabledIcon(disabledIcon); + compiledTabInfo.appendInitializationCode(id + ".setDisabledIcon(" + TypeManager.getJavaCode(disabledIcon) + ");"); + } else if (name.equals(ATTRIBUTE_MNEMONIC)) { + int mnemonic = (Character) TypeManager.convertFromString(value, char.class); + tabInfo.setMnemonic(mnemonic); + compiledTabInfo.appendInitializationCode(id + ".setMnemonic(" + mnemonic + ");"); + } else if (name.equals(ATTRIBUTE_DISPLAYED_MNEMONIC_INDEX)) { + int displayedMnemonicIndex = (Integer) TypeManager.convertFromString(value, int.class); + tabInfo.setDisplayedMnemonicIndex(displayedMnemonicIndex); + compiledTabInfo.appendInitializationCode(id + ".setDisplayedMnemonicIndex(" + displayedMnemonicIndex + ");"); + } else if (name.equals(ATTRIBUTE_FOREGROUND)) { + Color foreground = (Color) TypeManager.convertFromString(value, Color.class); + tabInfo.setForeground(foreground); + compiledTabInfo.appendInitializationCode(id + ".setForeground(" + TypeManager.getJavaCode(foreground) + ");"); + } else if (name.equals(ATTRIBUTE_BACKGROUND)) { + Color background = (Color) TypeManager.convertFromString(value, Color.class); + tabInfo.setBackground(background); + compiledTabInfo.appendInitializationCode(id + ".setBackground(" + TypeManager.getJavaCode(background) + ");"); + } else if (name.equals(ATTRIBUTE_TAB_COMPONENT)) { + tabInfo.setTabComponentStr(TypeManager.getJavaCode(value)); + compiledTabInfo.appendInitializationCode(id + ".setTabComponent(" + TypeManager.getJavaCode(value) + ");"); + } else { + compiler.reportError("The <tab> tag does not support the attribute '" + name + "'"); + } + } + + public void setAttributes(CompiledObject compiledTabInfo, JTabbedPaneHandler.CompiledTabbedPane tabs, Element tag, JAXXCompiler compiler) throws CompilerException { + NamedNodeMap children = tag.getAttributes(); + for (int i = 0; i < children.getLength(); i++) { + Attr attribute = (Attr) children.item(i); + String name = attribute.getName(); + String value = attribute.getValue(); + if (!name.startsWith("xmlns") && !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { + setAttribute(compiledTabInfo, tabs, name, value, compiler); + } + } + } + + protected void compileChildrenFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node node = children.item(i); + int nodeType = node.getNodeType(); + if (nodeType == Node.ELEMENT_NODE) { + Element child = (Element) node; + compileChildTagFirstPass(child, compiler); + } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { + String text = ((Text) node).getData().trim(); + if (text.length() > 0) { + compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); + } + } + } + } + + protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileFirstPass(tag); + } + + protected void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node node = children.item(i); + int nodeType = node.getNodeType(); + if (nodeType == Node.ELEMENT_NODE) { + Element child = (Element) node; + compileChildTagSecondPass(child, compiler); + } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { + String text = ((Text) node).getData().trim(); + if (text.length() > 0) { + compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); + } + } + } + } + + protected void compileChildTagSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileSecondPass(tag); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/TableHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/TableHandler.java new file mode 100644 index 0000000..85a7190 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/swing/TableHandler.java @@ -0,0 +1,175 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.swing; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.UnsupportedAttributeException; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultComponentHandler; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.runtime.swing.Table; + +import java.awt.GridBagConstraints; +import java.awt.Insets; +import java.util.ArrayList; +import java.util.List; + +public class TableHandler extends DefaultComponentHandler { + + public static final Insets DEFAULT_INSETS = new Insets(3, 3, 3, 3); + + public TableHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), + beanClass, + Table.class); + } + + @Override + public void setAttribute(CompiledObject object, + String propertyName, + String stringValue, + boolean inline, + JAXXCompiler compiler) throws CompilerException { + try { + if (object instanceof CompiledTable) { + CellHandler.setAttribute( + ((CompiledTable) object).getTableConstraints(), + propertyName, + stringValue + ); + } else { + super.setAttribute(object, + propertyName, + stringValue, + inline, + compiler); + } + } catch (UnsupportedAttributeException e) { + super.setAttribute(object, + propertyName, + stringValue, + inline, + compiler + ); + } + } + + class CompiledTable extends CompiledObject { + + private List<Integer> rowSpans = new ArrayList<>(); + + private GridBagConstraints tableConstraints; + + private GridBagConstraints rowConstraints; + + private GridBagConstraints cellConstraints; + + private boolean emptyCell; + + public CompiledTable(String id, + ClassDescriptor objectClass, + JAXXCompiler compiler) throws CompilerException { + super(id, objectClass, compiler); + tableConstraints = new GridBagConstraints(); + tableConstraints.gridx = -1; + tableConstraints.gridy = -1; + tableConstraints.insets = DEFAULT_INSETS; + } + + @Override + public void addChild(CompiledObject child, + String constraints, + JAXXCompiler compiler) throws CompilerException { + if (constraints != null) { + compiler.reportError("Table does not accept constraints"); + } + GridBagConstraints c = getCellConstraints(); + if (c == null) { + compiler.reportError("Table tag may only contain row tags"); + return; + } + if (!emptyCell) { + compiler.reportError( + "Table cells may only have one child component"); + } + while (rowSpans.size() < c.gridx + c.gridwidth) { + rowSpans.add(null); + } + for (int x = c.gridx; x < c.gridx + c.gridwidth; x++) { + rowSpans.set(x, c.gridheight); + } + + super.addChild(child, TypeManager.getJavaCode(c), compiler); + + emptyCell = false; + + compiler.addImport(GridBagConstraints.class); + compiler.addImport(Insets.class); + } + + public GridBagConstraints getTableConstraints() { + return tableConstraints; + } + + public GridBagConstraints getRowConstraints() { + return rowConstraints; + } + + public GridBagConstraints getCellConstraints() { + return cellConstraints; + } + + public void newRow() { + tableConstraints.gridy++; + tableConstraints.gridx = -1; + rowConstraints = (GridBagConstraints) tableConstraints.clone(); + + for (int x = 0; x < rowSpans.size(); x++) { + int rowSpan = rowSpans.get(x); + if (rowSpan > 0) { + rowSpans.set(x, rowSpan - 1); + } + } + } + + public void newCell() { + emptyCell = true; + rowConstraints.gridx++; + while (rowConstraints.gridx < rowSpans.size() && + rowSpans.get(rowConstraints.gridx) > 0) { + rowConstraints.gridx++; + } + cellConstraints = (GridBagConstraints) rowConstraints.clone(); + } + } + + @Override + public CompiledObject createCompiledObject(String id, + JAXXCompiler compiler) throws CompilerException { + return new CompiledTable(id, getBeanClass(), compiler); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/validator/BeanValidatorHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/validator/BeanValidatorHandler.java new file mode 100644 index 0000000..22599b2 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/validator/BeanValidatorHandler.java @@ -0,0 +1,1092 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.validator; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.beans.JAXXBeanInfo; +import org.nuiton.jaxx.compiler.beans.JAXXPropertyDescriptor; +import org.nuiton.jaxx.compiler.binding.DataBindingHelper; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.DefaultObjectHandler; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.nuiton.jaxx.validator.swing.SwingValidator; +import org.nuiton.jaxx.validator.swing.SwingValidatorUtil; +import org.nuiton.jaxx.validator.swing.ui.AbstractBeanValidatorUI; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Element; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +public class BeanValidatorHandler extends DefaultObjectHandler { + + public static final String TAG = "BeanValidator"; + + public static final String BEAN_ATTRIBUTE = "bean"; + + public static final String BEAN_CLASS_ATTRIBUTE = "beanClass"; + + public static final String BEAN_INITIALIZER_ATTRIBUTE = "beanInitializer"; + + public static final String ERROR_LIST_MODEL_ATTRIBUTE = "errorListModel"; + + public static final String ERROR_TABLE_MODEL_ATTRIBUTE = "errorTableModel"; + + public static final String ERROR_LIST_ATTRIBUTE = "errorList"; + + public static final String ERROR_TABLE_ATTRIBUTE = "errorTable"; + + public static final String ERROR_LIST_MODEL_DEFAULT = "errorListModel"; + + public static final String ERROR_TABLE_MODEL_DEFAULT = "errorTableModel"; + + public static final String ERROR_LIST_DEFAULT = "errorList"; + + public static final String ERROR_TABLE_DEFAULT = "errorTable"; + + public static final String AUTOFIELD_ATTRIBUTE = "autoField"; + + public static final String UI_CLASS_ATTRIBUTE = "uiClass"; + + public static final String STRICT_MODE_ATTRIBUTE = "strictMode"; + + public static final String CONTEXT_ATTRIBUTE = "context"; + +// /** +// * @deprecated since 2.4.1, now use the {@link #CONTEXT_ATTRIBUTE}. +// */ +// @Deprecated +// public static final String CONTEXT_NAME_ATTRIBUTE = "contextName"; + //public static final String SCOPE_ATTRIBUTE = "scope"; + + public static final String PARENT_VALIDATOR_ATTRIBUTE = "parentValidator"; + + /** Logger */ + static Log log = LogFactory.getLog(BeanValidatorHandler.class); + + protected static Map<JAXXCompiler, List<CompiledBeanValidator>> validators = + new HashMap<>(); + + protected static Map<JAXXCompiler, List<String>> validatedComponents = + new HashMap<>(); + + public BeanValidatorHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass( + getClass(), + beanClass, + SwingValidator.class + ); + } + + @Override + protected CompiledObject createCompiledObject(String id, + JAXXCompiler compiler) { + return new CompiledBeanValidator(id, getBeanClass(), compiler); + } + + @Override + protected void compileChildTagFirstPass( + Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + if (log.isDebugEnabled()) { + log.debug(tag); + } + if (!tag.getLocalName().equals(FieldValidatorHandler.TAG)) { + compiler.reportError( + "tag '" + tag.getParentNode().getLocalName() + + "' may only contain " + FieldValidatorHandler.TAG + + " as children, but found : " + tag.getLocalName()); + } else { + compiler.compileFirstPass(tag); + } + } + + @Override + public void compileSecondPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + + super.compileSecondPass(tag, compiler); + + CompiledBeanValidator info = (CompiledBeanValidator) objectMap.get(tag); + + boolean error = info.addErrorListModel(tag, this, compiler); + + if (!error) { + error = info.addErrorList(tag, compiler); + } + + if (!error) { + error = info.addErrorTableModel(tag, this, compiler); + } + + if (!error) { + error = info.addErrorTable(tag, compiler); + } + + if (!error) { + error = info.addUiClass(this, compiler); + } + + if (!error) { + error = info.addBean(tag, this, compiler); + } + + if (!error) { + error = info.addParentValidator(tag, this, compiler); + } + + if (error) { + log.warn("error were detected in second compile pass " + + "of CompiledObject [" + info + "]"); + } + + // close the compiled object + compiler.closeComponent(info); + } + + @Override + protected void setDefaults(CompiledObject object, + Element tag, + JAXXCompiler compiler) { + // open the compiled object + compiler.openInvisibleComponent(object); + } + + @Override + public void setAttribute(CompiledObject object, + String propertyName, + String stringValue, + boolean inline, + JAXXCompiler compiler) { + if (log.isDebugEnabled()) { + log.debug(propertyName + " : " + stringValue + " for " + object); + } +// if (CONTEXT_ATTRIBUTE.equals(propertyName)) { +// if (stringValue != null && !stringValue.trim().isEmpty()) { +// // usage of a deprecated contextName, says it to user... +// compiler.reportWarning("You are using a validator attribute named 'contextName' which is deprecated, prefer use now a context attribute."); +// } +// } + // delegate to the compiled object with is statefull + // (but not the tag handler) + object.addProperty(propertyName, stringValue); + } + + /** + * The compiled objet representing a BeanValidator to be generated in + * JAXXObject + * + * @author Tony Chemit - chemit@codelutin.com + */ + public static class CompiledBeanValidator extends CompiledObject { + + /** + * Map of field to add into validator. + * + * Keys are editors, Values are bean properties. + */ + protected Multimap<String, String> fields; + + /** + * Map of field to exclude. + * + * Keys are bean properties, Values are editors. + */ + protected Map<String, String> excludeFields; + + protected String bean; + + protected String beanClass; + + protected String context; + + protected String uiClass; + + protected String errorListModel; + + protected String errorList; + + protected Boolean autoField; + + protected Boolean strictMode; + + protected JAXXBeanInfo beanDescriptor; + + protected String errorTableModel; + + protected String errorTable; + + protected String parentValidator; + + public CompiledBeanValidator(String id, + ClassDescriptor objectClass, + JAXXCompiler compiler) { + //TC-20090524 Use the real class descriptor, not the one by default, + //TC-20090524 otherwise can not override the validator class while generation + //super(id, objectClass, compiler); + super(id, getDescriptor(objectClass, compiler), compiler); + fields = ArrayListMultimap.create(); + excludeFields = new TreeMap<>(); + if (log.isDebugEnabled()) { + log.debug("validator objectClass " + getObjectClass()); + } + } + + protected static ClassDescriptor getDescriptor( + ClassDescriptor objectClass, + JAXXCompiler compiler) { + Class<?> validatorClass = SwingValidator.class; +// compiler.getConfiguration().getValidatorClass(); + return ClassDescriptorHelper.getClassDescriptor(validatorClass); + } + + public Multimap<String, String> getFields() { + return fields; + } + + public boolean containsFieldEditor(String editorName) { + return fields.containsKey(editorName); + } + + public boolean containsFieldPropertyName(String propertyName) { + return fields.containsValue(propertyName); + } + + public Set<String> getFieldEditors() { + return fields.keySet(); + } + +// public Set<String> getFieldIds() { +// return fields.values(); +// } + + public boolean containsExcludeFieldEditor(String editorName) { + return excludeFields.containsValue(editorName); + } + + protected boolean containsExcludeFieldPropertyName(String editorName) { + return excludeFields.containsKey(editorName); + } + +// public Map<String, String> getExcludeFields() { +// return excludeFields; +// } + +// public Set<String> getExcludeFieldEditors() { +// return new HashSet<String>(excludeFields.values()); +// } + + public Set<String> getExcludeFieldPropertyNames() { + return excludeFields.keySet(); + } + + protected void removeFieldPropertyName(String propertyName) { + //must find the editor for this property + for (String editor : fields.keySet()) { + if (fields.containsEntry(editor, propertyName)) { + + fields.remove(editor, propertyName); + break; + } + } + } + + public void addField(String propertyName, String editor) { + fields.put(editor, propertyName); + } + + public void addExcludeField(String propertyName, String editor) { + excludeFields.put(propertyName, editor); + } + + public Collection<String> getFieldPropertyNames(String editor) { + return fields.get(editor); + } + +// public void setFields(Map<String, String> fields) { +// this.fields = fields; +// } + +// public void setExcludeFields(Map<String, String> excludeFields) { +// this.excludeFields = excludeFields; +// } + + @Override + public void addProperty(String property, String value) { + + if (BEAN_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + bean = value.trim(); + } + return; + } + +// if (CONTEXT_NAME_ATTRIBUTE.equals(property)) { +// if (value != null && !value.trim().isEmpty()) { +// context= value.trim(); +// } +// +// return; +// } + + if (CONTEXT_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + context = value.trim(); + } + return; + } + + if (BEAN_CLASS_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + beanClass = value.trim(); + } + return; + } + + if (ERROR_LIST_MODEL_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + errorListModel = value.trim(); + } + return; + } + + if (ERROR_LIST_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + errorList = value.trim(); + } + return; + } + + if (ERROR_TABLE_MODEL_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + errorTableModel = value.trim(); + } + return; + } + + if (ERROR_TABLE_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + errorTable = value.trim(); + } + return; + } + + if (UI_CLASS_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + uiClass = value.trim(); + } + return; + } + + if (AUTOFIELD_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + autoField = (Boolean) TypeManager.convertFromString( + value.trim(), + Boolean.class + ); + } + return; + } + + if (STRICT_MODE_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + strictMode = (Boolean) TypeManager.convertFromString( + value.trim(), + Boolean.class + ); + } + return; + } + + if (PARENT_VALIDATOR_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + parentValidator = value.trim(); + } + return; + } + + throw new CompilerException("property " + property + + " is not allowed on object " + this); + } + + public String getBean() { + return bean; + } + + public String getErrorListModel() { + return errorListModel; + } + + public boolean getAutoField() { + return autoField != null && autoField; + } + + public boolean getStrictMode() { + return strictMode != null && strictMode; + } + + public String getUiClass() { + return uiClass; + } + + public String getBeanClass() { + return beanClass; + } + + public String getContext() { + return context; + } + + public String getParentValidator() { + return parentValidator; + } + + public JAXXBeanInfo getBeanDescriptor(JAXXCompiler compiler) { + if (beanDescriptor == null && foundBean()) { + +// String beanClassName = null; + try { + //TC-20090111 beanClass is mandatory + // get the real bean class name (from bean or beanClass) + /*if (beanClass != null) { + beanClassName = beanClass; + } else { + beanClassName = compiler.getSymbolTable().getClassTagIds().get(bean); + if (beanClassName == null) { + compiler.reportError("could not find class of the bean '" + bean + "'"); + return null; + } + }*/ + ClassDescriptor beanClassDescriptor = + ClassDescriptorHelper.getClassDescriptor(beanClass); + beanDescriptor = DefaultObjectHandler.getJAXXBeanInfo( + beanClassDescriptor); + + } catch (Exception e) { + compiler.reportError( + "could not load class " + beanClass); + } + } + return beanDescriptor; + } + + @Override + public void addChild(CompiledObject child, + String constraints, + JAXXCompiler compiler) throws CompilerException { + // do nothing + compiler.reportError("can not add CompiledObject in the tag '" + + TAG + " (only field tags)"); + } + + public boolean foundBean() { + return !(beanClass == null || beanClass.isEmpty()); + } + + protected boolean addUiClass(BeanValidatorHandler handler, + JAXXCompiler compiler) { + boolean withError = false; + if (uiClass == null && + compiler.getConfiguration().getDefaultErrorUI() != null) { + uiClass = compiler.getConfiguration().getDefaultErrorUI().getName(); + } + if (uiClass != null) { + try { + ClassDescriptor uiClazz = + ClassDescriptorHelper.getClassDescriptor(uiClass); + if (!ClassDescriptorHelper.getClassDescriptor(AbstractBeanValidatorUI.class).isAssignableFrom(uiClazz)) { + compiler.reportError( + "attribute 'ui' :'" + uiClass + + "' is not assignable from class " + + AbstractBeanValidatorUI.class + ); + withError = true; + } else { + String prefix = compiler.getImportedType(uiClazz.getName()); + String code = handler.getSetPropertyCode( + getJavaCode(), + UI_CLASS_ATTRIBUTE, + prefix + ".class", + compiler + ); + appendAdditionCode(code); + } + } catch (ClassNotFoundException e) { + compiler.reportError("class not found '" + uiClass + "'"); + withError = true; + } + } + + return withError; + } + + protected boolean addErrorListModel(Element tag, + BeanValidatorHandler handler, + JAXXCompiler compiler) { + if (errorListModel == null) { + // try with the default "errors" + if (!compiler.checkReference( + tag, + ERROR_LIST_MODEL_DEFAULT, + false, + ERROR_LIST_MODEL_ATTRIBUTE)) { + return false; + } + errorListModel = ERROR_LIST_MODEL_DEFAULT; + } else { + if (errorListModel.startsWith("{") && + errorListModel.endsWith("}")) { + // this is a script, no check here + errorListModel = errorListModel.substring( + 1, + errorListModel.length() - 1).trim(); + } else if (!compiler.checkReference( + tag, + errorListModel, + true, + ERROR_LIST_MODEL_ATTRIBUTE)) { + // errorListModel is not defined + return true; + } + } + + String code = handler.getSetPropertyCode( + getJavaCode(), + ERROR_LIST_MODEL_ATTRIBUTE, + errorListModel, + compiler + ); + appendAdditionCode(code); + + return false; + } + + protected boolean addErrorTableModel(Element tag, + BeanValidatorHandler handler, + JAXXCompiler compiler) { + if (errorTableModel == null) { + // try with the default "errors" + if (!compiler.checkReference( + tag, + ERROR_TABLE_MODEL_DEFAULT, + false, + ERROR_LIST_MODEL_ATTRIBUTE)) { + return false; + } + errorTableModel = ERROR_TABLE_MODEL_DEFAULT; + } else { + if (errorTableModel.startsWith("{") && + errorTableModel.endsWith("}")) { + // this is a script, no check here + errorTableModel = errorTableModel.substring( + 1, errorTableModel.length() - 1).trim(); + } else if (!compiler.checkReference( + tag, + errorTableModel, + true, + ERROR_TABLE_MODEL_ATTRIBUTE)) { + // errorListModel is not defined + return true; + } + } + + String code = handler.getSetPropertyCode( + getJavaCode(), + ERROR_TABLE_MODEL_ATTRIBUTE, + errorTableModel, + compiler + ); + appendAdditionCode(code); + + return false; + + } + + protected boolean addParentValidator(Element tag, + BeanValidatorHandler handler, + JAXXCompiler compiler) { + if (parentValidator != null) { + String initializer; + if (parentValidator.startsWith("{") && + parentValidator.endsWith("}")) { + + // todo : should be able to bind + initializer = parentValidator.substring( + 1, + parentValidator.length() - 1 + ); + + } else { + // the attribute referes an existing widget + if (!compiler.checkReference( + tag, + parentValidator, + true, + PARENT_VALIDATOR_ATTRIBUTE)) { + // parentValidator is not defined + return true; + } + initializer = parentValidator; + } + String code = handler.getSetPropertyCode( + getJavaCode(), + PARENT_VALIDATOR_ATTRIBUTE, + initializer, + compiler + ); + appendAdditionCode(code); + } + return false; + } + + protected boolean addErrorList(Element tag, JAXXCompiler compiler) { + + if (errorList == null) { + // try with the default "errorList" + if (!compiler.checkReference( + tag, + ERROR_LIST_DEFAULT, + false, + ERROR_LIST_ATTRIBUTE)) { + return false; + } + errorList = ERROR_LIST_DEFAULT; + } else { + if (!compiler.checkReference( + tag, + errorList, + true, + ERROR_LIST_ATTRIBUTE)) { + return true; + } + } + + String prefix = compiler.getImportedType(SwingValidatorUtil.class); + + String code = prefix + + ".registerErrorListMouseListener(" + errorList + ");"; + appendAdditionCode(code); + + return false; + } + + protected boolean addErrorTable(Element tag, JAXXCompiler compiler) { + + if (errorTable == null) { + // try with the default "errorList" + if (!compiler.checkReference(tag, + ERROR_TABLE_DEFAULT, + false, + ERROR_TABLE_ATTRIBUTE)) { + return false; + } + errorTable = ERROR_TABLE_DEFAULT; + } else { + if (!compiler.checkReference(tag, + errorTable, + true, + ERROR_TABLE_ATTRIBUTE)) { + return true; + } + } + + String prefix = compiler.getImportedType(SwingValidatorUtil.class); + + String code = prefix + + ".registerErrorTableMouseListener(" + errorTable + + ");"; + appendAdditionCode(code); + + return false; + } + + protected boolean addBean(Element tag, + BeanValidatorHandler handler, + JAXXCompiler compiler) { + + if (beanClass == null || beanClass.isEmpty()) { + // try to guest beanClass from bean attribute + if (bean != null && !bean.isEmpty()) { + beanClass = compiler.getSymbolTable().getClassTagIds().get(bean); + if (beanClass == null) { + compiler.reportError( + "could not find class of the bean '" + bean + + "', and no beanClass was setted"); + return true; + } + } + } + if (beanClass == null) { + compiler.reportError( + "tag '" + tag + "' requires a 'beanClass' attribute, " + + "and could not guest it from 'bean' attribute " + + "(no bean attribute setted...)"); + return true; + } + + JAXXBeanInfo beanInfo = getBeanDescriptor(compiler); + if (beanInfo == null) { + compiler.reportError( + tag, + "could not find descriptor of class " + beanClass + ); + return true; + } + + String beanInitializer = null; + if (bean != null) { + + if (bean.startsWith("{") && bean.endsWith("}")) { + + String labelBinding = + DataBindingHelper.processDataBindings(bean); + if (labelBinding != null) { + compiler.getBindingHelper().registerDataBinding( + getId() + ".bean", + labelBinding, + getId() + ".setBean(" + labelBinding + ");" + ); + } +// // just has an intializer +// beanInitializer = bean.substring(1, bean.length() - 1); +// // this is not a real bean, so delete it + bean = null; + } else { + + if (!compiler.checkReference(tag, + bean, + true, + BEAN_ATTRIBUTE)) { + // could not find bean in compiled object + return true; + } + + if (isBeanUsedByValidator(compiler, bean)) { + compiler.reportError( + "the bean '" + bean + "' is already used in " + + "another the validator, can not used it in '" + + tag + "'" + ); + return true; + } + + /*if (beanInitializer != null) { + compiler.reportWarning("tag '" + tag + "' found a 'bean' and a 'beanInitializer' attributes, 'beanInitializer' is skipped"); + }*/ + beanInitializer = bean; + } + } + + if (beanInitializer != null) { + String code = handler.getSetPropertyCode( + getJavaCode(), + BEAN_ATTRIBUTE, + compiler.checkJavaCode(beanInitializer), + compiler + ); + appendAdditionCode(code); + } + + String beanClassName = beanInfo.getJAXXBeanDescriptor().getClassDescriptor().getName(); + String type = compiler.getImportedType(beanClassName); + // contextName must be in constructor to able to init validator with his correct contextName + String constructorParams = type + ".class, " + + TypeManager.getJavaCode(context); +// setConstructorParams(constructorParams); + String validatorFactoryFqn = + compiler.getConfiguration().getValidatorFactoryFQN(); + + String prefix = compiler.getImportedType(validatorFactoryFqn); + setInitializer( + prefix + ".newValidator(" + constructorParams + ")" + ); + + // add generic type to validator + setGenericTypes(beanClassName); + + if (getAutoField()) { + registerAutoFieldBean(tag, compiler, beanInfo); + } + + if (getBeanDescriptor(compiler) != null) { + + // add fieldrepresentation invocations +// addFieldRepresentations(tag, compiler); + + // register the validator in compiler + registerValidator(compiler, this); + + } + + return false; + } + + private void registerValidator( + JAXXCompiler compiler, + CompiledBeanValidator compiledBeanValidator) { + List<CompiledBeanValidator> vals = validators.get(compiler); + if (vals == null) { + vals = new ArrayList<>(); + validators.put(compiler, vals); + } + vals.add(compiledBeanValidator); + List<String> ids = validatedComponents.get(compiler); + if (ids == null) { + ids = new ArrayList<>(); + validatedComponents.put(compiler, ids); + } +// ids.addAll(compiledBeanValidator.getFields().values()); + ids.addAll(compiledBeanValidator.getFieldEditors()); + } + +// /** +// * Register in buffer all field representation to init (and to record in method {@link JAXXValidator#registerValidatorFields()} +// * +// * @param compiler the compiler used +// * @param javaFile generated file +// * @param buffer the buffer where to add code +// * @since 2.2.1 +// */ +// public void addFieldRepresentations(JAXXCompiler compiler, +// JavaFile javaFile, +// StringBuilder buffer) { +// for (String component : fields.keySet()) { +//// String component = entry.getKey(); +// Collection<String> propertyNames = fields.get(component); +// List<String> keyCodes = +// Lists.newArrayListWithCapacity(propertyNames.size()); +// for (String propertyName : propertyNames) { +// if (!checkBeanProperty(compiler, propertyName)) { +// // property not find on bean +// continue; +// } +// String keyCode = TypeManager.getJavaCode(propertyName); +// keyCodes.add(keyCode); +// } +// +// if (keyCodes.isEmpty()) { +// // no property +// continue; +// } +// String keyCode = Joiner.on(", ").join(keyCodes); +// if (keyCodes.size()>1) { +// keyCode = "{ " + keyCode+" }"; +// } +//// String propertyName = entry.getKey(); +// +// String validatorId = TypeManager.getJavaCode(getId()); +// +// String editorCode = TypeManager.getJavaCode(component); +// JavaField editor = javaFile.getField(component); +// String annotation = ValidatorField.class.getSimpleName() + +// "( validatorId = " + validatorId + "," + +// " propertyName = " + keyCode + "," + +// " editorName = " + editorCode + "" + +// ")"; +// editor.addAnnotation(annotation); +// +//// if (!compiler.checkReference(tag, component, true, null)) { +//// // editor component not find on ui +//// continue; +//// } +// +//// buffer.append(getJavaCode()); +//// buffer.append(".setFieldRepresentation("); +//// buffer.append(keyCode); +//// buffer.append(", "); +//// buffer.append(component); +//// buffer.append(");\n"); +// } +// } + + protected void registerAutoFieldBean(Element tag, + JAXXCompiler compiler, + JAXXBeanInfo beanInfo) { + for (JAXXPropertyDescriptor beanProperty : + beanInfo.getJAXXPropertyDescriptors()) { + String descriptionName = beanProperty.getName(); + if (log.isDebugEnabled()) { + log.debug("try to bind on bean " + + beanInfo.getJAXXBeanDescriptor().getName() + + " property " + descriptionName); + } + if (beanProperty.getWriteMethodDescriptor() == null) { + // read-only property + continue; + } +// if (fields.containsKey(descriptionName)) { + if (containsFieldPropertyName(descriptionName)) { + // already defined in field + continue; + } +// if (excludeFields.containsKey(descriptionName)) { + if (containsExcludeFieldPropertyName(descriptionName)) { + // exclude field + continue; + } + if (!compiler.checkReference(tag, + descriptionName, + getStrictMode(), + null)) { + // no editor component found + continue; + } + // ok add the field mapping + registerField(descriptionName, descriptionName, compiler); + } + +// for (Entry<String, String> entry : excludeFields.entrySet()) { + for (String key : getExcludeFieldPropertyNames()) { +// String key = entry.getKey(); +// if (fields.containsKey(key)) { + if (containsFieldPropertyName(key)) { + compiler.reportWarning( + "field '" + key + "' can not be used and " + + "excluded at same time ! (field is skipped) " + + "for validator " + this + ); +// fields.remove(key); + removeFieldPropertyName(key); + } + } + } + + public void registerField(String id, + String component, + JAXXCompiler compiler) { +// if (fields.containsKey(id)) { + if (containsFieldPropertyName(id)) { + compiler.reportError( + "duplicate field '" + id + "' for validator " + this); + } else { + if (log.isDebugEnabled()) { + log.debug("add field <" + id + ":" + component + ">"); + } +// fields.put(id, component); + addField(id, component); + + } + } + + public void registerExcludeField(String id, + String component, + JAXXCompiler compiler) { +// if (excludeFields.containsKey(id)) { + if (containsExcludeFieldPropertyName(id)) { + compiler.reportError( + "duplicate field '" + id + "' for validator " + this); + } else { + if (log.isDebugEnabled()) { + log.debug("add excludeField <" + id + ":" + component + ">"); + } +// excludeFields.put(id, component); + addExcludeField(id, component); + } + } + + public boolean checkBeanProperty(JAXXCompiler compiler, + String propertyName) { + + for (JAXXPropertyDescriptor beanProperty : + getBeanDescriptor(compiler).getJAXXPropertyDescriptors()) { + if (beanProperty.getName().equals(propertyName)) { + if (beanProperty.getWriteMethodDescriptor() == null) { + // read-onlyproperty + compiler.reportError( + "could not bind the readonly property '" + + propertyName + "' on bean [" + getBean() + "] "); + return false; + } + return true; + } + } + compiler.reportError( + "could not find the property '" + propertyName + + "' on bean [" + getBean() + "] "); + return false; + } + } + + /** + * Test if a given bean is attached to a validator. + * + * @param compiler current compiler to use + * @param beanId the bean to test + * @return <code>true</code> if the given bean is attached to a validator, + * <code>false</code> otherwise + */ + public static boolean isBeanUsedByValidator(JAXXCompiler compiler, + String beanId) { + List<CompiledBeanValidator> beanValidatorList = validators.get(compiler); + if (beanValidatorList != null) { + for (CompiledBeanValidator validator : beanValidatorList) { + if (beanId.equals(validator.getBean())) { + return true; + } + } + } + return false; + } + + /** + * @param compiler compiler to use + * @return <code>true</code> if some validators were detected, + * <code>false</code> otherwise + */ + public static boolean hasValidator(JAXXCompiler compiler) { + List<CompiledBeanValidator> beanValidatorList = + validators.get(compiler); + return beanValidatorList != null && !beanValidatorList.isEmpty(); + } + + /** + * Test if a given CompiledObject is attached to a validator. + * + * @param compiler compiler to use + * @param componentId the compiled object to test + * @return <code>true</code> if the given compiled object is attached to + * a validator, <code>false</code> otherwise + */ + public static boolean isComponentUsedByValidator(JAXXCompiler compiler, + String componentId) { + List<String> ids = validatedComponents.get(compiler); + return ids != null && ids.contains(componentId); + } + + public static List<CompiledBeanValidator> getValidators(JAXXCompiler compiler) { + return validators.get(compiler); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/validator/ExcludeFieldValidatorHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/validator/ExcludeFieldValidatorHandler.java new file mode 100644 index 0000000..a5becfb --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/validator/ExcludeFieldValidatorHandler.java @@ -0,0 +1,127 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.validator; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.TagHandler; +import org.nuiton.jaxx.compiler.tags.validator.BeanValidatorHandler.CompiledBeanValidator; +import org.nuiton.jaxx.validator.swing.SwingValidator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Element; + +import java.io.IOException; + +public class ExcludeFieldValidatorHandler implements TagHandler { + + public static final String TAG = "excludeField"; + + public static final String NAME_ATTRIBUTE = "name"; + + public static final String COMPONENT_ATTRIBUTE = "component"; + + /** Logger */ + static private Log log = LogFactory.getLog(ExcludeFieldValidatorHandler.class); + + @Override + public void compileFirstPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + if (compiler.getConfiguration().isVerbose()) { + log.info(tag); + } + //todo check there is no child + } + + @Override + public void compileSecondPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + if (compiler.getConfiguration().isVerbose()) { + log.debug(tag); + } + + ClassDescriptor descriptor = + ClassDescriptorHelper.getClassDescriptor(SwingValidator.class); + if (!descriptor.isAssignableFrom( + compiler.getOpenComponent().getObjectClass())) { + compiler.reportError(TAG + " tag may only appear within " + + BeanValidatorHandler.TAG + " tag but was " + + tag); + return; + } + + CompiledBeanValidator info = + (CompiledBeanValidator) compiler.getOpenComponent(); + if (!info.getAutoField()) { + compiler.reportError(TAG + " tag can not be used without an " + + "'autoField' validator : " + tag); + return; + } + String name = tag.getAttribute(NAME_ATTRIBUTE); + String component = tag.getAttribute(COMPONENT_ATTRIBUTE); + if (name == null || name.trim().isEmpty()) { + compiler.reportError(TAG + " tag requires a " + NAME_ATTRIBUTE + + " attribute"); + return; + } + name = name.trim(); + if (component == null || component.trim().isEmpty()) { + // try to use the name as component + if (!compiler.checkReference(tag, name, false, name)) { + compiler.reportError(TAG + " tag requires a " + + COMPONENT_ATTRIBUTE + " attribute, try " + + "to use the name attribute [" + name + + "] for the component, but no such " + + "component found"); + return; + } + component = name; + } + component = component.trim(); + + // check component is not already used by this compiled object +// if (info.getFields().containsValue(component)) { + if (info.containsFieldEditor(component)) { + compiler.reportError(TAG + " tag found a attribute " + + COMPONENT_ATTRIBUTE + " [" + component + + "] already used in this validator"); + return; + } +// if (info.getExcludeFields().containsValue(component)) { + if (info.containsExcludeFieldEditor(component)) { + compiler.reportError(TAG + " tag found a attribute " + + COMPONENT_ATTRIBUTE + " [" + component + + "] already used in this validator"); + return; + } + // check component exist (again perharps, but let the error knows exactly which tag failed...) + if (compiler.checkReference(tag, component, true, COMPONENT_ATTRIBUTE)) { + // add a field + info.registerField(name, component, compiler); + } + + + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/validator/FieldValidatorHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/validator/FieldValidatorHandler.java new file mode 100644 index 0000000..3960847 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tags/validator/FieldValidatorHandler.java @@ -0,0 +1,153 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags.validator; + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.binding.DataBindingHelper; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tags.TagHandler; +import org.nuiton.jaxx.compiler.tags.validator.BeanValidatorHandler.CompiledBeanValidator; +import org.nuiton.jaxx.validator.swing.SwingValidator; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Element; + +import java.io.IOException; + +public class FieldValidatorHandler implements TagHandler { + + public static final String TAG = "field"; + + public static final String NAME_ATTRIBUTE = "name"; + + public static final String COMPONENT_ATTRIBUTE = "component"; + + /** Logger */ + static private Log log = LogFactory.getLog(FieldValidatorHandler.class); + + public void compileFirstPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + if (compiler.getConfiguration().isVerbose()) { + log.debug(tag); + } + //todo check there is no child + } + + @Override + public void compileSecondPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + if (compiler.getConfiguration().isVerbose()) { + log.debug(tag); + } + + ClassDescriptor descriptor = + ClassDescriptorHelper.getClassDescriptor(SwingValidator.class); + if (!descriptor.isAssignableFrom( + compiler.getOpenComponent().getObjectClass())) { + compiler.reportError( + TAG + " tag may only appear within " + + BeanValidatorHandler.TAG + " tag but was " + tag); + return; + } + + CompiledBeanValidator info = + (CompiledBeanValidator) compiler.getOpenComponent(); + + String name = tag.getAttribute(NAME_ATTRIBUTE); + if (StringUtils.isEmpty(name)) { + compiler.reportError(TAG + " tag requires a " + NAME_ATTRIBUTE + + " attribute"); + return; + } + name = name.trim(); + + String component = tag.getAttribute(COMPONENT_ATTRIBUTE); + if (StringUtils.isEmpty(component)) { + // try to use the name as component + if (!compiler.checkReference(tag, name, false, name)) { + compiler.reportError( + TAG + " tag requires a " + COMPONENT_ATTRIBUTE + + " attribute, try to use the name attribute [" + name + + "] for the component, but no such component found"); + return; + } + component = name; + } + component = component.trim(); + + boolean complexType = false; + if (component.startsWith("{") && component.endsWith("}")) { + + complexType = true; + + // means a complex reference (says a java Code in facts) + component = compiler.preprocessScript( + component.substring(1, component.length() - 1)); + } + + if (log.isDebugEnabled()) { + log.debug("Check '" + component + "' reference"); + } + + // check component is not already used by this compiled object +// if (info.getFields().containsValue(component)) { +// if (info.containsFieldEditor(component)) { +// compiler.reportError( +// TAG + " tag found a attribute " + COMPONENT_ATTRIBUTE + +// " [" + component + "] already used in this validator"); +// return; +// } + + if (complexType) { + String binding = DataBindingHelper.processDataBindings(component); + boolean withBinding = binding != null; + + if (log.isDebugEnabled()) { + log.debug("apply data binding on [" + component + "] : " + withBinding); + } + + // this means reference is ok, can safely add field + + // add a field + info.registerField(name, component, compiler); + return; + } + + // simple reference, check it directly on compiler + + // check component exist (again perharps, but let the error knows + // exactly which tag failed...) + if (compiler.checkReference(tag, + component, + true, + COMPONENT_ATTRIBUTE)) { + // add a field + info.registerField(name, component, compiler); + } + + + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/CompileFirstPassTask.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/CompileFirstPassTask.java new file mode 100644 index 0000000..2bf96d8 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/CompileFirstPassTask.java @@ -0,0 +1,127 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.tasks; + +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXCompilerFile; +import org.nuiton.jaxx.compiler.JAXXEngine; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.File; + +/** + * First compile pass task to validate jaxx files and look after dependencies. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class CompileFirstPassTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(CompileFirstPassTask.class); + + /** Task name */ + public static final String TASK_NAME = "CompileFirstPass"; + + public CompileFirstPassTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + boolean success = true; + + JAXXCompilerFile[] undone = engine.getFilesToCompile(); + + while (undone.length > 0) { + + // start a new round of compilation + + for (JAXXCompilerFile jaxxFile : undone) { + + boolean successForFile = treatFile(engine, jaxxFile); + + if (!successForFile) { + + // something is wrong... + success = false; + } + } + + // prepare next round + undone = engine.getFilesToCompile(); + } + return success; + } + + protected boolean treatFile(JAXXEngine engine, + JAXXCompilerFile jaxxFile) throws Exception { + + boolean isVerbose = engine.isVerbose(); + + if (isVerbose) { + log.info("start " + jaxxFile.getClassName()); + } + + boolean success = true; + + JAXXCompiler compiler = engine.newCompiler(jaxxFile); + addStartProfileTime(engine, compiler); + + compiler.compileFirstPass(); + + if (!compiler.isIdentCssFound()) { + + // check if we can add ident css file + + File cssFile = jaxxFile.getCssFile(); + + if (log.isDebugEnabled()) { + log.debug("test ident css file " + cssFile + " : " + isVerbose); + } + if (cssFile.exists()) { + + if (isVerbose) { + log.info("Auto import of css " + cssFile); + } + // ok add it + compiler.registerStyleSheetFile(cssFile, false); + } + } + + File commonCss = engine.getConfiguration().getCommonCss(); + if (commonCss != null) { + if (isVerbose) { + log.info("Import global css: " + commonCss); + } + compiler.registerStyleSheetFile(commonCss, false); + } + + addEndProfileTime(engine, compiler); + + if (compiler.isFailed()) { + success = false; + } + return success; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/CompileSecondPassTask.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/CompileSecondPassTask.java new file mode 100644 index 0000000..441a056 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/CompileSecondPassTask.java @@ -0,0 +1,92 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.tasks; + +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXCompilerFile; +import org.nuiton.jaxx.compiler.JAXXEngine; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Task to execute the Second round of compile. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class CompileSecondPassTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = + LogFactory.getLog(CompileSecondPassTask.class); + + /** Task name */ + public static final String TASK_NAME = "CompileSecondPass"; + + public CompileSecondPassTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + boolean success = true; + boolean isVerbose = engine.isVerbose(); + + // check all files are attached to a compiler + checkAllFilesCompiled(engine); + + JAXXCompilerFile[] files = engine.getCompiledFiles(); + + for (JAXXCompilerFile jaxxFile : files) { + + String className = jaxxFile.getClassName(); + if (isVerbose) { + log.info("start " + className); + } + + JAXXCompiler compiler = jaxxFile.getCompiler(); + + addStartProfileTime(engine, compiler); + if (log.isDebugEnabled()) { + log.debug("runInitializers for " + className); + } + if (!compiler.isFailed()) { + compiler.runInitializers(); + } + if (log.isDebugEnabled()) { + log.debug("compile second pass for " + className); + } + compiler.compileSecondPass(); + addEndProfileTime(engine, compiler); + if (log.isDebugEnabled()) { + log.debug("done with result [" + !compiler.isFailed() + + "] for " + className); + } + if (compiler.isFailed()) { + success = false; + } + } + + return success; + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/FinalizeTask.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/FinalizeTask.java new file mode 100644 index 0000000..8c4c508 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/FinalizeTask.java @@ -0,0 +1,75 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.tasks; + +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXCompilerFile; +import org.nuiton.jaxx.compiler.JAXXEngine; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Task to execute after stylesheet tasks and juste before generation task. + * + * This task will finialize all compilers. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class FinalizeTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(FinalizeTask.class); + + /** Task name */ + public static final String TASK_NAME = "Finalize"; + + public FinalizeTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + boolean success = true; + boolean isVerbose = engine.getConfiguration().isVerbose(); + + // check all files are attached to a compiler + checkAllFilesCompiled(engine); + + JAXXCompilerFile[] files = engine.getCompiledFiles(); + + for (JAXXCompilerFile jaxxFile : files) { + + if (isVerbose) { + log.info("start " + jaxxFile.getClassName()); + } + JAXXCompiler compiler = jaxxFile.getCompiler(); + addStartProfileTime(engine, compiler); + compiler.finalizeCompiler(); + addEndProfileTime(engine, compiler); + if (compiler.isFailed()) { + success = false; + } + } + return success; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/GenerateConstructorsTask.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/GenerateConstructorsTask.java new file mode 100644 index 0000000..db9e88a --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/GenerateConstructorsTask.java @@ -0,0 +1,508 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.tasks; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXCompilerFile; +import org.nuiton.jaxx.compiler.JAXXEngine; +import org.nuiton.jaxx.compiler.finalizers.DefaultFinalizer; +import org.nuiton.jaxx.compiler.java.JavaArgument; +import org.nuiton.jaxx.compiler.java.JavaConstructor; +import org.nuiton.jaxx.compiler.java.JavaElementFactory; +import org.nuiton.jaxx.compiler.java.JavaFile; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; +import org.nuiton.jaxx.compiler.tags.TagManager; +import org.nuiton.jaxx.runtime.JAXXContext; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import static java.lang.reflect.Modifier.PUBLIC; + +/** + * Task to execute just after finalize task to create all constructors for any + * compiler. + * + * In fact, we can not compute constructor in one time since some compiler may + * need of the constructors of previous compiler... + * + * This task will compute all constructors to generate. + * + * @author Tony Chemit - chemit@codelutin.com + * @see JavaConstructor + * @since 2.4 + */ +public class GenerateConstructorsTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(GenerateConstructorsTask.class); + + /** Task name */ + public static final String TASK_NAME = "PostFinalize"; + + private static final String PARAMETER_NAME_PARENT_CONTEXT = "parentContext"; + + public GenerateConstructorsTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + boolean success = true; + boolean isVerbose = engine.getConfiguration().isVerbose(); + + JAXXCompilerFile[] files = engine.getCompiledFiles(); + + // to contains all compilers + List<JAXXCompiler> compilers = new ArrayList<>(); + for (JAXXCompilerFile jaxxFile : files) { + compilers.add(jaxxFile.getCompiler()); + } + + int round = 0; + + while (!compilers.isEmpty()) { + + if (isVerbose) { + log.info("Round " + round++ + ", still " + + compilers.size() + " compilers to treat."); + } + + // launch a round since there is still some compiler to treat + Iterator<JAXXCompiler> itr = compilers.iterator(); + while (itr.hasNext()) { + JAXXCompiler compiler = itr.next(); + JavaFile javaFile = compiler.getJavaFile(); + + boolean isJAXXObject = javaFile.isSuperclassIsJAXXObject(); + if (!isJAXXObject) { + + // can directly compute constructors + + if (log.isDebugEnabled()) { + log.debug("Compute constructor from non super " + + "jaxx object file " + javaFile.getName()); + } + + // get the constructors of the parent class + + addConstructorsForNoneSuperClassJaxx(engine, compiler); + itr.remove(); + continue; + } + + // compiler inheritate from a jaxx object + CompiledObject rootObject = compiler.getRootObject(); + ClassDescriptor parentClassDescriptor = rootObject.getObjectClass(); + + if (parentClassDescriptor.getResolverType() + != ClassDescriptorHelper.ResolverType.JAXX_FILE) { + + // the parent was not generated by this engine; we can safely + // use it + + if (log.isDebugEnabled()) { + log.debug("Compute constructor from outside super " + + "jaxx object file " + javaFile.getName()); + } + addConstructorsForSuperClassJaxx(engine, compiler, null); + itr.remove(); + continue; + + } + + JAXXCompiler parentCompiler = engine.getJAXXCompiler( + JAXXCompiler.getCanonicalName(parentClassDescriptor)); + + + if (!compilers.contains(parentCompiler)) { + + // parent was generated by this engine and was laready + // treated, can now safely deal this the given compiler + + if (log.isDebugEnabled()) { + log.debug("Compute constructor from inside super " + + "jaxx object file " + javaFile.getName()); + } + + addConstructorsForSuperClassJaxx(engine, compiler, parentCompiler); + itr.remove(); + continue; + } + + // can not treate at the moment... + if (log.isDebugEnabled()) { + log.debug("Can not compute constructors for " + + compiler.getRootObject().getId() + + " waits fro his parent to be treated..."); + } + } + } + return success; + } + + /** + * To add constructor on the given {@code compiler}, knowing that the super + * class of it is not a jaxx class. + * + * In this mode, we takes all the constructors of the parent (if parent has + * some!) and for each of them add the simple one and another one with + * first parameter a {@link JAXXContext}. + * + * @param engine the current engine which compiled compiler + * @param compiler the current compiler to treat + * @throws ClassNotFoundException if a class could not be found (when wanted to have extact type for constructor parameters) + * @throws IllegalStateException if given {@code compiler has a super JAXX class}. + */ + protected void addConstructorsForNoneSuperClassJaxx(JAXXEngine engine, + JAXXCompiler compiler) throws ClassNotFoundException, IllegalStateException { + + JavaFile javaFile = compiler.getJavaFile(); + + if (javaFile.isSuperclassIsJAXXObject()) { + throw new IllegalStateException( + "This method does not accept compiler that " + + "inheritates from a jaxx file."); + } + + String className = javaFile.getSimpleName(); + + if (engine.isVerbose()) { + log.info("start " + javaFile.getName()); + } + + addStartProfileTime(engine, compiler); + + // get already registred constructors : need to keep the list of parameters + // not to generate a constructor with same prototype twice. + List<List<String>> prototypes = getDeclaredConstructorPrototypes(compiler, javaFile); + + MethodDescriptor[] constructorDescriptors = + compiler.getRootObject().getObjectClass().getConstructorDescriptors(); + + List<String> constructorTypes; + boolean canAddConstructor; + + if (constructorDescriptors == null || constructorDescriptors.length == 0) { + + // no constructors (use only a default constructor) + + constructorTypes = getConstructorTypes(); + canAddConstructor = canAddConstructor(prototypes, constructorTypes); + if (canAddConstructor) { + addConstructor(compiler, className, constructorTypes); + } + + constructorTypes.add(0, JAXXCompiler.getCanonicalName(JAXXContext.class)); + canAddConstructor = canAddConstructor(prototypes, constructorTypes); + if (canAddConstructor) { + addConstructorWithInitialContext(compiler, className, constructorTypes, false); + } + } else { + for (MethodDescriptor constructorDescriptor : constructorDescriptors) { + + constructorTypes = getConstructorTypes(constructorDescriptor.getParameterTypes()); + canAddConstructor = canAddConstructor(prototypes, constructorTypes); + if (canAddConstructor) { + addConstructor(compiler, className, constructorTypes); + } + + constructorTypes.add(0, JAXXCompiler.getCanonicalName(JAXXContext.class)); + canAddConstructor = canAddConstructor(prototypes, constructorTypes); + if (canAddConstructor) { + addConstructorWithInitialContext(compiler, className, constructorTypes, false); + } + } + } + + addEndProfileTime(engine, compiler); + } + + /** + * To add constructor on the given {@code compiler}, knowing that the super + * class of it is a jaxx class. + * + * In this mode, we takes all the constructors of the parent (if parent has + * some!) and for each of them add the simple one and another one with + * first parameter a {@link JAXXContext}. + * + * @param engine the current engine which compiled compiler + * @param compiler the current compiler to treat + * @param parentCompiler the compiler of the super class (can be + * {@code null} if super class was not generated by + * the given engine). + * @throws ClassNotFoundException if a class could not be found (when wanted to have extact type for constructor parameters) + * @throws IllegalStateException if given {@code compiler has not a super JAXX class}. + */ + protected void addConstructorsForSuperClassJaxx(JAXXEngine engine, + JAXXCompiler compiler, + JAXXCompiler parentCompiler) throws ClassNotFoundException, IllegalStateException { + + JavaFile javaFile = compiler.getJavaFile(); + + if (!javaFile.isSuperclassIsJAXXObject()) { + throw new IllegalStateException( + "This method does not accept compiler that " + + "inheritates not from a jaxx file."); + } + + String className = javaFile.getSimpleName(); + + if (engine.isVerbose()) { + log.info("start " + javaFile.getName()); + } + + addStartProfileTime(engine, compiler); + + // get already registred constructors : need to keep the list of parameters + // not to generate a constructor with same prototype twice. + List<List<String>> prototypes = getDeclaredConstructorPrototypes(compiler, javaFile); + + MethodDescriptor[] constructorDescriptors; + + if (parentCompiler == null) { + + // the parent was not generated by this engine, this means that is + // class descriptor can be used to obtain constructors + constructorDescriptors = compiler.getRootObject().getObjectClass().getConstructorDescriptors(); + } else { + + // the parent was generated by this engine, can not trust the class + // descriptor at the moment, so just seek in his java file for + // already generated constructor + List<JavaConstructor> constructors = parentCompiler.getJavaFile().getConstructors(); + constructorDescriptors = new MethodDescriptor[constructors.size()]; + + int i = 0; + for (JavaConstructor constructor : constructors) { + String[] parameters = new String[constructor.getArguments().length]; + int j = 0; + for (JavaArgument argument : constructor.getArguments()) { + String type = argument.getType(); + parameters[j++] = type; + } + constructorDescriptors[i++] = new MethodDescriptor( + null, + constructor.getModifiers(), + null, + parameters, + compiler.getClassLoader() + ); + } + } + + // dealing with a jsuper class JAXX we are sure to have at least two constructors : + // a default one + one with just a JAXXContext parameter + + List<String> constructorTypes; + boolean canAddConstructor; + + for (MethodDescriptor constructorDescriptor : constructorDescriptors) { + + ClassDescriptor[] parameterTypes = constructorDescriptor.getParameterTypes(); + + if (parentCompiler == null) { + + // we already have the good type ??? this is dangerous + // because we could miss an import ? must be improved + constructorTypes = new ArrayList<>(parameterTypes.length); + + for (ClassDescriptor parameterType : parameterTypes) { + constructorTypes.add(parameterType.getName()); + } + } else { + + + constructorTypes = getConstructorTypes(parameterTypes); + } + canAddConstructor = canAddConstructor(prototypes, constructorTypes); + if (canAddConstructor) { + addConstructor(compiler, className, constructorTypes); + } + +// constructorTypes.add(0, JAXXCompiler.getCanonicalName(JAXXContext.class)); +// canAddConstructor = canAddConstructor(prototypes, constructorTypes); +// if (canAddConstructor) { +// addConstructorWithInitialContext(compiler, className, constructorTypes, true); +// } + } + + + addEndProfileTime(engine, compiler); + } + + protected List<List<String>> getDeclaredConstructorPrototypes(JAXXCompiler compiler, + JavaFile javaFile) throws ClassNotFoundException { + List<JavaConstructor> constructors = javaFile.getConstructors(); + List<List<String>> prototypes = new ArrayList<>(constructors.size()); + for (JavaConstructor constructor : constructors) { + List<String> prototype = new ArrayList<>(); + for (JavaArgument argument : constructor.getArguments()) { + String type = argument.getType(); + String fqn = TagManager.resolveClassName(type, compiler); + ClassDescriptor classDescriptor = ClassDescriptorHelper.getClassDescriptor(fqn); + String canonicalName = JAXXCompiler.getCanonicalName(classDescriptor); + prototype.add(canonicalName); + } + prototypes.add(prototype); + } + return prototypes; + } + + private boolean canAddConstructor(List<List<String>> prototypes, List<String> constructorTypes) { + return !prototypes.contains(constructorTypes); + } + + private List<String> getConstructorTypes(ClassDescriptor... descriptors) { + List<String> result = new ArrayList<>(); + // add all parameters from constructor + for (ClassDescriptor descriptor : descriptors) { + String fqn = JAXXCompiler.getCanonicalName(descriptor); + result.add(fqn); + } + return result; + } + + protected void addConstructor(JAXXCompiler compiler, + String className, + List<String> constructorTypes) throws CompilerException { + StringBuilder code = new StringBuilder(); + String eol = JAXXCompiler.getLineSeparator(); + + JavaArgument[] arguments = new JavaArgument[constructorTypes.size()]; + + if (!constructorTypes.isEmpty()) { + + // constructeur avec des paramètres + code.append(" super("); + int i = 0; + for (String constructorType : constructorTypes) { + JavaArgument argument = JavaElementFactory.newArgument( + constructorType, + "param" + i + ); + arguments[i] = argument; + if (i > 0) { + code.append(" ,"); + } + code.append(argument.getName()); + i++; + } + + code.append(");").append(eol); + } + code.append(DefaultFinalizer.METHOD_NAME_$INITIALIZE + "();"); + code.append(eol); + JavaConstructor constructor = JavaElementFactory.newConstructor(PUBLIC, + className, + code.toString(), + arguments + ); + compiler.getJavaFile().addConstructor(constructor); + } + + protected void addConstructorWithInitialContext(JAXXCompiler compiler, + String className, + List<String> constructorTypes, + boolean superclassIsJAXXObject) throws CompilerException { + StringBuilder code = new StringBuilder(); + String eol = JAXXCompiler.getLineSeparator(); + + JavaArgument firstArgument = JavaElementFactory.newArgument( + JAXXContext.class.getName(), + PARAMETER_NAME_PARENT_CONTEXT + ); + JavaArgument[] arguments = new JavaArgument[constructorTypes.size()]; + arguments[0] = firstArgument; + for (int i = 1, max = constructorTypes.size(); i < max; i++) { + String constructorType = constructorTypes.get(i); + JavaArgument argument = JavaElementFactory.newArgument( + constructorType, + "param" + i + ); + arguments[i] = argument; + } + if (superclassIsJAXXObject) { + + // we are sure to have at least the first parameter in the super code + code.append(" super("); + code.append(PARAMETER_NAME_PARENT_CONTEXT); + for (int i = 1, max = constructorTypes.size(); i < max; i++) { + String constructorType = constructorTypes.get(i); + JavaArgument argument = JavaElementFactory.newArgument( + constructorType, + "param" + i + ); + arguments[i] = argument; + code.append(" ,"); + code.append(argument.getName()); + } + code.append(");").append(eol); + } else { + + // only a super class only if more than the parentContext parameter + if (constructorTypes.size() > 1) { + + code.append(" super("); + + for (int i = 1, max = constructorTypes.size(); i < max; i++) { + String constructorType = constructorTypes.get(i); + JavaArgument argument = JavaElementFactory.newArgument( + constructorType, + "param" + i + ); + arguments[i] = argument; + if (i > 1) { + code.append(" ,"); + } + code.append(argument.getName()); + } + code.append(");").append(eol); + } + } + + if (!superclassIsJAXXObject) { + + // call explicitly the init code of the parentContext + String prefix = compiler.getImportedType(JAXXUtil.class); + code.append(prefix); + code.append(".initContext(this, " + PARAMETER_NAME_PARENT_CONTEXT + ");"); + code.append(eol); + } + code.append(DefaultFinalizer.METHOD_NAME_$INITIALIZE + "();"); + code.append(eol); + JavaConstructor constructor = JavaElementFactory.newConstructor(PUBLIC, + className, + code.toString(), + arguments + ); + compiler.getJavaFile().addConstructor(constructor); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/GenerateMissingRulesTask.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/GenerateMissingRulesTask.java new file mode 100644 index 0000000..911dd90 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/GenerateMissingRulesTask.java @@ -0,0 +1,130 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.tasks; + +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXCompilerFile; +import org.nuiton.jaxx.compiler.JAXXEngine; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.File; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Last task to generate java files. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class GenerateMissingRulesTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(GenerateMissingRulesTask.class); + + /** Task name */ + public static final String TASK_NAME = "GenerateMissingRules"; + + public GenerateMissingRulesTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + boolean success = true; + boolean isVerbose = engine.getConfiguration().isVerbose(); + + JAXXCompilerFile[] files = engine.getCompiledFiles(); + + for (JAXXCompilerFile jaxxFile : files) { + String className = jaxxFile.getClassName(); + if (isVerbose) { + log.info("start " + className); + } + + JAXXCompiler compiler = jaxxFile.getCompiler(); + addStartProfileTime(engine, compiler); + + if (compiler.isIdentCssFound()) { + + File cssFile = jaxxFile.getCssFile(); + + String cssContent = FileUtils.readFileToString(cssFile); + + Map<String, CompiledObject> objects = compiler.getObjects(); + + Set<String> cssRulesToAdd = new LinkedHashSet<>(); + + for (String id : objects.keySet()) { + + CompiledObject object = objects.get(id); + String styleClass = object.getStyleClass(); + + if (isVerbose) { + log.info("id : " + id + ", styleClass : " + styleClass); + } + + if (!id.startsWith("$")) { + Pattern idPattern = Pattern.compile("#" + id + "\\s*\\{.*\\}", Pattern.DOTALL); + Matcher idMatcher = idPattern.matcher(cssContent); + + if (!idMatcher.find()) { + if (log.isInfoEnabled()) { + log.info("add css rule for #" + id + " in " + cssFile.getName()); + } + cssRulesToAdd.add( "\n\n/* #" + id + " {} */"); + } + } + + if (styleClass != null) { + Pattern classPattern = Pattern.compile("\\." + styleClass + "\\s*\\{.*\\}", Pattern.DOTALL); + Matcher classMatcher = classPattern.matcher(cssContent); + + if (!classMatcher.find()) { + if (log.isInfoEnabled()) { + log.info("add css rule for ." + styleClass + " in " + cssFile.getName()); + } + cssRulesToAdd.add( "\n\n/* ." + styleClass + " {} */"); + } + } + + } + + FileUtils.write(cssFile, StringUtils.join(cssRulesToAdd, ""), true); + } + + addEndProfileTime(engine, compiler); + + if (compiler.isFailed()) { + success = false; + } + } + return success; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/GenerateTask.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/GenerateTask.java new file mode 100644 index 0000000..e99c9f5 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/GenerateTask.java @@ -0,0 +1,205 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.tasks; + +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXCompilerFile; +import org.nuiton.jaxx.compiler.JAXXEngine; +import org.nuiton.jaxx.compiler.java.JavaArgument; +import org.nuiton.jaxx.compiler.java.JavaConstructor; +import org.nuiton.jaxx.compiler.java.JavaFile; +import org.nuiton.jaxx.compiler.java.JavaFileGenerator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.eugene.java.extension.ImportsManager; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Last task to generate java files. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class GenerateTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(GenerateTask.class); + + /** Task name */ + public static final String TASK_NAME = "Generate"; + + public GenerateTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + + // check all files are attached to a compiler + checkAllFilesCompiled(engine); + + boolean success = true; + + boolean verbose = engine.isVerbose(); + + JavaFileGenerator generator = + new JavaFileGenerator(JAXXCompiler.getLineSeparator(), verbose); + + JAXXCompilerFile[] files = engine.getCompiledFiles(); + + for (JAXXCompilerFile jaxxFile : files) { + if (verbose) { + log.info("start " + jaxxFile.getClassName()); + } + + JAXXCompiler compiler = jaxxFile.getCompiler(); + + addStartProfileTime(engine, compiler); + + try { + consumeCompiler(compiler, generator); + } finally { + compiler.getJavaFile().clear(); + } + addEndProfileTime(engine, compiler); + if (compiler.isFailed()) { + success = false; + } + } + return success; + } + + public void consumeCompiler(JAXXCompiler compiler, + JavaFileGenerator generator) throws IOException { + + JavaFile javaFile = compiler.getJavaFile(); + + String packageName = javaFile.getPackageName(); + + // optimize imports + List<String> imports = optimizeImports(javaFile, packageName); + + String packageToExclude = packageName + ".*"; + + // push back previous imports + for (String importFQN : javaFile.getImports()) { + if (!packageToExclude.equals(importFQN) && + !imports.contains(importFQN)) { + imports.add(importFQN); + } + } + + // set them to the file to generate + javaFile.setImports(imports); + + + // generate java file + compiler.generate(generator); + } + + public List<String> optimizeImports(JavaFile f, + String packageName) { + + ImportsManager importsManager = f.getImportManager(); + + List<String> result; + + for (String importFQN : f.getImports()) { + if (log.isDebugEnabled()) { + log.debug("Add import : " + importFQN); + } + importsManager.addImport(importFQN); + } + + if (f.getSuperClass() != null) { + String superClass = f.getSuperClass(); + try { + String type = importsManager.getType(superClass); + f.setSuperClass(type); + } catch (Exception e) { + log.error("file [" + f.getName() + + "] Could not determine simple name of super class " + + superClass); + } + } + + List<String> interfaces = f.getInterfaces(); + List<String> interfaces2 = new ArrayList<>(interfaces.size()); + for (String anInterface : interfaces) { + try { + String newInterface = importsManager.getType(anInterface); + interfaces2.add(newInterface); + } catch (Exception e) { + log.error("file [" + f.getName() + + "] Could not get interface " + anInterface + " :: " + + e.getMessage()); + interfaces2.add(anInterface); + } + } + f.setInterfaces(interfaces2); + + // optimize constructors parameters + optimizeConstructorParameters(f, importsManager); +// importsManager.addImport(JAXXUtil.class); +// if (!f.isSuperclassIsJAXXObject() || needSwingUtil) { +// +// // while implementing JAXXObject contract we sure need the +// // SwingUtil class +// importsManager.addImport(SwingUtil.class); +// } + result = importsManager.getImports(packageName); + result.remove(packageName + ".*"); + if (log.isDebugEnabled()) { + log.debug("[" + f.getName() + "] Detect " + result.size() + + " imports to add."); + for (String s : result) { + log.debug(" " + s); + } + } + + return result; + } + + protected void optimizeConstructorParameters(JavaFile f, + ImportsManager importsManager) { + + List<JavaConstructor> constructors = f.getConstructors(); + for (JavaConstructor constructor : constructors) { + JavaArgument[] arguments = constructor.getArguments(); + for (JavaArgument argument : arguments) { + String type = argument.getType(); + try { + String simpleType = importsManager.getType(type); + argument.setType(simpleType); + } catch (Exception e) { + log.error("file [" + f.getName() + + "] Could not get simple type of constructor paramter " + type + " :: " + + e.getMessage()); + } + + } + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/InitTask.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/InitTask.java new file mode 100644 index 0000000..715974d --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/InitTask.java @@ -0,0 +1,83 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.tasks; + +import org.nuiton.jaxx.compiler.CompilerConfiguration; +import org.nuiton.jaxx.compiler.JAXXEngine; +import org.nuiton.jaxx.compiler.JAXXFactory; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * The init task to be launched first. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class InitTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(InitTask.class); + + /** Task name */ + public static final String TASK_NAME = "Init"; + + public InitTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + boolean success = true; + + CompilerConfiguration configuration = engine.getConfiguration(); + + // check initializers + if (configuration.getInitializers() == null) { + throw new NullPointerException( + "no initializers found in configuration."); + } + + // check decorators + if (configuration.getDecorators() == null) { + + throw new NullPointerException( + "no decorators found in configuration."); + } + + // check finalizers + if (configuration.getFinalizers() == null) { + + throw new NullPointerException( + "no finalizers found in configuration."); + } + + if (configuration.isVerbose()) { + log.info("Will init " + JAXXFactory.class.getName()); + } + JAXXFactory.initFactory(); + + engine.clearReports(); + + return success; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/JAXXEngineTask.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/JAXXEngineTask.java new file mode 100644 index 0000000..8eaf3ec --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/JAXXEngineTask.java @@ -0,0 +1,83 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.tasks; + +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXCompilerFile; +import org.nuiton.jaxx.compiler.JAXXEngine; + +/** + * Base class to implement a task to be launched by a {@link JAXXEngine}. + * + * The {@link #perform(JAXXEngine)} method contains the logic of the task. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public abstract class JAXXEngineTask { + + /** Task name */ + private final String name; + + public JAXXEngineTask(String name) { + this.name = name; + } + + /** + * Performs the task on the given {@code engine}. + * + * @param engine the engine to use + * @return {@code false} if task failed (with no exception), {@code true} otherwise. + * @throws Exception if any error + */ + public abstract boolean perform(JAXXEngine engine) throws Exception; + + public String getName() { + return name; + } + + /** + * Checks the engine does not have any more files to discover. + * + * @param engine the engine to test + * @throws IllegalStateException if there is still some files to discover. + */ + protected void checkAllFilesCompiled(JAXXEngine engine) throws IllegalStateException { + JAXXCompilerFile[] undone = engine.getFilesToCompile(); + + if (undone.length > 0) { + + throw new IllegalStateException("Can not start '" + getName() + "', there is still files to process in '" + CompileFirstPassTask.TASK_NAME); + } + } + + protected void addStartProfileTime(JAXXEngine engine, + JAXXCompiler compiler) { + engine.addProfileTime(compiler, name + "_start"); + } + + + protected void addEndProfileTime(JAXXEngine engine, + JAXXCompiler compiler) { + engine.addProfileTime(compiler, name + "_end"); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/ProfileTask.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/ProfileTask.java new file mode 100644 index 0000000..9ae465d --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/ProfileTask.java @@ -0,0 +1,53 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.tasks; + +import org.nuiton.jaxx.compiler.JAXXEngine; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A task to display result of profile mode + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class ProfileTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(ProfileTask.class); + + /** Task name */ + public static final String TASK_NAME = "Profile"; + + public ProfileTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + boolean success = true; + StringBuilder buffer = engine.getProfiler().computeProfileReport(); + log.info(buffer.toString()); + return success; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/StyleSheetTask.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/StyleSheetTask.java new file mode 100644 index 0000000..80ceb07 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tasks/StyleSheetTask.java @@ -0,0 +1,77 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.tasks; + +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXCompilerFile; +import org.nuiton.jaxx.compiler.JAXXEngine; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Task to apply css stylesheet on objects after second round of compilation. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class StyleSheetTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(StyleSheetTask.class); + + /** Task name */ + public static final String TASK_NAME = "StyleSheet"; + + public StyleSheetTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + + // check all files are attached to a compiler + checkAllFilesCompiled(engine); + + boolean success = true; + boolean isVerbose = engine.getConfiguration().isVerbose(); + + JAXXCompilerFile[] files = engine.getCompiledFiles(); + + for (JAXXCompilerFile jaxxFile : files) { + String className = jaxxFile.getClassName(); + if (isVerbose) { + log.info("start " + className); + } + + JAXXCompiler compiler = jaxxFile.getCompiler(); + addStartProfileTime(engine, compiler); + compiler.applyStylesheets(); + addEndProfileTime(engine, compiler); + + if (compiler.isFailed()) { + success = false; + } + } + return success; + } + +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/PrintTagInfo.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/PrintTagInfo.java new file mode 100644 index 0000000..cd0ee9f --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/PrintTagInfo.java @@ -0,0 +1,143 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tools; + +import org.nuiton.jaxx.compiler.DefaultCompilerConfiguration; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXFactory; +import org.nuiton.jaxx.compiler.beans.JAXXPropertyDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; +import org.nuiton.jaxx.compiler.tags.DefaultObjectHandler; +import org.nuiton.jaxx.compiler.tags.TagManager; +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStreamWriter; + +/** Generates information about a tag for use on the jaxxframework.org web site. */ +public class PrintTagInfo { + /** + * Displays information about the class name in arg[0]. + * + * @param arg command-line arguments + * @throws Exception if an error occurs + */ + public static void main(String[] arg) throws Exception { + if (arg.length < 1) { + throw new IllegalArgumentException("programm needs at least two parameters : the file where to put the result, and at least one fqn class to treate"); + } + String firstarg = arg[0]; + boolean toFile = false; + BufferedWriter w; + if (firstarg.startsWith("file:")) { + w = new BufferedWriter(new FileWriter(firstarg.substring(5))); + toFile = true; + } else { + w = new BufferedWriter(new OutputStreamWriter(System.out)); + } + + try { + JAXXFactory.setConfiguration(new DefaultCompilerConfiguration()); + JAXXFactory.initFactory(); + for (int i = toFile ? 1 : 0; i < arg.length; i++) { + String className = arg[i]; + treateClass(w, className); + } + } finally { + w.flush(); + w.close(); + } + + } + + protected static void treateClass(BufferedWriter w, String className) throws ClassNotFoundException, IOException { + + ClassDescriptor beanClass = ClassDescriptorHelper.getClassDescriptor(className); + DefaultObjectHandler handler = TagManager.getTagHandler(beanClass); + + DefaultObjectHandler superHandler = TagManager.getTagHandler(beanClass.getSuperclass()); + + // dump all bean properties + w.append("Properties in ").append(String.valueOf(beanClass)); + w.newLine(); + JAXXPropertyDescriptor[] properties = handler.getJAXXBeanInfo().getJAXXPropertyDescriptors(); + JAXXPropertyDescriptor[] superProperties = superHandler.getJAXXBeanInfo().getJAXXPropertyDescriptors(); + for (JAXXPropertyDescriptor property : properties) { + if (property.getWriteMethodDescriptor() == null) { + continue; + } + + boolean found = false; + String name = property.getName(); + for (JAXXPropertyDescriptor superProperty : superProperties) { + if (superProperty.getName().equals(name)) { + found = true; + break; + } + } + if (!found) { + if (property.getPropertyType() == null) { + System.err.println(name + " has null type"); + } else { + w.append("{{EquivalentAttribute|"); + w.append(name); + w.append("|"); + w.append(className.replace('.', '/')); + w.append("|set"); + w.append(StringUtils.capitalize(name)); + w.append("|"); + w.append(JAXXCompiler.getCanonicalName(property.getPropertyType())); + w.append("}}"); + w.append("|-"); + w.newLine(); + } + } + } + + w.newLine(); + w.newLine(); + + // dump all bound methods + dumpMethods(w, beanClass, handler); + } + + protected static void dumpMethods(BufferedWriter w, ClassDescriptor beanClass, DefaultObjectHandler handler) throws IOException { + MethodDescriptor[] methods = beanClass.getMethodDescriptors(); + w.append("Bound methods in ").append(String.valueOf(beanClass)); + w.newLine(); + for (MethodDescriptor method : methods) { + try { + if (handler.isMemberBound(method.getName())) { + w.append("* <tt>").append(method.getName()).append("()</tt>"); + w.newLine(); + } + } catch (Throwable e) { + // ignore ? + } + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/AbstractContextNode.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/AbstractContextNode.java new file mode 100644 index 0000000..754288f --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/AbstractContextNode.java @@ -0,0 +1,41 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tools.jaxxcapture; + +import java.util.ArrayList; +import java.util.List; + +public abstract class AbstractContextNode implements ContextNode { + private List<ContextNode> arguments = new ArrayList<>(); + + + @Override + public void addArgument(ContextNode node) { + arguments.add(node); + } + + @Override + public ContextNode[] getArguments() { + return arguments.toArray(new ContextNode[arguments.size()]); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/CapturedObject.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/CapturedObject.java new file mode 100644 index 0000000..e817221 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/CapturedObject.java @@ -0,0 +1,176 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tools.jaxxcapture; + +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.tools.jaxxcapture.handlers.ObjectHandler; + +import java.awt.Component; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +public class CapturedObject extends AbstractContextNode { + private String className; + + private ObjectHandler handler; + + /** Maps children to their constraints. */ + private Map<CapturedObject, ContextNode> children = new LinkedHashMap<>(); + + private CapturedObject parent; + + private Map<String, String> properties = new LinkedHashMap<>(); + + private Map<String, Object> additionalData = new HashMap<>(); + + private StringBuilder innerXML = new StringBuilder(); + + private StringBuilder script = new StringBuilder(); + + private boolean inlineable = true; + + private JAXXCapture capture; + + public CapturedObject(ObjectHandler handler, String className, JAXXCapture capture) { + this.handler = handler; + this.className = className; + this.capture = capture; + } + + + public ObjectHandler getObjectHandler() { + return handler; + } + + + public void addChild(CapturedObject child, ContextNode constraints) { + children.put(child, constraints); + child.setParent(this); + } + + + public CapturedObject[] getChildren() { + return children.keySet().toArray(new CapturedObject[children.size()]); + } + + + public CapturedObject getParent() { + return parent; + } + + + public void setParent(CapturedObject parent) { + this.parent = parent; + } + + + public ContextNode getConstraints(CapturedObject child) { + return children.get(child); + } + + + public String getClassName() { + return className; + } + + + public String getProperty(String key) { + return properties.get(key); + } + + + public void setProperty(String key, String value) { + properties.put(key, value); + } + + + public Map<String, String> getProperties() { + return properties; + } + + + public Object getAdditionalData(String key) { + return additionalData.get(key); + } + + + public void setAdditionalData(String key, Object value) { + additionalData.put(key, value); + } + + + public Map<String, Object> getAdditionalData() { + return additionalData; + } + + + public void setInlineable(boolean inlineable) { + this.inlineable = inlineable; + } + + + public boolean isInlineable() { + try { + return script.length() == 0 && !Component.class.isAssignableFrom(Class.forName(className, true, capture.getClassLoader())) && inlineable; + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + + public void appendInnerXML(String xml) { + if (this.innerXML.length() > 0) { + this.innerXML.append(JAXXCompiler.getLineSeparator()); + } + this.innerXML.append(xml); + } + + + public String getInnerXML() { + return innerXML.toString(); + } + + + public void appendScriptCode(String script) { + if (this.script.length() > 0) { + this.script.append(JAXXCompiler.getLineSeparator()); + } + this.script.append(script); + } + + + public String getScriptCode() { + return script.toString(); + } + + + public String getXML(JAXXCapture capture) { + return getObjectHandler().getXML(this, capture); + } + + @Override + public String toString() { + return "CapturedObject[" + getProperty("id") + ", " + className + "]"; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/ContextNode.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/ContextNode.java new file mode 100644 index 0000000..d6d0308 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/ContextNode.java @@ -0,0 +1,30 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tools.jaxxcapture; + +public interface ContextNode { + + void addArgument(ContextNode node); + + ContextNode[] getArguments(); +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/JAXXCapture.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/JAXXCapture.java new file mode 100644 index 0000000..1318f0f --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/JAXXCapture.java @@ -0,0 +1,405 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tools.jaxxcapture; + +import org.nuiton.jaxx.compiler.ClassMap; +import org.nuiton.jaxx.compiler.CompiledObject; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.tools.jaxxcapture.handlers.JTabbedPaneHandler; +import org.nuiton.jaxx.compiler.tools.jaxxcapture.handlers.ObjectHandler; +import org.nuiton.jaxx.compiler.tools.jaxxcapture.handlers.TableHandler; +import org.nuiton.jaxx.compiler.types.TypeManager; +import org.apache.commons.lang3.StringUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; +import org.xml.sax.SAXException; + +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JTabbedPane; +import javax.swing.JWindow; +import javax.swing.SwingUtilities; +import java.awt.AWTEvent; +import java.awt.Component; +import java.awt.Container; +import java.awt.EventQueue; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.MouseEvent; +import java.beans.XMLEncoder; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; + +public class JAXXCapture { + + private static ClassMap<Object> objectHandlers = new ClassMap<>(); + + static { + //TODO make a serviceLoader mecanism to allow inter-module loading + objectHandlers.put(ClassDescriptorHelper.getClassDescriptor(Object.class), new ObjectHandler()); + objectHandlers.put(ClassDescriptorHelper.getClassDescriptor(JTabbedPane.class), new JTabbedPaneHandler()); + try { + objectHandlers.put(ClassDescriptorHelper.getClassDescriptor("org.nuiton.jaxx.runtime.swing.Table"), new TableHandler()); + } catch (ClassNotFoundException e) { + System.err.println(e); + } + } + + private Map<String, Object> sourceObjects = new HashMap<>(); + + private Map<String, CapturedObject> capturedObjects = new HashMap<>(); + + private ClassLoader classLoader; + + private int count; + + private static class CaptureEventQueue extends EventQueue { + + private ClassLoader classLoader; + + private CaptureEventQueue(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + @Override + public void dispatchEvent(AWTEvent event) { + if (event.getID() == MouseEvent.MOUSE_PRESSED && ((MouseEvent) event).isControlDown()) { + Component target = ((MouseEvent) event).getComponent(); + if (!(target instanceof Window)) { + target = SwingUtilities.getWindowAncestor(target); + } + if (target instanceof JFrame) { + target = ((JFrame) target).getContentPane(); + } else if (target instanceof JDialog) { + target = ((JDialog) target).getContentPane(); + } + if (target instanceof JWindow) { + target = ((JWindow) target).getContentPane(); + } + if (target != null) { + Thread.currentThread().setContextClassLoader(classLoader); + JAXXCapture capture = new JAXXCapture(classLoader); + capture.applyNames(target); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + XMLEncoder encoder = new XMLEncoder(buffer); + encoder.writeObject(target); + encoder.close(); + try { + System.err.println(new String(buffer.toByteArray())); + System.out.println(capture.convertToJAXX(new ByteArrayInputStream(buffer.toByteArray()))); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + super.dispatchEvent(event); + } + } + + private JAXXCapture(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public Map<String, CapturedObject> getCapturedObjects() { + return capturedObjects; + } + + private void applyNames(Component target) { + String name = target.getName(); + if (name == null || sourceObjects.containsKey(name) || !CompiledObject.isValidID(name)) { + do { + name = "Object" + ++count; + } while (sourceObjects.containsKey(name)); + } + target.setName(name); + assert !sourceObjects.containsKey(name) : "ID " + name + " is already registered"; + sourceObjects.put(name, target); + + if (target instanceof Container) { + Container container = (Container) target; + for (int i = 0; i < container.getComponentCount(); i++) { + applyNames(container.getComponent(i)); + } + } + } + + public static String getText(Element tag) { // NOT a safe general-purpose implementation! + return ((Text) tag.getChildNodes().item(0)).getData(); + } + + private String getArgumentsCode(ContextNode[] arguments) { + StringBuilder result = new StringBuilder(); + result.append('('); + for (int i = 0; i < arguments.length; i++) { + if (i != 0) { + result.append(", "); + } + result.append(getJavaCode(arguments[i])); + } + result.append(')'); + return result.toString(); + } + + public String getJavaCode(ContextNode node) { + StringBuilder result = new StringBuilder(); + if (node instanceof PropertyNode) { + ContextNode[] arguments = node.getArguments(); + result.append(arguments.length == 0 ? "get" : "set"); + result.append(StringUtils.capitalize(((PropertyNode) node).getProperty())); + result.append(getArgumentsCode(arguments)); + } else if (node instanceof MethodNode) { + result.append((((MethodNode) node).getMethodName())); + result.append(getArgumentsCode(node.getArguments())); + } else if (node instanceof CapturedObject) { + CapturedObject object = (CapturedObject) node; + if (object.isInlineable()) { + result.append("new "); + result.append(object.getClassName()); + result.append(getArgumentsCode(node.getArguments())); + } else { + String id = object.getProperty("id"); + assert id != null; + result.append(id); + } + } else if (node instanceof ValueNode) { + result.append(TypeManager.getJavaCode(((ValueNode) node).getValue())); + } else if (node instanceof LiteralNode) { + result.append(((LiteralNode) node).getJavaCode()); + } else { + throw new IllegalArgumentException("unrecognized node type: " + node); + } + return result.toString(); + } + + // returns the best matching method for the specified argument types + private static Method getMethod(Class<?> target, String methodName, Class<?>[] arguments) { + try { + // use the package-private class java.beans.ReflectionUtils to resolve the method. This isn't 100% safe, but it's better than + // having to rewrite the resolution myself. + Class<?> reflectionUtils = Class.forName("java.beans.ReflectionUtils"); + Method getMethod = reflectionUtils.getDeclaredMethod("getMethod", new Class<?>[]{Class.class, String.class, Class[].class}); + getMethod.setAccessible(true); + return (Method) getMethod.invoke(null, target, methodName, arguments); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + // returns the best matching constructor for the specified argument types + private static Constructor<?> getConstructor(Class<?> target, Class<?>[] arguments) { + try { + // use the package-private class java.beans.ReflectionUtils to resolve the constructor. This isn't 100% safe, but it's better than + // having to rewrite the resolution myself. + Class<?> reflectionUtils = Class.forName("java.beans.ReflectionUtils"); + Method getConstructor = reflectionUtils.getDeclaredMethod("getConstructor", new Class<?>[]{Class.class, Class[].class}); + getConstructor.setAccessible(true); + return (Constructor<?>) getConstructor.invoke(null, target, arguments); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private Object createInstance(CapturedObject object) { + try { + ContextNode[] argumentNodes = object.getArguments(); + Object[] arguments = new Object[argumentNodes.length]; + Class<?>[] argumentTypes = new Class<?>[argumentNodes.length]; + for (int j = 0; j < argumentNodes.length; j++) { + if (argumentNodes[j] instanceof ValueNode) { + arguments[j] = ((ValueNode) argumentNodes[j]).getValue(); + argumentTypes[j] = arguments[j] != null ? arguments[j].getClass() : null; + } else if (argumentNodes[j] instanceof CapturedObject) { + arguments[j] = createInstance((CapturedObject) argumentNodes[j]); + argumentTypes[j] = arguments[j] != null ? arguments[j].getClass() : null; + } + } + Constructor<?> constructor = getConstructor(Class.forName(object.getClassName(), true, classLoader), argumentTypes); + return constructor.newInstance(arguments); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public String getJavaCode(Stack/*<ContextNode>*/ context) { + CapturedObject contextCapturedObject = (CapturedObject) context.get(0); + StringBuilder result = new StringBuilder(); + int start = 1; + for (int i = context.size() - 1; i > 1; i--) { + if (context.get(i) instanceof CapturedObject) { + start = i; + contextCapturedObject = (CapturedObject) context.get(i); + break; + } + } + Object contextObject = sourceObjects.get(contextCapturedObject.getProperty("id")); + Class<?> contextClass = contextObject != null ? contextObject.getClass() : null; + + for (int i = start; i < context.size(); i++) { + ContextNode node = (ContextNode) context.get(i); + if (contextObject != null && (node instanceof MethodNode || node instanceof PropertyNode)) { + // need to follow the call chain so we can insert typecasts as necessary + try { + String methodName; + ContextNode[] argumentNodes = node.getArguments(); + if (node instanceof MethodNode) { + methodName = ((MethodNode) node).getMethodName(); + } else { + methodName = (argumentNodes.length == 0 ? "get" : "set") + StringUtils.capitalize(((PropertyNode) node).getProperty()); + } + Object[] arguments = new Object[argumentNodes.length]; + Class<?>[] argumentTypes = new Class<?>[argumentNodes.length]; + for (int j = 0; j < argumentNodes.length; j++) { + if (argumentNodes[j] instanceof ValueNode) { + arguments[j] = ((ValueNode) argumentNodes[j]).getValue(); + argumentTypes[j] = arguments[j] != null ? arguments[j].getClass() : null; + } else if (argumentNodes[j] instanceof CapturedObject) { + arguments[j] = createInstance((CapturedObject) argumentNodes[j]); + argumentTypes[j] = arguments[j].getClass(); + } else if (argumentNodes[j] instanceof LiteralNode) { + arguments[j] = ((LiteralNode) argumentNodes[j]).getValue(); + argumentTypes[j] = arguments[j].getClass(); + } else { + throw new IllegalArgumentException("unsupported argument type: " + argumentNodes[j]); + } + } + + Method method = getMethod(contextClass, methodName, argumentTypes); + if (method == null) { + // could not find method in contextClass, must be defined in a subclass -- insert a typecast + result.insert(0, "((" + getOutputName(contextObject.getClass()) + ") "); + result.append(')'); + method = getMethod(contextObject.getClass(), methodName, argumentTypes); + } + if (method == null) { + throw new RuntimeException("could not find method " + methodName + Arrays.asList(argumentTypes) + " in " + contextObject.getClass() + " (context: " + context + ")"); + } + contextObject = method.invoke(contextObject, arguments); + contextClass = method.getReturnType(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + if (i > start) { + result.append('.'); + } + + result.append(getJavaCode(node)); + } + return result + ";"; + } + + private String getOutputName(Class<?> c) { + return c.getName(); + } + + public CapturedObject processObject(Element objectTag, Stack<ContextNode> context) { + String className = objectTag.getAttribute("class"); + ObjectHandler handler; + if (className.length() > 0) { + try { + ClassDescriptor descriptor = ClassDescriptorHelper.getClassDescriptor(className, classLoader); + handler = (ObjectHandler) objectHandlers.get(descriptor); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + handler = (ObjectHandler) objectHandlers.get(ClassDescriptorHelper.getClassDescriptor(Object.class)); + } + + return handler.processObject(objectTag, context, this); + } + + private synchronized String convertToJAXX(InputStream beansXML) throws IOException { + try { + Document document = JAXXCompiler.parseDocument(beansXML); + Element rootElement = document.getDocumentElement(); + NodeList nodes = rootElement.getChildNodes(); + Stack<ContextNode> context = new Stack<>(); + for (int i = 0; i < nodes.getLength(); i++) { + Node child = nodes.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) child; + if (!element.getTagName().equals("object")) { + throw new Error("expected tag 'object', found '" + element.getTagName() + "'"); + } + CapturedObject root = processObject(element, context); + for (CapturedObject object : capturedObjects.values()) { // add all orphan objects to the root, so any non-inlineable ones have their XML created + if (object.getParent() == null && object != root) { + root.addChild(object, null); + } + } + return root.getXML(this); + } + } + return null; + } catch (SAXException e) { + throw new RuntimeException(e); + } finally { + reset(); + } + } + + private void reset() { + sourceObjects.clear(); + capturedObjects.clear(); + count = 0; + } + + public static void main(String[] arg) throws Exception { + File file = new File(arg[0]); + JarFile jarFile = new JarFile(file); + ClassLoader classLoader = new URLClassLoader(new URL[]{file.toURI().toURL()}); + Thread.currentThread().setContextClassLoader(classLoader); + EventQueue systemQueue = Toolkit.getDefaultToolkit().getSystemEventQueue(); + systemQueue.push(new CaptureEventQueue(classLoader)); + Manifest mf = jarFile.getManifest(); + String mainClassName = mf.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS); + Class<?> mainClass = Class.forName(mainClassName, true, classLoader); + Method main = mainClass.getMethod("main", String[].class); + main.invoke(null, new Object[]{new String[0]}); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/LiteralNode.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/LiteralNode.java new file mode 100644 index 0000000..eff19fa --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/LiteralNode.java @@ -0,0 +1,43 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tools.jaxxcapture; + +public class LiteralNode extends AbstractContextNode { + private String javaCode; + + private Object value; + + public LiteralNode(String javaCode, Object value) { + this.javaCode = javaCode; + this.value = value; + } + + + public String getJavaCode() { + return javaCode; + } + + public Object getValue() { + return value; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/MethodNode.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/MethodNode.java new file mode 100644 index 0000000..b028ba5 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/MethodNode.java @@ -0,0 +1,41 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tools.jaxxcapture; + +public class MethodNode extends AbstractContextNode { + private String methodName; + + public MethodNode(String methodName) { + this.methodName = methodName; + } + + + public String getMethodName() { + return methodName; + } + + @Override + public String toString() { + return "Method[" + methodName + ", " + java.util.Arrays.asList(getArguments()) + "]"; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/PropertyNode.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/PropertyNode.java new file mode 100644 index 0000000..6cfbeba --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/PropertyNode.java @@ -0,0 +1,41 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tools.jaxxcapture; + +public class PropertyNode extends AbstractContextNode { + private String property; + + public PropertyNode(String property) { + this.property = property; + } + + + public String getProperty() { + return property; + } + + + public String toString() { + return "Property[" + property + ", " + java.util.Arrays.asList(getArguments()) + "]"; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/ValueNode.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/ValueNode.java new file mode 100644 index 0000000..0213e1c --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/ValueNode.java @@ -0,0 +1,36 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tools.jaxxcapture; + +public class ValueNode extends AbstractContextNode { + private Object value; + + public ValueNode(Object value) { + this.value = value; + } + + + public Object getValue() { + return value; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/handlers/JTabbedPaneHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/handlers/JTabbedPaneHandler.java new file mode 100644 index 0000000..ef95f8a --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/handlers/JTabbedPaneHandler.java @@ -0,0 +1,48 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tools.jaxxcapture.handlers; + +import org.nuiton.jaxx.compiler.tools.jaxxcapture.ContextNode; +import org.nuiton.jaxx.compiler.tools.jaxxcapture.JAXXCapture; +import org.nuiton.jaxx.compiler.tools.jaxxcapture.MethodNode; +import org.w3c.dom.Element; + +import java.util.Arrays; +import java.util.Stack; + +public class JTabbedPaneHandler extends ObjectHandler { + + @Override + protected void evaluateMethod(Element tag, Stack<ContextNode> context, JAXXCapture capture) { + String methodName = tag.getAttribute("method"); + if (methodName.equals("addTab")) { + MethodNode addTab = new MethodNode(methodName); + context.push(addTab); + processChildren(tag, context, capture); + context.pop(); + System.err.println(Arrays.asList(addTab.getArguments())); + } else { + super.evaluateMethod(tag, context, capture); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/handlers/ObjectHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/handlers/ObjectHandler.java new file mode 100644 index 0000000..d7e2db1 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/handlers/ObjectHandler.java @@ -0,0 +1,346 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tools.jaxxcapture.handlers; + +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import org.nuiton.jaxx.compiler.java.JavaFileGenerator; +import org.nuiton.jaxx.compiler.tools.jaxxcapture.CapturedObject; +import org.nuiton.jaxx.compiler.tools.jaxxcapture.ContextNode; +import org.nuiton.jaxx.compiler.tools.jaxxcapture.JAXXCapture; +import org.nuiton.jaxx.compiler.tools.jaxxcapture.LiteralNode; +import org.nuiton.jaxx.compiler.tools.jaxxcapture.MethodNode; +import org.nuiton.jaxx.compiler.tools.jaxxcapture.PropertyNode; +import org.nuiton.jaxx.compiler.tools.jaxxcapture.ValueNode; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.awt.Container; +import java.lang.reflect.Field; +import java.util.Map; +import java.util.Stack; + +public class ObjectHandler { + private static int count; + + public static final String ATTRIBUTE_PROPERTY = "property"; + + protected CapturedObject createCapturedObject(String className, JAXXCapture capture) { + return new CapturedObject(this, className, capture); + } + + + // returns true if the tag has any "void" children + protected boolean processChildren(Element tag, Stack<ContextNode> context, JAXXCapture capture) { + boolean result = false; + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + Element innerTag = (Element) child; + if (innerTag.getTagName().equals(JAXXCompilerFinalizer.TYPE_VOID)) { + result = true; + } + evaluate(innerTag, context, capture); + } + } + return result; + } + + + protected void evaluateProperty(Element tag, Stack<ContextNode> context, JAXXCapture capture) { + // determine containing object + CapturedObject contextObject = null; + for (int i = context.size() - 1; i >= 0; i--) { + if (context.get(i) instanceof CapturedObject) { + contextObject = (CapturedObject) context.get(i); + break; + } + } + assert contextObject != null; + + String property = tag.getAttribute(ATTRIBUTE_PROPERTY); + if (!property.equals("actionCommand")) { // filter out actionCommand due to screwiness in XMLEncoder's handling of it + Object current = context.peek(); + PropertyNode newContext = new PropertyNode(property); + context.push(newContext); + boolean voidChildren = processChildren(tag, context, capture); + + ContextNode[] arguments = newContext.getArguments(); + if (arguments.length == 1) { + if (current instanceof CapturedObject && arguments[0] instanceof ValueNode) // simple property assignment + { + ((CapturedObject) current).setProperty(property, dataBindingEncode(String.valueOf(((ValueNode) arguments[0]).getValue()))); + } else if (current instanceof CapturedObject && arguments[0] instanceof CapturedObject && ((CapturedObject) arguments[0]).isInlineable()) // simple data binding + { + ((CapturedObject) current).setProperty(property, "{" + capture.getJavaCode(arguments[0]) + "}"); + } else { + contextObject.setInlineable(false); + contextObject.appendScriptCode(capture.getJavaCode(context)); + } + } else if (!voidChildren) { + contextObject.setInlineable(false); + contextObject.appendScriptCode(capture.getJavaCode(context)); + } + + assert context.peek() == newContext; + context.pop(); + } + } + + + protected void evaluateAdd(CapturedObject contextObject, CapturedObject child, ContextNode constraints) { + contextObject.addChild(child, constraints); + } + + + protected void evaluateMethod(Element tag, Stack<ContextNode> context, JAXXCapture capture) { + // determine containing object + CapturedObject contextObject = null; + for (int i = context.size() - 1; i >= 0; i--) { + if (context.get(i) instanceof CapturedObject) { + contextObject = (CapturedObject) context.get(i); + break; + } + } + assert contextObject != null; + + try { + String methodName = tag.getAttribute("method"); + MethodNode newContext = new MethodNode(methodName); + context.push(newContext); + boolean voidChildren = processChildren(tag, context, capture); + boolean add = false; + + ContextNode[] arguments = newContext.getArguments(); + if (methodName.equals("add") && arguments.length >= 1 && arguments[0] instanceof CapturedObject) { + Class<?> contextClass = Class.forName(contextObject.getClassName(), true, capture.getClassLoader()); + if (Container.class.isAssignableFrom(contextClass)) { + add = true; + evaluateAdd(contextObject, (CapturedObject) arguments[0], null); + } + } + + if (!voidChildren && !add) { + contextObject.appendScriptCode(capture.getJavaCode(context)); + } + + assert context.peek() == newContext; + context.pop(); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + + protected void evaluate(Element tag, Stack<ContextNode> context, JAXXCapture capture) { + String tagName = tag.getTagName(); + if (tagName.equals("object")) { + String fieldName = tag.getAttribute("field"); + ContextNode currentNode = context.peek(); + if (fieldName.length() > 0) { + try { + String className = tag.getAttribute("class"); + Field field = Class.forName(className, true, capture.getClassLoader()).getField(fieldName); + Object value = field.get(null); + currentNode.addArgument(new LiteralNode(className + "." + fieldName, value)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + currentNode.addArgument(capture.processObject(tag, context)); + } + } else if (tagName.equals(JAXXCompilerFinalizer.TYPE_VOID)) { + String property = tag.getAttribute(ATTRIBUTE_PROPERTY); + if (property.length() > 0) { + evaluateProperty(tag, context, capture); + } else { + evaluateMethod(tag, context, capture); + } + } else if (tagName.equals("string")) { + context.peek().addArgument(new ValueNode(JAXXCapture.getText(tag))); + } else if (tagName.equals("boolean")) { + context.peek().addArgument(new ValueNode(Boolean.valueOf(JAXXCapture.getText(tag)))); + } else if (tagName.equals("char")) { + context.peek().addArgument(new ValueNode(JAXXCapture.getText(tag).charAt(0))); + } else if (tagName.equals("short")) { + context.peek().addArgument(new ValueNode(Short.valueOf(JAXXCapture.getText(tag)))); + } else if (tagName.equals("int")) { + context.peek().addArgument(new ValueNode(Integer.valueOf(JAXXCapture.getText(tag)))); + } else if (tagName.equals("long")) { + context.peek().addArgument(new ValueNode(Long.valueOf(JAXXCapture.getText(tag)))); + } else if (tagName.equals("float")) { + context.peek().addArgument(new ValueNode(Float.valueOf(JAXXCapture.getText(tag)))); + } else if (tagName.equals("double")) { + context.peek().addArgument(new ValueNode(Double.valueOf(JAXXCapture.getText(tag)))); + } else if (tagName.equals("null")) { + context.peek().addArgument(new ValueNode(null)); + } else { + System.err.println("unsupported tag: " + tag.getTagName()); + } + } + + + private static String dataBindingEncode(String value) { + return value.replaceAll("\\{", "\\\\{").replaceAll("\\}", "\\\\}"); + } + + + public CapturedObject processObject(Element objectTag, Stack<ContextNode> context, JAXXCapture capture) { + String className = objectTag.getAttribute("class"); + if (className.length() > 0) { + CapturedObject capturedObject = createCapturedObject(className, capture); + context.push(capturedObject); + NodeList children = objectTag.getChildNodes(); + String id = objectTag.getAttribute("id"); + if (id.length() == 0 || capture.getCapturedObjects().containsKey(id)) { + id = "Auto" + ++count; + } + assert !capture.getCapturedObjects().containsKey(id); + capture.getCapturedObjects().put(id, capturedObject); + capturedObject.setProperty("id", id); + // process object's name before anything else + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) child; + if (element.getTagName().equals(JAXXCompilerFinalizer.TYPE_VOID) && element.getAttribute(ATTRIBUTE_PROPERTY).equals("name")) { + evaluate(element, context, capture); + String name = capturedObject.getProperty("name"); + if (name != null && !capture.getCapturedObjects().containsKey(name)) { + capture.getCapturedObjects().put(name, capturedObject); + capturedObject.setProperty("id", name); + capturedObject.getProperties().remove("name"); + } + } + } + } + // process remaining children + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) child; + if (!JAXXCompilerFinalizer.TYPE_VOID.equals(element.getTagName()) || !element.getAttribute(ATTRIBUTE_PROPERTY).equals("name")) { + evaluate(element, context, capture); + } + } + } + assert context.peek() == capturedObject; + context.pop(); + + return capturedObject; + } else { + CapturedObject result = capture.getCapturedObjects().get(objectTag.getAttribute("idref")); + if (result == null) { + throw new RuntimeException("Internal error: could not find tag with id " + objectTag.getAttribute("idref")); + } + result.setInlineable(false); // we have at least two references to it, and so can't inline it + return result; + } + } + + + private static String xmlEncode(String src) { + return src.replaceAll("'", "&").replaceAll("<", "<"); + } + + + public String getXML(CapturedObject object, JAXXCapture capture) { + StringBuilder result = new StringBuilder(); + result.append('<'); + String className = object.getClassName(); + if (className.startsWith("javax.swing.")) { + className = className.substring("javax.swing.".length()); + } + result.append(className); + Map<String, String> properties = object.getProperties(); + for (Map.Entry<String, String> e : properties.entrySet()) { + result.append(' '); + result.append(e.getKey()); + result.append("='"); + result.append(xmlEncode(e.getValue())); + result.append('\''); + } + ContextNode[] arguments = object.getArguments(); + if (arguments != null && arguments.length > 0) { + result.append(" constructorParams='"); + for (int j = 0; j < arguments.length; j++) { + if (j != 0) { + result.append(", "); + } + result.append(capture.getJavaCode(arguments[j])); + } + result.append('\''); + } + boolean tagClosed = false; + + String children = getChildXML(object, capture); + String lineSeparator = JAXXCompiler.getLineSeparator(); + if (children != null && children.length() > 0) { + if (!tagClosed) { + tagClosed = true; + result.append('>'); + result.append(lineSeparator); + } + result.append(children); + } + + String script = object.getScriptCode(); + if (script != null && script.length() > 0) { + if (!tagClosed) { + tagClosed = true; + result.append('>'); + result.append(lineSeparator); + } + result.append(" <script>"); + result.append(lineSeparator); + result.append(JavaFileGenerator.indent(script, 4, false, lineSeparator)); + result.append(lineSeparator); + result.append(" </script>"); + result.append(lineSeparator); + } + if (tagClosed) { + result.append("</"); + result.append(className); + result.append('>'); + } else { + result.append("/>"); + } + return result.toString(); + } + + + protected String getChildXML(CapturedObject object, JAXXCapture capture) { + StringBuilder result = new StringBuilder(); + CapturedObject[] children = object.getChildren(); + String lineSeparator = JAXXCompiler.getLineSeparator(); + for (CapturedObject aChildren : children) { + if (!aChildren.isInlineable()) { + result.append(JavaFileGenerator.indent(aChildren.getXML(capture), 2, false, lineSeparator)); + result.append(lineSeparator); + } + } + return result.toString(); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/handlers/TableHandler.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/handlers/TableHandler.java new file mode 100644 index 0000000..0c28827 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/tools/jaxxcapture/handlers/TableHandler.java @@ -0,0 +1,36 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tools.jaxxcapture.handlers; + +import org.nuiton.jaxx.compiler.tools.jaxxcapture.CapturedObject; +import org.nuiton.jaxx.compiler.tools.jaxxcapture.JAXXCapture; + +public class TableHandler extends ObjectHandler { + + @Override + protected CapturedObject createCapturedObject(String className, JAXXCapture capture) { + CapturedObject result = new CapturedObject(this, "javax.swing.JPanel", capture); + result.setProperty("layout", "{new GridBagLayout()}"); + return result; + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/ColorConverter.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/ColorConverter.java new file mode 100644 index 0000000..c566e02 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/ColorConverter.java @@ -0,0 +1,60 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.types; + +import java.awt.Color; +import java.lang.reflect.Field; + +public class ColorConverter implements TypeConverter { + + @Override + public Class<?>[] getSupportedTypes() { + return new Class<?>[]{ + Color.class + }; + } + + @Override + public String getJavaCode(Object object) { + Color color = (Color) object; + return "new Color(" + color.getRed() + ", " + color.getGreen() + ", " + color.getBlue() + ")"; + } + + @Override + public Object convertFromString(String string, Class<?> type) { + if (!Color.class.equals(type)) { + throw new IllegalArgumentException("unsupported type: " + type); + } + if (string.length() == 7 && string.charAt(0) == '#') { + return new Color(Integer.parseInt(string.substring(1), 16)); + } + try { + Field color = Color.class.getField(string); + return color.get(null); + } catch (NoSuchFieldException e) { + throw new IllegalArgumentException("colors must be of the form #xxxxxx ('#' followed by six hexadecimal digits), or the name of a constant field in java.awt.Color (found: '" + string + "')"); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/GridBagConstraintsConverter.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/GridBagConstraintsConverter.java new file mode 100644 index 0000000..edebd44 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/GridBagConstraintsConverter.java @@ -0,0 +1,48 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.types; + +import java.awt.GridBagConstraints; + +public class GridBagConstraintsConverter implements TypeConverter { + + @Override + public Class<?>[] getSupportedTypes() { + return new Class<?>[]{ + GridBagConstraints.class + }; + } + + @Override + public String getJavaCode(Object object) { + GridBagConstraints g = (GridBagConstraints) object; + return "new GridBagConstraints(" + g.gridx + ", " + g.gridy + ", " + g.gridwidth + ", " + g.gridheight + ", " + + g.weightx + ", " + g.weighty + ", " + g.anchor + ", " + g.fill + ", " + + TypeManager.getJavaCode(g.insets) + ", " + g.ipadx + ", " + g.ipady + ")"; + } + + @Override + public Object convertFromString(String string, Class<?> type) { + throw new UnsupportedOperationException("GridBagConstraints must be represented using Java code"); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/InsetsConverter.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/InsetsConverter.java new file mode 100644 index 0000000..d9f1d95 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/InsetsConverter.java @@ -0,0 +1,61 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.types; + +import java.awt.Insets; +import java.util.StringTokenizer; + +public class InsetsConverter implements TypeConverter { + + @Override + public Class<?>[] getSupportedTypes() { + return new Class<?>[]{Insets.class}; + } + + @Override + public String getJavaCode(Object object) { + Insets insets = (Insets) object; + return "new Insets(" + insets.top + ", " + insets.left + ", " + insets.bottom + ", " + insets.right + ")"; + } + + @Override + public Object convertFromString(String string, Class<?> type) { + if (!Insets.class.equals(type)) { + throw new IllegalArgumentException("unsupported type: " + type); + } + StringTokenizer tokenizer = new StringTokenizer(string, ","); + int count = tokenizer.countTokens(); + if (count == 1) { + int i = Integer.parseInt(tokenizer.nextToken().trim()); + return new Insets(i, i, i, i); + } + if (count == 4) { + int[] insets = new int[count]; + for (int i = 0; tokenizer.hasMoreTokens(); i++) { + insets[i] = Integer.parseInt(tokenizer.nextToken().trim()); + } + return new Insets(insets[0], insets[1], insets[2], insets[3]); + } + throw new IllegalArgumentException("unable to convert string '" + string + "' to Insets"); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/KeyStrokeConverter.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/KeyStrokeConverter.java new file mode 100644 index 0000000..27a1c3e --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/KeyStrokeConverter.java @@ -0,0 +1,46 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.types; + +import javax.swing.KeyStroke; + +public class KeyStrokeConverter implements TypeConverter { + + @Override + public Class<?>[] getSupportedTypes() { + return new Class<?>[]{KeyStroke.class}; + } + + @Override + public String getJavaCode(Object object) { + return "KeyStroke.getKeyStroke(\"" + object.toString() + "\")"; + } + + @Override + public Object convertFromString(String string, Class<?> type) { + if (!KeyStroke.class.equals(type)) { + throw new IllegalArgumentException("unsupported type: " + type); + } + return KeyStroke.getKeyStroke(string); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/PrimitiveConverter.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/PrimitiveConverter.java new file mode 100644 index 0000000..fabe605 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/PrimitiveConverter.java @@ -0,0 +1,122 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.types; + +import org.nuiton.jaxx.compiler.JAXXCompiler; + +public class PrimitiveConverter implements TypeConverter { + + @Override + public Class<?>[] getSupportedTypes() { + + return new Class<?>[]{ + boolean.class, + Boolean.class, + byte.class, + Byte.class, + short.class, + Short.class, + int.class, + Integer.class, + long.class, + Long.class, + float.class, + Float.class, + double.class, + Double.class, + char.class, + Character.class, + String.class + }; + } + + @Override + public String getJavaCode(Object object) { + if (object instanceof Boolean) { + return String.valueOf(((Boolean) object).booleanValue()); + } + if (object instanceof Byte) { + return String.valueOf(((Byte) object).byteValue()); + } + if (object instanceof Short) { + return String.valueOf(((Short) object).shortValue()); + } + if (object instanceof Integer) { + return String.valueOf(((Integer) object).intValue()); + } + if (object instanceof Long) { + return String.valueOf(((Long) object).longValue()) + "L"; + } + if (object instanceof Float) { + return String.valueOf(((Float) object).floatValue()) + "F"; + } + if (object instanceof Double) { + return String.valueOf(((Double) object).doubleValue()); + } + if (object instanceof String) { + return '"' + JAXXCompiler.escapeJavaString((String) object) + '"'; + } + throw new IllegalArgumentException("unsupported object: " + object); + } + + @Override + public Object convertFromString(String string, Class<?> type) { + if (String.class.equals(type) || Object.class.equals(type) || type == null) { + return string; + } + if (int.class.equals(type) || Integer.class.equals(type)) { + return Integer.valueOf(string); + } + if (boolean.class.equals(type) || Boolean.class.equals(type)) { + if (string.toLowerCase().equals("true")) { + return Boolean.TRUE; + } + if (string.toLowerCase().equals("false")) { + return Boolean.FALSE; + } + throw new IllegalArgumentException("expected 'true' or 'false', found '" + string + "'"); + } + if (byte.class.equals(type) || Byte.class.equals(type)) { + return Byte.valueOf(string); + } + if (short.class.equals(type) || Short.class.equals(type)) { + return Short.valueOf(string); + } + if (long.class.equals(type) || Long.class.equals(type)) { + return Long.valueOf(string); + } + if (float.class.equals(type) || Float.class.equals(type)) { + return Float.valueOf(string); + } + if (double.class.equals(type) || Double.class.equals(type)) { + return Double.valueOf(string); + } + if (char.class.equals(type) || Character.class.equals(type)) { + if (string.length() == 1) { + return string.charAt(0); + } + throw new IllegalArgumentException("expected a single character, found '" + string + "'"); + } + throw new IllegalArgumentException("unsupported type: " + type); + } +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/TypeConverter.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/TypeConverter.java new file mode 100644 index 0000000..2851a05 --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/TypeConverter.java @@ -0,0 +1,32 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.types; + +public interface TypeConverter { + + Class<?>[] getSupportedTypes(); + + String getJavaCode(Object object); + + Object convertFromString(String string, Class<?> type); +} diff --git a/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/TypeManager.java b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/TypeManager.java new file mode 100644 index 0000000..aa93aec --- /dev/null +++ b/jaxx-compiler/src/main/java/org/nuiton/jaxx/compiler/types/TypeManager.java @@ -0,0 +1,126 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.types; + +import java.util.HashMap; +import java.util.Map; +import java.util.ServiceLoader; + +public class TypeManager { + + /** + * Dictionnary of converters loaded by the {@link ServiceLoader} mecanism + */ + private static Map<Class<?>, TypeConverter> converters; + + /** + * @return dictionnary of known converters + */ + public static Map<Class<?>, TypeConverter> getConverters() { + if (converters == null) { + converters = new HashMap<>(); + // load converters + ServiceLoader<TypeConverter> loader = + ServiceLoader.load(TypeConverter.class); + for (TypeConverter c : loader) { + // for each supported type, register the converter + for (Class<?> type : c.getSupportedTypes()) { + converters.put(type, c); + } + } + } + return converters; + } + + private TypeManager() { /* not instantiable */ } + + public static TypeConverter getTypeConverter(Class<?> type) { + return getConverters().get(type); + } + + public static String getJavaCode(Object object) { + if (object == null) { + return "null"; + } + TypeConverter converter = getTypeConverter(object.getClass()); + if (converter == null) { + throw new IllegalArgumentException("unsupported type: " + object.getClass()); + } + return converter.getJavaCode(object); + } + + public static Object convertFromString(String string, Class<?> type) { + TypeConverter converter = getTypeConverter(type); + if (converter == null) { + throw new IllegalArgumentException("unsupported type: " + type); + } + return converter.convertFromString(string, type); + } + + /** + * Convertit un nom de variable en nom de constante. + * + * @param variableName le nom de variable a convertir + * @return le nom de la constante à partir du nom de la variable + */ + public static String convertVariableNameToConstantName(String variableName) { + StringBuilder buffer = new StringBuilder(); + boolean lastCarIsUp = false; + char lastChar = '$'; + for (int i = 0, j = variableName.length(); i < j; i++) { + char c = variableName.charAt(i); + boolean carIsUp; + if (c == '!') { + buffer.append("NOT_"); + lastChar = '_'; + lastCarIsUp = true; + continue; + } + if (Character.isLetterOrDigit(c)) { + carIsUp = Character.isUpperCase(c); + } else { + carIsUp = false; + if (c != '$') { + // on remplace tous les caractères non standard par un _ + if (lastChar == '_' && c != '_') { + continue; + } + c = '_'; + } + } + + if (i > 0 && !lastCarIsUp && carIsUp) { + // ajout d'un _ + buffer.append('_'); + } + if (carIsUp) { + buffer.append(c); + } else { + buffer.append(Character.toUpperCase(c)); + } + lastCarIsUp = carIsUp || c == '$' || c == '_'; + lastChar = c; + } + return buffer.toString(); + } +} diff --git a/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.CompiledObjectDecorator b/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.CompiledObjectDecorator deleted file mode 100644 index 55f046a..0000000 --- a/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.CompiledObjectDecorator +++ /dev/null @@ -1,3 +0,0 @@ -jaxx.compiler.decorators.DefaultCompiledObjectDecorator -jaxx.compiler.decorators.BoxedCompiledObjectDecorator -jaxx.compiler.decorators.HelpRootCompiledObjectDecorator diff --git a/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.JAXXCompilerFinalizer b/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.JAXXCompilerFinalizer deleted file mode 100644 index abb8df4..0000000 --- a/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.JAXXCompilerFinalizer +++ /dev/null @@ -1,3 +0,0 @@ -jaxx.compiler.finalizers.DefaultFinalizer -jaxx.compiler.finalizers.SwingFinalizer -jaxx.compiler.finalizers.ValidatorFinalizer diff --git a/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.spi.Initializer b/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.spi.Initializer deleted file mode 100644 index 763ca46..0000000 --- a/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.spi.Initializer +++ /dev/null @@ -1 +0,0 @@ -jaxx.compiler.spi.DefaultInitializer \ No newline at end of file diff --git a/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.types.TypeConverter b/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.types.TypeConverter deleted file mode 100644 index 440367e..0000000 --- a/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.types.TypeConverter +++ /dev/null @@ -1,5 +0,0 @@ -jaxx.compiler.types.ColorConverter -jaxx.compiler.types.GridBagConstraintsConverter -jaxx.compiler.types.InsetsConverter -jaxx.compiler.types.KeyStrokeConverter -jaxx.compiler.types.PrimitiveConverter diff --git a/jaxx-compiler/src/main/resources/META-INF/services/org.nuiton.jaxx.compiler.CompiledObjectDecorator b/jaxx-compiler/src/main/resources/META-INF/services/org.nuiton.jaxx.compiler.CompiledObjectDecorator new file mode 100644 index 0000000..8f372c3 --- /dev/null +++ b/jaxx-compiler/src/main/resources/META-INF/services/org.nuiton.jaxx.compiler.CompiledObjectDecorator @@ -0,0 +1,3 @@ +org.nuiton.jaxx.compiler.decorators.DefaultCompiledObjectDecorator +org.nuiton.jaxx.compiler.decorators.BoxedCompiledObjectDecorator +org.nuiton.jaxx.compiler.decorators.HelpRootCompiledObjectDecorator diff --git a/jaxx-compiler/src/main/resources/META-INF/services/org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer b/jaxx-compiler/src/main/resources/META-INF/services/org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer new file mode 100644 index 0000000..1359878 --- /dev/null +++ b/jaxx-compiler/src/main/resources/META-INF/services/org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer @@ -0,0 +1,3 @@ +org.nuiton.jaxx.compiler.finalizers.DefaultFinalizer +org.nuiton.jaxx.compiler.finalizers.SwingFinalizer +org.nuiton.jaxx.compiler.finalizers.ValidatorFinalizer diff --git a/jaxx-compiler/src/main/resources/META-INF/services/org.nuiton.jaxx.compiler.spi.Initializer b/jaxx-compiler/src/main/resources/META-INF/services/org.nuiton.jaxx.compiler.spi.Initializer new file mode 100644 index 0000000..669f777 --- /dev/null +++ b/jaxx-compiler/src/main/resources/META-INF/services/org.nuiton.jaxx.compiler.spi.Initializer @@ -0,0 +1 @@ +org.nuiton.jaxx.compiler.spi.DefaultInitializer \ No newline at end of file diff --git a/jaxx-compiler/src/main/resources/META-INF/services/org.nuiton.jaxx.compiler.types.TypeConverter b/jaxx-compiler/src/main/resources/META-INF/services/org.nuiton.jaxx.compiler.types.TypeConverter new file mode 100644 index 0000000..4d3009a --- /dev/null +++ b/jaxx-compiler/src/main/resources/META-INF/services/org.nuiton.jaxx.compiler.types.TypeConverter @@ -0,0 +1,5 @@ +org.nuiton.jaxx.compiler.types.ColorConverter +org.nuiton.jaxx.compiler.types.GridBagConstraintsConverter +org.nuiton.jaxx.compiler.types.InsetsConverter +org.nuiton.jaxx.compiler.types.KeyStrokeConverter +org.nuiton.jaxx.compiler.types.PrimitiveConverter diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/beans/BeanIntoUtilTest.java b/jaxx-compiler/src/test/java/jaxx/compiler/beans/BeanIntoUtilTest.java deleted file mode 100644 index a33f606..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/beans/BeanIntoUtilTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.beans; - -import org.junit.Assert; -import org.junit.Test; - -import java.beans.Introspector; - -/** @author Tony Chemit - chemit@codelutin.com */ -public class BeanIntoUtilTest { - - @Test - public void testExtraBeanInfoPath() { - BeanInfoUtil.reset(); - String[] searchPath0 = Introspector.getBeanInfoSearchPath(); - - BeanInfoUtil.addJaxxBeanInfoPath("jaxx.runtime.swing"); - - String[] searchPath = Introspector.getBeanInfoSearchPath(); - Assert.assertEquals(searchPath0.length + 1, searchPath.length); - - BeanInfoUtil.reset(); - Assert.assertEquals(searchPath0.length, Introspector.getBeanInfoSearchPath().length); - - String packageName = getClass().getPackage().getName() + ".dummy"; - BeanInfoUtil.addJaxxBeanInfoPath("jaxx.beaninfos", packageName); - - searchPath = Introspector.getBeanInfoSearchPath(); - Assert.assertEquals(searchPath0.length + 2, searchPath.length); - Assert.assertEquals(packageName, searchPath[searchPath.length - 1]); - - BeanInfoUtil.reset(); - Assert.assertEquals(searchPath0.length, Introspector.getBeanInfoSearchPath().length); - } -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/binding/JavaParserUtilTest.java b/jaxx-compiler/src/test/java/jaxx/compiler/binding/JavaParserUtilTest.java deleted file mode 100644 index 4e596f0..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/binding/JavaParserUtilTest.java +++ /dev/null @@ -1,324 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.binding; - -import jaxx.compiler.java.parser.JavaParser; -import jaxx.compiler.java.parser.SimpleNode; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Assert; -import org.junit.Test; - -import java.io.StringReader; -import java.util.*; - -/** - * Created: 5 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - * - * Mise a jour: $Date$ par : - * $Author$ - */ -public class JavaParserUtilTest { - - /** - * Logger - */ - private static final Log log = LogFactory.getLog(JavaParserUtilTest.class); - - Map<SimpleNode, List<SimpleNode>> store = new LinkedHashMap<>(); - Map<SimpleNode, List<SimpleNode>> casts = new LinkedHashMap<>(); - List<SimpleNode> literals = new ArrayList<>(); - Set<String> requirements; - Iterator<SimpleNode> simpleNodeIterator; - Iterator<String> requirementsIterator; - SimpleNode node; - String source; - - @Test - public void testGetExpressionsWithLiterals() throws Exception { - - parseSourceAndGetExpressions("1", 1, 1); - assertNextNode(source, 0); - assertLiteralNode(0); - - parseSourceAndGetExpressions("true", 1, 1); - assertNextNode(source, 0); - assertLiteralNode(0); - - parseSourceAndGetExpressions("\"1\"", 1, 1); - assertNextNode(source, 0); - assertLiteralNode(0); - - parseSourceAndGetExpressions("\"1\" + \"2\"", 2, 2); - assertNextNode("\"1\"", 0); - assertLiteralNode(0); - assertNextNode("\"2\"", 0); - assertLiteralNode(1); - - parseSourceAndGetExpressions("1.1 + 2", 2, 2); - assertNextNode("1.1", 0); - assertLiteralNode(0); - assertNextNode("2", 0); - assertLiteralNode(1); - } - - @Test - public void testGetExpressionsWithNoLiterals() throws Exception { - - parseSourceAndGetExpressions("a", 0, 1); - assertNextNode(source, 0); - - parseSourceAndGetExpressions("a.getText()", 0, 1); - assertNextNode(source, 0); - - parseSourceAndGetExpressions("a.getText().getLength()", 0, 1); - assertNextNode(source, 0); - - parseSourceAndGetExpressions("getText()", 0, 1); - assertNextNode(source, 0); - - parseSourceAndGetExpressions("getText(a)", 0, 2); - assertNextNode(source, 1); - assertNextNode("a", 0); - - parseSourceAndGetExpressions("getText(a, b, c)", 0, 4); - assertNextNode(source, 3); - assertNextNode("a", 0); - assertNextNode("b", 0); - assertNextNode("c", 0); - - parseSourceAndGetExpressions("getText(a + b, c)", 0, 4); - assertNextNode(source, 3); - assertNextNode("a", 0); - assertNextNode("b", 0); - assertNextNode("c", 0); - - parseSourceAndGetExpressions("getText(a + b + c)", 0, 4); - assertNextNode(source, 3); - assertNextNode("a", 0); - assertNextNode("b", 0); - assertNextNode("c", 0); - - parseSourceAndGetExpressions("(Hum)a", 0, 1); - assertNextNode("a", 0); - - parseSourceAndGetExpressions("(Hum) a", 0, 1); - assertNextNode("a", 0); - - parseSourceAndGetExpressions("((Hum) a)", 0, 2); - assertNextNode(source, 1); - assertNextNode("a", 0); - - parseSourceAndGetExpressions("((Hum) a).getText()", 0, 2); - assertNextNode(source, 1); - assertNextNode("a", 0); - } - - @Test - public void testGetExpressions() throws Exception { - - parseSourceAndGetExpressions("getText(\"a\")", 1, 2); - assertNextNode(source, 1); - assertNextNode("\"a\"", 0); - assertLiteralNode(0); - - parseSourceAndGetExpressions("SwingUtil.getText(\"a\")", 1, 2); - assertNextNode(source, 1); - assertNextNode("\"a\"", 0); - assertLiteralNode(0); - - parseSourceAndGetExpressions("getText2() && getText(\"a.b\")", 1, 3); - assertNextNode("getText2()", 0); - assertNextNode("getText(\"a.b\")", 1); - assertNextNode("\"a.b\"", 0); - assertLiteralNode(0); - - parseSourceAndGetExpressions("SwingUtil.getText2() && getText(\"a.b\")", 1, 3); - assertNextNode("SwingUtil.getText2()", 0); - assertNextNode("getText(\"a.b\")", 1); - assertNextNode("\"a.b\"", 0); - assertLiteralNode(0); - - parseSourceAndGetExpressions("SwingUtil.getText2() && SwingUtil2.getText(\"a.b\")", 1, 3); - assertNextNode("SwingUtil.getText2()", 0); - assertNextNode("SwingUtil2.getText(\"a.b\")", 1); - assertNextNode("\"a.b\"", 0); - assertLiteralNode(0); - - parseSourceAndGetExpressions("SwingUtil.get().getText2() && SwingUtil2.getText(\"a.b\")", 1, 3); - assertNextNode("SwingUtil.get().getText2()", 0); - assertNextNode("SwingUtil2.getText(\"a.b\")", 1); - assertNextNode("\"a.b\"", 0); - assertLiteralNode(0); - } - - @Test - public void testGetMethodInvocationParameters() throws Exception { - getMethodInvocationParameters("a", null); - getMethodInvocationParameters("a(", null); - getMethodInvocationParameters("a( ", null); - getMethodInvocationParameters("a)", null); - getMethodInvocationParameters("a )", null); - getMethodInvocationParameters("a()", ""); - getMethodInvocationParameters("a( )", ""); - getMethodInvocationParameters("a( yo )", "yo"); - getMethodInvocationParameters("SwingUtil.a( yo )", "yo"); - getMethodInvocationParameters("SwingUtil.a( yo, ya )", "yo, ya"); - - } - - @Test - public void testGetRequirementsWithLiterals() throws Exception { - - parseSourceAndGetRequirements("1"); - - parseSourceAndGetRequirements("true"); - - parseSourceAndGetRequirements("\"1\""); - - parseSourceAndGetRequirements("\"1\" + \"2\""); - - parseSourceAndGetRequirements("1.1 + 2"); - } - - - @Test - public void testGetRequirementsWithNoLiterals() throws Exception { - - parseSourceAndGetRequirements("a"); - - parseSourceAndGetRequirements("a.getText()", "a"); - - parseSourceAndGetRequirements("a.getText().getLength()", "a", "a.getText()"); - - parseSourceAndGetRequirements("getText()"); - - parseSourceAndGetRequirements("getText(a)"); - - parseSourceAndGetRequirements("getText(a, b, c)"); - - parseSourceAndGetRequirements("getText(a + b, c)"); - - parseSourceAndGetRequirements("getText(a + b + c)"); - - parseSourceAndGetRequirements("(Hum)a"); - - parseSourceAndGetRequirements("((Hum)a)"); - - parseSourceAndGetRequirements("((Hum)a).getText()", "a"); - - parseSourceAndGetRequirements("((Hum)a).getB().getText()", "a", "a.getB()"); - - parseSourceAndGetRequirements("((Hum)a.getB()).getText()", "a", "a.getB()"); - } - - @Test - public void testGetRequirements() throws Exception { - - parseSourceAndGetRequirements("getText(\"a\")"); - - parseSourceAndGetRequirements("SwingUtil.getText(\"a\")", "SwingUtil"); - - parseSourceAndGetRequirements("getText2() && getText(\"a.b\")"); - - parseSourceAndGetRequirements("SwingUtil.getText2() && getText(\"a.b\")", "SwingUtil"); - - parseSourceAndGetRequirements("SwingUtil.getText2() && SwingUtil2.getText(\"a.b\")", "SwingUtil", "SwingUtil2"); - - parseSourceAndGetRequirements("SwingUtil.get().getText2() && SwingUtil2.getText(\"a.b\")", "SwingUtil2", "SwingUtil", "SwingUtil.get()"); - - } - - protected void parseSourceAndGetExpressions(String source, int expectedNbLiterals, int expectedNbExpressions) { - - // clean stores - literals.clear(); - - parseSource(source); - - Assert.assertEquals(expectedNbLiterals, literals.size()); - Assert.assertEquals(expectedNbExpressions, store.size()); - - simpleNodeIterator = store.keySet().iterator(); - } - - protected void parseSourceAndGetRequirements(String source, String... expected) { - - parseSource(source); - - requirements = JavaParserUtil.getRequired(store.keySet(), casts); - Assert.assertEquals(expected.length, requirements == null ? 0 : requirements.size()); - if (expected.length > 0) { - - requirementsIterator = requirements.iterator(); - for (String s : expected) { - Assert.assertTrue(requirementsIterator.hasNext()); - Assert.assertEquals(s, requirementsIterator.next()); - } - } - } - - protected void getMethodInvocationParameters(String code, String expected) { - String invocationParameters = JavaParserUtil.getMethodInvocationParameters(code); - Assert.assertEquals(expected, invocationParameters); - } - - protected void assertNextNode(String expectedText, int nbDep) { - - Assert.assertTrue(simpleNodeIterator.hasNext()); - node = simpleNodeIterator.next(); - Assert.assertNotNull(node); - Assert.assertEquals(expectedText, node.getText().trim()); - Assert.assertEquals(nbDep, store.get(node).size()); - } - - private void parseSource(String source) { - - this.source = source; - // clean stores - store.clear(); - literals.clear(); - casts.clear(); - - if (log.isDebugEnabled()) { - log.debug(source); - } - - JavaParser p; - SimpleNode node; - p = new JavaParser(new StringReader(source)); - while (!p.Line()) { - node = p.popNode(); - JavaParserUtil.getExpressions(node, store, literals, casts); - } - } - - protected void assertLiteralNode(int nbDep) { - Assert.assertNotNull(node); - Assert.assertTrue(nbDep <= literals.size()); - Assert.assertEquals(node, literals.get(nbDep)); - } - -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/java/JavaFieldTest.java b/jaxx-compiler/src/test/java/jaxx/compiler/java/JavaFieldTest.java deleted file mode 100644 index 2cf92f4..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/java/JavaFieldTest.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.java; - -import com.google.common.collect.Lists; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Assert; -import org.junit.Test; - -import java.lang.reflect.Modifier; -import java.util.Collections; -import java.util.EnumSet; -import java.util.List; - -/** - * Created: 3 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - * - * Mise a jour: $Date$ par : - * $Author$ - */ -public class JavaFieldTest { - /** Logger */ - private static final Log log = LogFactory.getLog(JavaFieldTest.class); - - @Test - public void testGetFieldOrderScope() { - - EnumSet<JavaField.FieldOrder> allConstants = EnumSet.allOf(JavaField.FieldOrder.class); - if (log.isDebugEnabled()) { - for (JavaField.FieldOrder allConstant : allConstants) { - log.debug("\n" + allConstant.getHeader()); - } - } - - EnumSet<JavaField.FieldOrder> constants; - - constants = JavaField.getFieldOrderScope(allConstants, Modifier.STATIC); - - Assert.assertEquals(4, constants.size()); - Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsBean)); - Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsOthers)); - Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsPublicBindings)); - Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsPrivateBindings)); - - constants = JavaField.getFieldOrderScope(allConstants, Modifier.PUBLIC); - - Assert.assertEquals(3, constants.size()); - Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsBean)); -// Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsOthers)); - Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsPublicBindings)); - Assert.assertTrue(constants.contains(JavaField.FieldOrder.publicFields)); - - constants = JavaField.getFieldOrderScope(allConstants, Modifier.PROTECTED); - - Assert.assertEquals(2, constants.size()); -// Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsOthers)); - Assert.assertTrue(constants.contains(JavaField.FieldOrder.protectedFields)); - Assert.assertTrue(constants.contains(JavaField.FieldOrder.internalFields)); - - - constants = JavaField.getFieldOrderScope(allConstants, Modifier.PRIVATE); - Assert.assertEquals(3, constants.size()); - Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsPrivateBindings)); -// Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsOthers)); - Assert.assertTrue(constants.contains(JavaField.FieldOrder.privateFields)); - Assert.assertTrue(constants.contains(JavaField.FieldOrder.internalFields)); - - } - - /** - * To test https://forge.nuiton.org/issues/2154. - * - * @since 2.5.1 - */ - @Test - public void testCompare() { - - String[] names = new String[]{ - "cf0", - "cf1", - "cf0O1", - "cf0A1", - "ct0O1", "ct0A1", - "cgett0", - "cgett1", "cgett0O1", - "cgett0A1", "cfile", "cgetfile", "t0", "t1", - "cmt0", "cmt1", "cmt0O1", "cmt0A1", "cmgett0", - "cmgett1", "cmgett0O1", "cmgett0A1", - "cMfile", "cMgetfile", - "Mt0", "Mt1", "cit0", "cit1", "cit0O1", "cit0A1", "cigett0", - "bindings" - }; - List<JavaField> theFileds = Lists.newArrayList(); - for (String name : names) { - JavaField field = new JavaField(Modifier.PROTECTED, "String", name, false); - theFileds.add(field); - } - Collections.sort(theFileds); - - } -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/java/JavaMethodTest.java b/jaxx-compiler/src/test/java/jaxx/compiler/java/JavaMethodTest.java deleted file mode 100644 index 60801bb..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/java/JavaMethodTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.java; - -import jaxx.compiler.java.JavaMethod.MethodOrder; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Assert; -import org.junit.Test; - -import java.lang.reflect.Modifier; -import java.util.EnumSet; - -/** - * @author Tony Chemit - chemit@codelutin.com - */ -public class JavaMethodTest { - /** - * Logger - */ - private static final Log log = LogFactory.getLog(JavaMethodTest.class); - - @Test - public void testGetMethodOrderScope() { - - EnumSet<MethodOrder> allConstants = EnumSet.allOf(MethodOrder.class); - if (log.isDebugEnabled()) { - for (MethodOrder allConstant : allConstants) { - log.debug("\n" + allConstant.getHeader()); - } - } - - EnumSet<MethodOrder> constants; - - constants = JavaMethod.getMethodOrderScope(allConstants, Modifier.STATIC); - - Assert.assertEquals(1, constants.size()); - Assert.assertTrue(constants.contains(MethodOrder.statics)); - - constants = JavaMethod.getMethodOrderScope(allConstants, Modifier.PUBLIC); - - Assert.assertEquals(8, constants.size()); - Assert.assertTrue(constants.contains(MethodOrder.constructors)); - Assert.assertTrue(constants.contains(MethodOrder.JAXXObject)); - Assert.assertTrue(constants.contains(MethodOrder.JAXXContext)); - Assert.assertTrue(constants.contains(MethodOrder.JAXXValidation)); - Assert.assertTrue(constants.contains(MethodOrder.events)); - Assert.assertTrue(constants.contains(MethodOrder.publicGetters)); - Assert.assertTrue(constants.contains(MethodOrder.publicSetters)); - Assert.assertTrue(constants.contains(MethodOrder.otherPublic)); - - constants = JavaMethod.getMethodOrderScope(allConstants, Modifier.PROTECTED); - - Assert.assertEquals(4, constants.size()); - Assert.assertTrue(constants.contains(MethodOrder.protectedGetters)); - Assert.assertTrue(constants.contains(MethodOrder.protecteds)); - Assert.assertTrue(constants.contains(MethodOrder.createMethod)); - Assert.assertTrue(constants.contains(MethodOrder.internalMethod)); - - constants = JavaMethod.getMethodOrderScope(allConstants, Modifier.PRIVATE); - Assert.assertEquals(3, constants.size()); - - Assert.assertTrue(constants.contains(MethodOrder.createMethod)); - Assert.assertTrue(constants.contains(MethodOrder.packageLocal)); - Assert.assertTrue(constants.contains(MethodOrder.privates)); - - } -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/java/parser/JavaParserTest.java b/jaxx-compiler/src/test/java/jaxx/compiler/java/parser/JavaParserTest.java deleted file mode 100644 index 429e255..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/java/parser/JavaParserTest.java +++ /dev/null @@ -1,128 +0,0 @@ -package jaxx.compiler.java.parser; - -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2015 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.compiler.CompilerException; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.MethodDescriptor; -import jaxx.compiler.reflect.resolvers.ClassDescriptorResolverFromJavaFile; -import org.junit.Assert; -import org.junit.Test; -import org.nuiton.util.FileUtil; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; - -/** - * Created on 4/12/15. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.24 - */ -public class JavaParserTest { - - public static final List<String> DUMMY_LIST = new ArrayList<>(); - public static final List<String> DUMMY_LIST2 = new ArrayList<>(); - - @Test - public void testParseClassButNotMethodBody() throws IOException, ClassNotFoundException, NoSuchMethodException { - - File file = new File("").getAbsoluteFile(); - Path rootSourceDirectory = file.toPath().resolve("src").resolve("test").resolve("java"); - - File thisClassJavaFile = new File(FileUtil.getFileFromFQN(rootSourceDirectory.toFile(), getClass().getPackage().getName()), getClass().getSimpleName() + ".java"); - - Assert.assertTrue("Could not find java file " + thisClassJavaFile, thisClassJavaFile.exists()); - - ClassDescriptorResolverFromJavaFile resolver = new ClassDescriptorResolverFromJavaFile(); - - ClassDescriptor yo = resolver.resolvDescriptor("yo", thisClassJavaFile.toURI().toURL()); - MethodDescriptor[] methodDescriptors = yo.getMethodDescriptors(); - Assert.assertTrue(methodDescriptors.length>3); - - { - MethodDescriptor method = yo.getMethodDescriptor("testParseClassButNotMethodBody"); - Assert.assertNotNull(method); - } - - { - MethodDescriptor method = yo.getMethodDescriptor("methodWithDiamondInside"); - Assert.assertNotNull(method); - } - - { - MethodDescriptor method = yo.getMethodDescriptor("methodWithTryResourceInside"); - Assert.assertNotNull(method); - } - - } - - - @Test - public void testParseClassAndMethodBody() throws IOException, ClassNotFoundException, NoSuchMethodException { - - File file = new File("").getAbsoluteFile(); - Path rootSourceDirectory = file.toPath().resolve("src").resolve("test").resolve("java"); - - File thisClassJavaFile = new File(FileUtil.getFileFromFQN(rootSourceDirectory.toFile(), getClass().getPackage().getName()), getClass().getSimpleName() + ".java"); - - Assert.assertTrue("Could not find java file " + thisClassJavaFile, thisClassJavaFile.exists()); - - ClassDescriptorResolverFromJavaFile resolver = new ClassDescriptorResolverFromJavaFile(true); - - try { - resolver.resolvDescriptor("yo", thisClassJavaFile.toURI().toURL()); - Assert.fail("Can't compile body method (there is some jdk7 syntaxes inside them)..."); - } catch (RuntimeException e) { - Assert.assertTrue(e.getCause() instanceof CompilerException); - } - - } - - public void methodWithDiamondInside() { - - System.out.println(new ArrayList<>()); - System.out.println(DUMMY_LIST); - System.out.println(DUMMY_LIST2); - - } - - public void methodWithTryResourceInside() { - - try (BufferedReader reader = Files.newBufferedReader(new File("").toPath(), Charset.forName("UTF-8"))) { - - System.out.println(reader); - } catch (IOException | RuntimeException e ) { - e.printStackTrace(); - } - - - } - -} \ No newline at end of file diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/ClassDescriptorTest.java b/jaxx-compiler/src/test/java/jaxx/compiler/reflect/ClassDescriptorTest.java deleted file mode 100644 index 00e3794..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/ClassDescriptorTest.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.reflect; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.Arrays; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -public class ClassDescriptorTest { - - @BeforeClass - public static void before() { - ClassDescriptorHelper.setShowLoading(true); - } - - @AfterClass - public static void after() { - ClassDescriptorHelper.setShowLoading(true); - } - - /*@Test - public void testGetClassDescriptor() throws Exception { - ClassDescriptorHelper.getClassDescriptor("jaxx.runtime.swing.navigation.tree.NavigationTreeModel.NavigationTreeNode"); - }*/ - @Test - public void testBuiltInClassName() throws ClassNotFoundException, NoSuchMethodException { - ClassDescriptor object = ClassDescriptorHelper.getClassDescriptor("java.lang.Object"); - MethodDescriptor toString = object.getMethodDescriptor("toString"); - assertEquals(toString.getName(), "toString"); - assertEquals(toString.getParameterTypes().length, 0); - - MethodDescriptor equals = object.getMethodDescriptor("equals", object); - assertEquals(equals.getName(), "equals"); - assertEquals(equals.getParameterTypes().length, 1); - assertEquals(equals.getParameterTypes()[0], object); - } - - @Test - public void testBuiltInClass() throws ClassNotFoundException, NoSuchMethodException { - ClassDescriptor object1 = ClassDescriptorHelper.getClassDescriptor("java.lang.Object"); - ClassDescriptor object2 = ClassDescriptorHelper.getClassDescriptor(Object.class); - assertEquals(object1, object2); - } - - @Test - public void testUserClassName() throws ClassNotFoundException, NoSuchMethodException { - ClassDescriptor me = ClassDescriptorHelper.getClassDescriptor(ClassDescriptorTest.class.getName(), getClass().getClassLoader()); - MethodDescriptor testUserClassName = me.getMethodDescriptor("testUserClassName"); - assertEquals(testUserClassName.getName(), "testUserClassName"); - assertEquals(testUserClassName.getParameterTypes().length, 0); - } - - @Test(expected = ClassNotFoundException.class) - public void testWrongCase() throws ClassNotFoundException { - ClassDescriptorHelper.getClassDescriptor("jaxx.junit.classdescriptortest", getClass().getClassLoader()); - } - - @Test - public void testArrays() throws ClassNotFoundException { - ClassDescriptor intArray = ClassDescriptorHelper.getClassDescriptor(int[].class); - assertNotNull(intArray); - ClassDescriptor objectArray = ClassDescriptorHelper.getClassDescriptor(Object[].class); - assertNotNull(objectArray); - } - - @Test - public void testConstructorFromClass() throws ClassNotFoundException, MalformedURLException { - String className = MyClass.class.getName(); - ClassDescriptor descriptor = ClassDescriptorHelper.getClassDescriptor(className); - assertNotNull(descriptor); - ClassDescriptorHelper.ResolverType resolverType = descriptor.getResolverType(); - - //FIXME-tchemit find out why ? (https://forge.nuiton.org/issues/2203) - // using jdk 7 VM Server it found a FILE instead of a CLASS ? Wonder why? - // Need to find out why -// assertEquals(ClassDescriptorHelper.ResolverType.JAVA_CLASS, resolverType); - assertTrue(Arrays.asList(ClassDescriptorHelper.ResolverType.JAVA_CLASS, ClassDescriptorHelper.ResolverType.JAVA_FILE).contains(resolverType)); - MethodDescriptor[] constructorDescriptors = descriptor.getConstructorDescriptors(); - assertNotNull(constructorDescriptors); - assertEquals(2, constructorDescriptors.length); - } - - @Test - public void testConstructorFromJavaFile() throws ClassNotFoundException, MalformedURLException { - String className = MyClass.class.getName(); - ClassLoader classLoader = getClass().getClassLoader(); - - - File testSourceDir = new File(getBasedir(), "src" + File.separator + "test" + File.separator + "java"); - - ClassLoader myClassLoader = new URLClassLoader(new URL[]{testSourceDir.toURI().toURL()}, classLoader); - - URL javaFileUrl = ClassDescriptorHelper.getURL(myClassLoader, className, "java"); - assertNotNull(javaFileUrl); - - ClassDescriptor descriptorFromFile = ClassDescriptorHelper.getClassDescriptor0( - ClassDescriptorHelper.ResolverType.JAVA_FILE, - className, - javaFileUrl, - myClassLoader - ); - assertNotNull(descriptorFromFile); - MethodDescriptor[] constructorDescriptorsfromFile = descriptorFromFile.getConstructorDescriptors(); - assertNotNull(constructorDescriptorsfromFile); - assertEquals(2, constructorDescriptorsfromFile.length); - } - - - static File basedir; - - public static File getBasedir() { - if (basedir == null) { - String tmp = System.getProperty("basedir"); - if (tmp == null) { - tmp = new File("").getAbsolutePath(); - } - basedir = new File(tmp); - - } - return basedir; - } - -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyAbstractClass.java b/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyAbstractClass.java deleted file mode 100644 index 4e7c82e..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyAbstractClass.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.reflect; - -/** - * To test parser on abstract class file. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public abstract class MyAbstractClass implements MyInterface { - - protected void myAbstractMethod() { - - } -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyChildClass.java b/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyChildClass.java deleted file mode 100644 index 7d5fcac..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyChildClass.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.reflect; - -/** - * A child class to test the bug https://forge.nuiton.org/issues/show/1470 - * - * To test if a child class obtains properties from his super class. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.4.2 - */ -public class MyChildClass extends MyClass implements Cloneable{ - - private static final long serialVersionUID = 2L; - - protected String childProperty; - - public String getChildProperty() { - return childProperty; - } - - public void setChildProperty(String childProperty) { - this.childProperty = childProperty; - } -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyChildClass2.java b/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyChildClass2.java deleted file mode 100644 index 61fad5f..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyChildClass2.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.reflect; - -/** - * To test the bug : https://forge.nuiton.org/issues/show/1442 - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.4.2 - */ -public class MyChildClass2 extends MyClass { - private static final long serialVersionUID = 1L; -} - -// This class will not be scanned! -class MyPackageClass { - -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyClass.java b/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyClass.java deleted file mode 100644 index 8f900ea..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyClass.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.reflect; - -import java.io.Serializable; - -/** - * To test inheritance. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class MyClass extends MyAbstractClass implements Serializable { - - private static final long serialVersionUID = 1L; - - private final String myPrivateStringField = "final"; - - protected String myProtectedStringField; - - public String myPublicStringField; - - public MyClass() { - } - - public MyClass(String myProtectedStringField, String myPublicStringField) { - this.myProtectedStringField = myProtectedStringField; - this.myPublicStringField = myPublicStringField; - } - - @Override - public void myMethod() { - } - - public String getMyPrivateStringField() { - return myPrivateStringField; - } - - public String getMyProtectedStringField() { - return myProtectedStringField; - } - - public String getMyPublicStringField() { - return myPublicStringField; - } -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyEnum.java b/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyEnum.java deleted file mode 100644 index a625e5b..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyEnum.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.reflect; - -import java.io.Serializable; - -/** - * Created: 4 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - * - * Mise a jour: $Date$ par : - * $Author$ - */ -public enum MyEnum implements Serializable, MyInterface { - - A, B; - - @Override - public void myMethod() { - } -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface.java b/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface.java deleted file mode 100644 index 11e198d..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.reflect; - -/** - * Simple interface to test. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public interface MyInterface { - - String MY_CONSTANT = "constant"; - - void myMethod(); -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface2.java b/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface2.java deleted file mode 100644 index 09248e9..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface2.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.reflect; - -import org.nuiton.config.ConfigOptionDef; - -/** - * Simple interface to test. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public interface MyInterface2 extends ConfigOptionDef { - - String MY_CONSTANT = "constant"; - - void myMethod(); -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface3.java b/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface3.java deleted file mode 100644 index d84ea50..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface3.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.reflect; - -import org.nuiton.config.ConfigOptionDef; - -/** - * Simple interface to test. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public interface MyInterface3 extends ConfigOptionDef, Iterable<MyInterface3> { - - String MY_CONSTANT = "constant"; - - void myMethod(); -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFileTest.java b/jaxx-compiler/src/test/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFileTest.java deleted file mode 100644 index 506fa21..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFileTest.java +++ /dev/null @@ -1,394 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.reflect.resolvers; - -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import jaxx.compiler.reflect.FieldDescriptor; -import jaxx.compiler.reflect.MyAbstractClass; -import jaxx.compiler.reflect.MyChildClass; -import jaxx.compiler.reflect.MyChildClass2; -import jaxx.compiler.reflect.MyClass; -import jaxx.compiler.reflect.MyEnum; -import jaxx.compiler.reflect.MyInterface; -import jaxx.compiler.reflect.MyInterface2; -import jaxx.compiler.reflect.MyInterface3; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.nuiton.config.ConfigOptionDef; -import org.nuiton.util.FileUtil; - -import java.io.File; -import java.io.Serializable; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.List; - -/** - * Tests the {@link ClassDescriptorResolverFromJavaFile} resolver. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.2 - */ -public class ClassDescriptorResolverFromJavaFileTest { - - /** log */ - protected static final Log log = - LogFactory.getLog(ClassDescriptorResolverFromJavaFileTest.class); - - - /** test source root directory */ - public static File testSourceRoot; - - @BeforeClass - public static void initBaseDir() { - // get maven env basedir - String basedir = System.getenv("basedir"); - if (basedir == null) { - - // says basedir is where we start tests. - basedir = new File("").getAbsolutePath(); - } - testSourceRoot = FileUtil.getFileFromPaths(new File(basedir), - "src", - "test", - "java"); - } - - protected ClassDescriptor getDescriptor(Class<?> klass) throws Exception { - - String javaFilePath = - klass.getName().replaceAll("\\.", File.separator) + ".java"; - File src = new File(testSourceRoot, javaFilePath); - Assert.assertTrue(src.exists()); - - if (log.isDebugEnabled()) { - log.debug("file to parse " + src); - } - - ClassDescriptorResolverFromJavaFile resolver = - new ClassDescriptorResolverFromJavaFile(); - - ClassDescriptor descriptor = - resolver.resolvDescriptor(klass.getName(), src.toURI().toURL()); - - Assert.assertNotNull(descriptor); - if (log.isDebugEnabled()) { - log.debug("loaded " + descriptor); - } - Assert.assertEquals(klass.getName(), descriptor.getName()); - return descriptor; - } - - @Test - public void parseClassDescriptorResolverFromJavaFileTest() throws Exception { - - ClassDescriptor descriptor = - getDescriptor(ClassDescriptorResolverFromJavaFileTest.class); - - assertInterfaces(descriptor); - assertSuperClass(descriptor, Object.class); - } - - - @Test - public void parseMyEnum() throws Exception { - - ClassDescriptor descriptor = getDescriptor(MyEnum.class); - - assertInterfaces(descriptor, Serializable.class, MyInterface.class); - assertInterfaces(descriptor, MyEnum.class.getInterfaces()); - assertSuperClass(descriptor, Enum.class); - - assertIsAssignableFrom( - descriptor, - Serializable.class, - MyInterface.class, - Enum.class - ); - } - - @Test - public void parseMyInterface() throws Exception { - - ClassDescriptor descriptor = getDescriptor(MyInterface.class); - - assertInterfaces(descriptor); - assertSuperClass(descriptor, null); - } - - @Test - public void parseMyInterface2() throws Exception { - - ClassDescriptor descriptor = getDescriptor(MyInterface2.class); - - assertInterfaces(descriptor, MyInterface2.class.getInterfaces()); - assertInterfaces(descriptor, ConfigOptionDef.class); - assertSuperClass(descriptor, null); - } - - - @Test - public void parseMyInterface3() throws Exception { - - ClassDescriptor descriptor = getDescriptor(MyInterface3.class); - - assertInterfaces(descriptor, MyInterface3.class.getInterfaces()); - assertInterfaces(descriptor, ConfigOptionDef.class, - Iterable.class); - assertSuperClass(descriptor, null); - } - - @Test - public void parseMyAbstractClass() throws Exception { - - ClassDescriptor descriptor = getDescriptor(MyAbstractClass.class); - - assertInterfaces(descriptor, MyAbstractClass.class.getInterfaces()); - assertInterfaces(descriptor, MyInterface.class); - assertSuperClass(descriptor, Object.class); - assertIsAssignableFrom(descriptor, MyInterface.class, Object.class); - } - - @Test - public void parseMyClass() throws Exception { - - ClassDescriptor descriptor = getDescriptor(MyClass.class); - - assertInterfaces(descriptor, MyClass.class.getInterfaces()); - assertInterfaces(descriptor, Serializable.class); - assertSuperClass(descriptor, MyAbstractClass.class); - assertIsAssignableFrom(descriptor, - Serializable.class, - MyInterface.class, - MyAbstractClass.class - ); - - assertDeclaredField( - descriptor, - "serialVersionUID", - long.class, - Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC - ); - - assertDeclaredField( - descriptor, - "myPrivateStringField", - String.class, - Modifier.PRIVATE | Modifier.FINAL - ); - - assertDeclaredField( - descriptor, - "myProtectedStringField", - String.class, - Modifier.PROTECTED - ); - - assertField( - descriptor, - "myPublicStringField", - String.class, - Modifier.PUBLIC - ); - } - - @Test - public void parseMyChildClass() throws Exception { - - ClassDescriptor descriptor = getDescriptor(MyChildClass.class); - - assertInterfaces(descriptor, MyChildClass.class.getInterfaces()); - assertInterfaces(descriptor, Cloneable.class); - assertSuperClass(descriptor, MyClass.class); - assertIsAssignableFrom(descriptor, - Serializable.class, - MyInterface.class, - MyAbstractClass.class, - MyClass.class - ); - - assertDeclaredField( - descriptor, - "serialVersionUID", - long.class, - Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC - ); - - assertDeclaredField( - descriptor, - "myPrivateStringField", - String.class, - Modifier.PRIVATE | Modifier.FINAL - ); - - assertDeclaredField( - descriptor, - "myProtectedStringField", - String.class, - Modifier.PROTECTED - ); - - assertDeclaredField( - descriptor, - "childProperty", - String.class, - Modifier.PROTECTED - ); - - assertField( - descriptor, - "myPublicStringField", - String.class, - Modifier.PUBLIC - ); - - } - - @Test - public void parseMyChildClass2() throws Exception { - - ClassDescriptor descriptor = getDescriptor(MyChildClass2.class); - - assertInterfaces(descriptor, MyChildClass2.class.getInterfaces()); - assertSuperClass(descriptor, MyClass.class); - assertIsAssignableFrom(descriptor, - Serializable.class, - MyInterface.class, - MyAbstractClass.class, - MyClass.class - ); - - assertDeclaredField( - descriptor, - "serialVersionUID", - long.class, - Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC - ); - - assertDeclaredField( - descriptor, - "myPrivateStringField", - String.class, - Modifier.PRIVATE | Modifier.FINAL - ); - - assertDeclaredField( - descriptor, - "myProtectedStringField", - String.class, - Modifier.PROTECTED - ); - - assertField( - descriptor, - "myPublicStringField", - String.class, - Modifier.PUBLIC - ); - - } - - public static void assertField(ClassDescriptor descriptor, - String fieldName, - Class<?> fieldType, - int fieldModifiers) throws NoSuchFieldException { - FieldDescriptor fieldDescriptor = - descriptor.getFieldDescriptor(fieldName); - Assert.assertNotNull(fieldDescriptor); - ClassDescriptor type = fieldDescriptor.getType(); - Assert.assertNotNull(type); - Assert.assertEquals(fieldType.getName(), type.getName()); - int modifiers = fieldDescriptor.getModifiers(); - Assert.assertEquals(fieldModifiers, modifiers); - } - - public static void assertDeclaredField(ClassDescriptor descriptor, - String fieldName, - Class<?> fieldType, - int fieldModifiers) throws NoSuchFieldException { - FieldDescriptor fieldDescriptor = - descriptor.getDeclaredFieldDescriptor(fieldName); - Assert.assertNotNull(fieldDescriptor); - ClassDescriptor type = fieldDescriptor.getType(); - Assert.assertNotNull(type); - Assert.assertEquals(fieldType.getName(), type.getName()); - int modifiers = fieldDescriptor.getModifiers(); - Assert.assertEquals(fieldModifiers, modifiers); - } - - - public static void assertIsAssignableFrom(ClassDescriptor descriptor, - Class<?>... interfaces) { - - for (Class<?> anInterface : interfaces) { - ClassDescriptor descriptor2 = - ClassDescriptorHelper.getClassDescriptor(anInterface); - Assert.assertNotNull(descriptor2); - boolean value = descriptor2.isAssignableFrom(descriptor); - Assert.assertTrue( - anInterface + " should be assignable from " + descriptor, - value - ); - } - } - - public static void assertInterfaces(ClassDescriptor descriptor, - Class<?>... interfaces) { - ClassDescriptor[] descriptors = descriptor.getInterfaces(); - Assert.assertEquals(interfaces.length, descriptors.length); - - List<String> doFind = new ArrayList<>(); - for (Class<?> anInterface : interfaces) { - doFind.add(anInterface.getName()); - } - - for (ClassDescriptor descriptor1 : descriptors) { - String name = descriptor1.getName(); - Assert.assertTrue(doFind.contains(name)); - doFind.remove(name); - } - Assert.assertTrue( - "The follwing interfaces were not find found : " + doFind, - doFind.isEmpty() - ); - } - - public static void assertSuperClass(ClassDescriptor descriptor, - Class<?> superClass) { - ClassDescriptor superDescriptor = descriptor.getSuperclass(); - if (superClass == null) { - Assert.assertNull( - "Should be null but was " + superDescriptor, - superDescriptor - ); - } else { - Assert.assertNotNull(superDescriptor); - Assert.assertEquals(superClass.getName(), superDescriptor.getName()); - } - - } - -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/tags/TagManagerTest.java b/jaxx-compiler/src/test/java/jaxx/compiler/tags/TagManagerTest.java deleted file mode 100644 index c01c7f2..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/tags/TagManagerTest.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.tags; - -import jaxx.compiler.CompilerConfiguration; -import jaxx.compiler.DefaultCompilerConfiguration; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXFactory; -import jaxx.compiler.reflect.ClassDescriptor; -import jaxx.compiler.reflect.ClassDescriptorHelper; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import javax.swing.JPopupMenu; -import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; - -public class TagManagerTest { - - protected static CompilerConfiguration configuration; - - protected JAXXCompiler compiler; - - public static class TestHandler extends DefaultObjectHandler { - - public TestHandler(ClassDescriptor beanClass) { - super(beanClass); - } - } - - @BeforeClass - public static void init() throws Exception { - if (configuration == null) { - configuration = new DefaultCompilerConfiguration(); - } -// TagManager.reset(); - JAXXFactory.setConfiguration(configuration); - JAXXFactory.initFactory(); - - } - - @Before - public void setUp() { - JAXXFactory.newDummyEngine(); - compiler = JAXXFactory.newDummyCompiler(JAXXCompiler.class.getClassLoader()); -// compiler = new JAXXCompiler(JAXXCompiler.class.getClassLoader()); - compiler.addImport("javax.swing.*"); - - } - - @Test - public void testRegisterBean() { - TagManager.registerBean(ClassDescriptorHelper.getClassDescriptor(InputStream.class), TestHandler.class); - - Assert.assertTrue(TagManager.getTagHandler(ClassDescriptorHelper.getClassDescriptor(InputStream.class)) instanceof TestHandler); - Assert.assertTrue(TagManager.getTagHandler(ClassDescriptorHelper.getClassDescriptor(FileInputStream.class)) instanceof TestHandler); - } - - @Test - public void testRegisterDefaultNamespace() { - - TagManager.registerBean(ClassDescriptorHelper.getClassDescriptor(OutputStream.class), TestHandler.class); - - TagManager.registerDefaultNamespace("OutputStream", "java.io.*"); - Assert.assertTrue("Could not find handler for OutputStream despite default namespace", TagManager.getTagHandler(null, "OutputStream", compiler) instanceof TestHandler); - - PrintStream oldErr = System.err; - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - System.setErr(new PrintStream(buffer)); - TagManager.registerDefaultNamespace("OutputStream", "java.dummy.*"); - Assert.assertNull("Found handler for OutputStream despite ambiguous default namespace", TagManager.getTagHandler(null, "OutputStream", compiler)); - System.setErr(oldErr); - Assert.assertTrue("No errors were produced with an ambiguous default namespace", buffer.size() > 0); - Assert.assertTrue(buffer.size() > 0); - } - - @Test - public void testResolveClassName() { - Assert.assertEquals("Could not resolve class name 'Object'", TagManager.resolveClassName("Object", compiler), "java.lang.Object"); - Assert.assertEquals("Could not resolve class name 'java.lang.Object'", TagManager.resolveClassName("java.lang.Object", compiler), "java.lang.Object"); - Assert.assertNull("Unexpectedly resolved class name 'java.awt.Object'", TagManager.resolveClassName("java.awt.Object", compiler)); - } - - @Test - public void testPackages() { - Assert.assertNull("Unexpectedly found handler for java.awt.JButton", TagManager.getTagHandler(null, "java.awt.JButton", compiler)); - Assert.assertNotNull("Did not find handler for JButton with default namespace of java.awt.*", TagManager.getTagHandler("java.awt.*", "JButton", compiler)); - Assert.assertNull("Unexpectedly found handler for java.awt.*:JButton", TagManager.getTagHandler("java.awt.*", "JButton", true, compiler)); - Assert.assertNotNull("Did not find handler for javax.swing.JButton", TagManager.getTagHandler(null, "javax.swing.JButton", compiler)); - Assert.assertNotNull("Did not find handler for JButton with default namespace of java.swing.*", TagManager.getTagHandler("java.swing.*", "JButton", compiler)); - Assert.assertNotNull("Did not find handler for javax.swing.*:JButton", TagManager.getTagHandler("javax.swing.*", "JButton", true, compiler)); - } - - @Test - public void testImport() throws Exception { - Assert.assertNull("Found handler for ActionListener despite no java.awt.event.* import", TagManager.getTagHandler(null, "ActionListener", compiler)); - - compiler.addImport("java.awt.event.*"); - - Assert.assertNotNull("Did not find ActionListener with java.awt.event.* import", TagManager.getTagHandler(null, "ActionListener", compiler)); - } - - @Test - public void testAmbiguousImport() throws Exception { - compiler.addImport("java.sql.*"); - Assert.assertNotNull("Did not find java.sql.Date with only java.sql.* imported", TagManager.getTagHandler(null, "Date", compiler)); - - PrintStream oldErr = System.err; - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - System.setErr(new PrintStream(buffer)); - compiler.addImport("java.util.*"); - init(); - Assert.assertNull("Still found a handler for Date with an ambiguous import", TagManager.getTagHandler(null, "Date", compiler)); - System.setErr(oldErr); - Assert.assertTrue("No errors were produced with an ambiguous import", buffer.size() > 0); - - compiler.addImport("java.util.Date"); - Assert.assertNotNull("Did not find java.util.Date with a disambiguating import", TagManager.getTagHandler(null, "Date", compiler)); - } - - @Test - public void testInnerClass() { - TagHandler handler = TagManager.getTagHandler(null, "JPopupMenu.Separator", compiler); - Assert.assertTrue("Unable to resolve tag <JPopupMenu.Separator>", handler instanceof DefaultComponentHandler); - Assert.assertTrue(((DefaultComponentHandler) handler).getBeanClass().getName().equals(JPopupMenu.Separator.class.getName())); - - handler = TagManager.getTagHandler(null, "javax.swing.JPopupMenu.Separator", compiler); - Assert.assertTrue("Unable to resolve tag <javax.swing.JPopupMenu.Separator>", handler instanceof DefaultComponentHandler); - Assert.assertTrue(((DefaultComponentHandler) handler).getBeanClass().getName().equals(JPopupMenu.Separator.class.getName())); - } - - @Test - public void testWrongCase() { - Assert.assertNull("Unexpectedly found handler for 'object'", TagManager.getTagHandler(null, "object", compiler)); - Assert.assertNull("Unexpectedly found handler for 'tagmanagertest'", TagManager.getTagHandler(null, "tagmanagertest", compiler)); - } - - @Test - public void testAliasing() { - Assert.assertEquals("ButtonGroup is not aliased to jaxx.runtime.swing.JAXXButtonGroup", "jaxx.runtime.swing.JAXXButtonGroup", TagManager.resolveClassName("ButtonGroup", compiler)); - Assert.assertEquals("javax.swing.ButtonGroup is not aliased to jaxx.runtime.swing.JAXXButtonGroup", "jaxx.runtime.swing.JAXXButtonGroup", TagManager.resolveClassName("javax.swing.ButtonGroup", compiler)); - } -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/types/ColorConverterTest.java b/jaxx-compiler/src/test/java/jaxx/compiler/types/ColorConverterTest.java deleted file mode 100644 index 75377d4..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/types/ColorConverterTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.types; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.awt.*; - -public class ColorConverterTest { - - ColorConverter converter; - - @Before - public void setUp() { - converter = new ColorConverter(); - } - - @Test - public void testHexValue() { - Color value = (Color) converter.convertFromString("#3000FF", Color.class); - Assert.assertEquals(value, new Color(48, 0, 255)); - } - - @Test - public void testUpperCaseConstant() { - Color value = (Color) converter.convertFromString("RED", Color.class); - Assert.assertEquals(value, Color.RED); - } - - @Test - public void testLowerCaseConstant() { - Color value = (Color) converter.convertFromString("blue", Color.class); - Assert.assertEquals(value, Color.blue); - } - - @Test(expected = IllegalArgumentException.class) - public void testMissingHash() { - converter.convertFromString("ABCDEF", Color.class); - } - - @Test(expected = IllegalArgumentException.class) - public void testInvalidNumber() { - converter.convertFromString("#ABCDEG", Color.class); - } - - @Test(expected = IllegalArgumentException.class) - public void testInvalidConstant() { - converter.convertFromString("rEd", Color.class); - } -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/types/InsetsConverterTest.java b/jaxx-compiler/src/test/java/jaxx/compiler/types/InsetsConverterTest.java deleted file mode 100644 index 2fdcb71..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/types/InsetsConverterTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.types; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.awt.Insets; - -public class InsetsConverterTest { - - InsetsConverter converter; - - @Before - public void setUp() { - converter = new InsetsConverter(); - } - - @Test - public void testSingleValue() { - Insets value = (Insets) converter.convertFromString("3", Insets.class); - Assert.assertEquals(value, new Insets(3, 3, 3, 3)); - } - - @Test - public void testFourValues() { - Insets value = (Insets) converter.convertFromString("3, 0, 12, 1000000", Insets.class); - Assert.assertEquals(value, new Insets(3, 0, 12, 1000000)); - } - - @Test(expected = IllegalArgumentException.class) - public void testTwoValues() { - converter.convertFromString("0, 4", Insets.class); - } - - @Test(expected = IllegalArgumentException.class) - public void testThreeValues() { - converter.convertFromString("0, 4, 9", Insets.class); - } - - @Test(expected = IllegalArgumentException.class) - public void testInvalidNumber() { - converter.convertFromString("0, 4, 9, A", Insets.class); - } - - @Test(expected = IllegalArgumentException.class) - public void testBadFormatting() { - converter.convertFromString("0 - 1 - 2 - 3", Insets.class); - } -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/types/PrimitiveConverterTest.java b/jaxx-compiler/src/test/java/jaxx/compiler/types/PrimitiveConverterTest.java deleted file mode 100644 index 1f01b05..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/types/PrimitiveConverterTest.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.compiler.types; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class PrimitiveConverterTest { - - PrimitiveConverter converter; - - - @Before - public void setUp() { - converter = new PrimitiveConverter(); - } - - @Test - public void testBoolean() { - Boolean value = (Boolean) converter.convertFromString("true", Boolean.class); - Assert.assertTrue(value); - - value = (Boolean) converter.convertFromString("false", Boolean.class); - Assert.assertFalse(value); - - } - - @Test(expected = IllegalArgumentException.class) - public void testBoolean2() { - converter.convertFromString("yes", Boolean.class); - } - - @Test - public void testByte() { - Byte value = (Byte) converter.convertFromString(String.valueOf(Byte.MAX_VALUE), Byte.class); - Assert.assertEquals(value.byteValue(), Byte.MAX_VALUE); - - } - - @Test(expected = IllegalArgumentException.class) - public void testByte2() { - - converter.convertFromString(String.valueOf(1 + Byte.MAX_VALUE), Byte.class); - } - - @Test - public void testShort() { - Short value = (Short) converter.convertFromString(String.valueOf(Short.MAX_VALUE), Short.class); - Assert.assertEquals(value.shortValue(), Short.MAX_VALUE); - - - } - - @Test(expected = IllegalArgumentException.class) - public void testShort2() { - - converter.convertFromString(String.valueOf(1 + Short.MAX_VALUE), Short.class); - } - - @Test - public void testInteger() { - Integer value = (Integer) converter.convertFromString(String.valueOf(Integer.MAX_VALUE), Integer.class); - Assert.assertEquals(value.intValue(), Integer.MAX_VALUE); - } - - @Test(expected = IllegalArgumentException.class) - public void testInteger2() { - - converter.convertFromString(String.valueOf(1L + Integer.MAX_VALUE), Integer.class); - } - - @Test - public void testLong() { - Long value = (Long) converter.convertFromString(String.valueOf(Long.MAX_VALUE), Long.class); - Assert.assertEquals(value.longValue(), Long.MAX_VALUE); - } - - @Test - public void testFloat() { - Float value = (Float) converter.convertFromString("3.1415", Float.class); - Assert.assertTrue(value == 3.1415f); - } - - @Test - public void testDouble() { - Double value = (Double) converter.convertFromString("3.1415", Double.class); - Assert.assertTrue(value == 3.1415); - } - - @Test - public void testCharacter() { - Character value = (Character) converter.convertFromString("A", Character.class); - Assert.assertEquals(value.charValue(), 'A'); - } - - @Test(expected = IllegalArgumentException.class) - public void testCharacter2() { - - converter.convertFromString("12", Character.class); - - } - - @Test(expected = IllegalArgumentException.class) - public void testCharacter3() { - converter.convertFromString("", Character.class); - } - - @Test - public void testString() { - String value = (String) converter.convertFromString("Test", String.class); - Assert.assertEquals(value, "Test"); - } -} diff --git a/jaxx-compiler/src/test/java/jaxx/compiler/types/TypeManagerTest.java b/jaxx-compiler/src/test/java/jaxx/compiler/types/TypeManagerTest.java deleted file mode 100644 index 9282456..0000000 --- a/jaxx-compiler/src/test/java/jaxx/compiler/types/TypeManagerTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * #%L - * JAXX :: Compiler - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.compiler.types; - -import org.junit.Assert; -import org.junit.Test; - -/** - * Created: 29 nov. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - * - * Mise a jour: $Date$ par : - * $Author$ - */ -public class TypeManagerTest { - - @Test - public void testHexValue() { - - String actual; - String expected; - - actual = TypeManager.convertVariableNameToConstantName("azerty"); - expected = "AZERTY"; - Assert.assertEquals(expected, actual); - - actual = TypeManager.convertVariableNameToConstantName("azertyQwerty"); - expected = "AZERTY_QWERTY"; - Assert.assertEquals(expected, actual); - - actual = TypeManager.convertVariableNameToConstantName("1azertyQwerty"); - expected = "1AZERTY_QWERTY"; - Assert.assertEquals(expected, actual); - - actual = TypeManager.convertVariableNameToConstantName("$1azertyQwerty"); - expected = "$1AZERTY_QWERTY"; - Assert.assertEquals(expected, actual); - - actual = TypeManager.convertVariableNameToConstantName("binding_$hum"); - expected = "BINDING_$HUM"; - Assert.assertEquals(expected, actual); - - actual = TypeManager.convertVariableNameToConstantName("BINding_$hum"); - expected = "BINDING_$HUM"; - Assert.assertEquals(expected, actual); - - actual = TypeManager.convertVariableNameToConstantName("BINding_$Hum"); - expected = "BINDING_$HUM"; - Assert.assertEquals(expected, actual); - - actual = TypeManager.convertVariableNameToConstantName("!BINding_$Hum"); - expected = "NOT_BINDING_$HUM"; - Assert.assertEquals(expected, actual); - } - -} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/beans/BeanIntoUtilTest.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/beans/BeanIntoUtilTest.java new file mode 100644 index 0000000..3307426 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/beans/BeanIntoUtilTest.java @@ -0,0 +1,56 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.beans; + +import org.junit.Assert; +import org.junit.Test; + +import java.beans.Introspector; + +/** @author Tony Chemit - chemit@codelutin.com */ +public class BeanIntoUtilTest { + + @Test + public void testExtraBeanInfoPath() { + BeanInfoUtil.reset(); + String[] searchPath0 = Introspector.getBeanInfoSearchPath(); + + BeanInfoUtil.addJaxxBeanInfoPath("org.nuiton.jaxx.runtime.swing"); + + String[] searchPath = Introspector.getBeanInfoSearchPath(); + Assert.assertEquals(searchPath0.length + 1, searchPath.length); + + BeanInfoUtil.reset(); + Assert.assertEquals(searchPath0.length, Introspector.getBeanInfoSearchPath().length); + + String packageName = getClass().getPackage().getName() + ".dummy"; + BeanInfoUtil.addJaxxBeanInfoPath("jaxx.beaninfos", packageName); + + searchPath = Introspector.getBeanInfoSearchPath(); + Assert.assertEquals(searchPath0.length + 2, searchPath.length); + Assert.assertEquals(packageName, searchPath[searchPath.length - 1]); + + BeanInfoUtil.reset(); + Assert.assertEquals(searchPath0.length, Introspector.getBeanInfoSearchPath().length); + } +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/binding/JavaParserUtilTest.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/binding/JavaParserUtilTest.java new file mode 100644 index 0000000..b29bd25 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/binding/JavaParserUtilTest.java @@ -0,0 +1,324 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.binding; + +import org.nuiton.jaxx.compiler.java.parser.JavaParser; +import org.nuiton.jaxx.compiler.java.parser.SimpleNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.io.StringReader; +import java.util.*; + +/** + * Created: 5 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + * + * Mise a jour: $Date$ par : + * $Author$ + */ +public class JavaParserUtilTest { + + /** + * Logger + */ + private static final Log log = LogFactory.getLog(JavaParserUtilTest.class); + + Map<SimpleNode, List<SimpleNode>> store = new LinkedHashMap<>(); + Map<SimpleNode, List<SimpleNode>> casts = new LinkedHashMap<>(); + List<SimpleNode> literals = new ArrayList<>(); + Set<String> requirements; + Iterator<SimpleNode> simpleNodeIterator; + Iterator<String> requirementsIterator; + SimpleNode node; + String source; + + @Test + public void testGetExpressionsWithLiterals() throws Exception { + + parseSourceAndGetExpressions("1", 1, 1); + assertNextNode(source, 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("true", 1, 1); + assertNextNode(source, 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("\"1\"", 1, 1); + assertNextNode(source, 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("\"1\" + \"2\"", 2, 2); + assertNextNode("\"1\"", 0); + assertLiteralNode(0); + assertNextNode("\"2\"", 0); + assertLiteralNode(1); + + parseSourceAndGetExpressions("1.1 + 2", 2, 2); + assertNextNode("1.1", 0); + assertLiteralNode(0); + assertNextNode("2", 0); + assertLiteralNode(1); + } + + @Test + public void testGetExpressionsWithNoLiterals() throws Exception { + + parseSourceAndGetExpressions("a", 0, 1); + assertNextNode(source, 0); + + parseSourceAndGetExpressions("a.getText()", 0, 1); + assertNextNode(source, 0); + + parseSourceAndGetExpressions("a.getText().getLength()", 0, 1); + assertNextNode(source, 0); + + parseSourceAndGetExpressions("getText()", 0, 1); + assertNextNode(source, 0); + + parseSourceAndGetExpressions("getText(a)", 0, 2); + assertNextNode(source, 1); + assertNextNode("a", 0); + + parseSourceAndGetExpressions("getText(a, b, c)", 0, 4); + assertNextNode(source, 3); + assertNextNode("a", 0); + assertNextNode("b", 0); + assertNextNode("c", 0); + + parseSourceAndGetExpressions("getText(a + b, c)", 0, 4); + assertNextNode(source, 3); + assertNextNode("a", 0); + assertNextNode("b", 0); + assertNextNode("c", 0); + + parseSourceAndGetExpressions("getText(a + b + c)", 0, 4); + assertNextNode(source, 3); + assertNextNode("a", 0); + assertNextNode("b", 0); + assertNextNode("c", 0); + + parseSourceAndGetExpressions("(Hum)a", 0, 1); + assertNextNode("a", 0); + + parseSourceAndGetExpressions("(Hum) a", 0, 1); + assertNextNode("a", 0); + + parseSourceAndGetExpressions("((Hum) a)", 0, 2); + assertNextNode(source, 1); + assertNextNode("a", 0); + + parseSourceAndGetExpressions("((Hum) a).getText()", 0, 2); + assertNextNode(source, 1); + assertNextNode("a", 0); + } + + @Test + public void testGetExpressions() throws Exception { + + parseSourceAndGetExpressions("getText(\"a\")", 1, 2); + assertNextNode(source, 1); + assertNextNode("\"a\"", 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("SwingUtil.getText(\"a\")", 1, 2); + assertNextNode(source, 1); + assertNextNode("\"a\"", 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("getText2() && getText(\"a.b\")", 1, 3); + assertNextNode("getText2()", 0); + assertNextNode("getText(\"a.b\")", 1); + assertNextNode("\"a.b\"", 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("SwingUtil.getText2() && getText(\"a.b\")", 1, 3); + assertNextNode("SwingUtil.getText2()", 0); + assertNextNode("getText(\"a.b\")", 1); + assertNextNode("\"a.b\"", 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("SwingUtil.getText2() && SwingUtil2.getText(\"a.b\")", 1, 3); + assertNextNode("SwingUtil.getText2()", 0); + assertNextNode("SwingUtil2.getText(\"a.b\")", 1); + assertNextNode("\"a.b\"", 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("SwingUtil.get().getText2() && SwingUtil2.getText(\"a.b\")", 1, 3); + assertNextNode("SwingUtil.get().getText2()", 0); + assertNextNode("SwingUtil2.getText(\"a.b\")", 1); + assertNextNode("\"a.b\"", 0); + assertLiteralNode(0); + } + + @Test + public void testGetMethodInvocationParameters() throws Exception { + getMethodInvocationParameters("a", null); + getMethodInvocationParameters("a(", null); + getMethodInvocationParameters("a( ", null); + getMethodInvocationParameters("a)", null); + getMethodInvocationParameters("a )", null); + getMethodInvocationParameters("a()", ""); + getMethodInvocationParameters("a( )", ""); + getMethodInvocationParameters("a( yo )", "yo"); + getMethodInvocationParameters("SwingUtil.a( yo )", "yo"); + getMethodInvocationParameters("SwingUtil.a( yo, ya )", "yo, ya"); + + } + + @Test + public void testGetRequirementsWithLiterals() throws Exception { + + parseSourceAndGetRequirements("1"); + + parseSourceAndGetRequirements("true"); + + parseSourceAndGetRequirements("\"1\""); + + parseSourceAndGetRequirements("\"1\" + \"2\""); + + parseSourceAndGetRequirements("1.1 + 2"); + } + + + @Test + public void testGetRequirementsWithNoLiterals() throws Exception { + + parseSourceAndGetRequirements("a"); + + parseSourceAndGetRequirements("a.getText()", "a"); + + parseSourceAndGetRequirements("a.getText().getLength()", "a", "a.getText()"); + + parseSourceAndGetRequirements("getText()"); + + parseSourceAndGetRequirements("getText(a)"); + + parseSourceAndGetRequirements("getText(a, b, c)"); + + parseSourceAndGetRequirements("getText(a + b, c)"); + + parseSourceAndGetRequirements("getText(a + b + c)"); + + parseSourceAndGetRequirements("(Hum)a"); + + parseSourceAndGetRequirements("((Hum)a)"); + + parseSourceAndGetRequirements("((Hum)a).getText()", "a"); + + parseSourceAndGetRequirements("((Hum)a).getB().getText()", "a", "a.getB()"); + + parseSourceAndGetRequirements("((Hum)a.getB()).getText()", "a", "a.getB()"); + } + + @Test + public void testGetRequirements() throws Exception { + + parseSourceAndGetRequirements("getText(\"a\")"); + + parseSourceAndGetRequirements("SwingUtil.getText(\"a\")", "SwingUtil"); + + parseSourceAndGetRequirements("getText2() && getText(\"a.b\")"); + + parseSourceAndGetRequirements("SwingUtil.getText2() && getText(\"a.b\")", "SwingUtil"); + + parseSourceAndGetRequirements("SwingUtil.getText2() && SwingUtil2.getText(\"a.b\")", "SwingUtil", "SwingUtil2"); + + parseSourceAndGetRequirements("SwingUtil.get().getText2() && SwingUtil2.getText(\"a.b\")", "SwingUtil2", "SwingUtil", "SwingUtil.get()"); + + } + + protected void parseSourceAndGetExpressions(String source, int expectedNbLiterals, int expectedNbExpressions) { + + // clean stores + literals.clear(); + + parseSource(source); + + Assert.assertEquals(expectedNbLiterals, literals.size()); + Assert.assertEquals(expectedNbExpressions, store.size()); + + simpleNodeIterator = store.keySet().iterator(); + } + + protected void parseSourceAndGetRequirements(String source, String... expected) { + + parseSource(source); + + requirements = JavaParserUtil.getRequired(store.keySet(), casts); + Assert.assertEquals(expected.length, requirements == null ? 0 : requirements.size()); + if (expected.length > 0) { + + requirementsIterator = requirements.iterator(); + for (String s : expected) { + Assert.assertTrue(requirementsIterator.hasNext()); + Assert.assertEquals(s, requirementsIterator.next()); + } + } + } + + protected void getMethodInvocationParameters(String code, String expected) { + String invocationParameters = JavaParserUtil.getMethodInvocationParameters(code); + Assert.assertEquals(expected, invocationParameters); + } + + protected void assertNextNode(String expectedText, int nbDep) { + + Assert.assertTrue(simpleNodeIterator.hasNext()); + node = simpleNodeIterator.next(); + Assert.assertNotNull(node); + Assert.assertEquals(expectedText, node.getText().trim()); + Assert.assertEquals(nbDep, store.get(node).size()); + } + + private void parseSource(String source) { + + this.source = source; + // clean stores + store.clear(); + literals.clear(); + casts.clear(); + + if (log.isDebugEnabled()) { + log.debug(source); + } + + JavaParser p; + SimpleNode node; + p = new JavaParser(new StringReader(source)); + while (!p.Line()) { + node = p.popNode(); + JavaParserUtil.getExpressions(node, store, literals, casts); + } + } + + protected void assertLiteralNode(int nbDep) { + Assert.assertNotNull(node); + Assert.assertTrue(nbDep <= literals.size()); + Assert.assertEquals(node, literals.get(nbDep)); + } + +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/java/JavaFieldTest.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/java/JavaFieldTest.java new file mode 100644 index 0000000..67fab45 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/java/JavaFieldTest.java @@ -0,0 +1,124 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.java; + +import com.google.common.collect.Lists; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Modifier; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; + +/** + * Created: 3 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + * + * Mise a jour: $Date$ par : + * $Author$ + */ +public class JavaFieldTest { + /** Logger */ + private static final Log log = LogFactory.getLog(JavaFieldTest.class); + + @Test + public void testGetFieldOrderScope() { + + EnumSet<JavaField.FieldOrder> allConstants = EnumSet.allOf(JavaField.FieldOrder.class); + if (log.isDebugEnabled()) { + for (JavaField.FieldOrder allConstant : allConstants) { + log.debug("\n" + allConstant.getHeader()); + } + } + + EnumSet<JavaField.FieldOrder> constants; + + constants = JavaField.getFieldOrderScope(allConstants, Modifier.STATIC); + + Assert.assertEquals(4, constants.size()); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsBean)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsOthers)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsPublicBindings)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsPrivateBindings)); + + constants = JavaField.getFieldOrderScope(allConstants, Modifier.PUBLIC); + + Assert.assertEquals(3, constants.size()); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsBean)); +// Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsOthers)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsPublicBindings)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.publicFields)); + + constants = JavaField.getFieldOrderScope(allConstants, Modifier.PROTECTED); + + Assert.assertEquals(2, constants.size()); +// Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsOthers)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.protectedFields)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.internalFields)); + + + constants = JavaField.getFieldOrderScope(allConstants, Modifier.PRIVATE); + Assert.assertEquals(3, constants.size()); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsPrivateBindings)); +// Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsOthers)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.privateFields)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.internalFields)); + + } + + /** + * To test https://forge.nuiton.org/issues/2154. + * + * @since 2.5.1 + */ + @Test + public void testCompare() { + + String[] names = new String[]{ + "cf0", + "cf1", + "cf0O1", + "cf0A1", + "ct0O1", "ct0A1", + "cgett0", + "cgett1", "cgett0O1", + "cgett0A1", "cfile", "cgetfile", "t0", "t1", + "cmt0", "cmt1", "cmt0O1", "cmt0A1", "cmgett0", + "cmgett1", "cmgett0O1", "cmgett0A1", + "cMfile", "cMgetfile", + "Mt0", "Mt1", "cit0", "cit1", "cit0O1", "cit0A1", "cigett0", + "bindings" + }; + List<JavaField> theFileds = Lists.newArrayList(); + for (String name : names) { + JavaField field = new JavaField(Modifier.PROTECTED, "String", name, false); + theFileds.add(field); + } + Collections.sort(theFileds); + + } +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/java/JavaMethodTest.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/java/JavaMethodTest.java new file mode 100644 index 0000000..bc12f03 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/java/JavaMethodTest.java @@ -0,0 +1,88 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.java; + +import org.nuiton.jaxx.compiler.java.JavaMethod.MethodOrder; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Modifier; +import java.util.EnumSet; + +/** + * @author Tony Chemit - chemit@codelutin.com + */ +public class JavaMethodTest { + /** + * Logger + */ + private static final Log log = LogFactory.getLog(JavaMethodTest.class); + + @Test + public void testGetMethodOrderScope() { + + EnumSet<MethodOrder> allConstants = EnumSet.allOf(MethodOrder.class); + if (log.isDebugEnabled()) { + for (MethodOrder allConstant : allConstants) { + log.debug("\n" + allConstant.getHeader()); + } + } + + EnumSet<MethodOrder> constants; + + constants = JavaMethod.getMethodOrderScope(allConstants, Modifier.STATIC); + + Assert.assertEquals(1, constants.size()); + Assert.assertTrue(constants.contains(MethodOrder.statics)); + + constants = JavaMethod.getMethodOrderScope(allConstants, Modifier.PUBLIC); + + Assert.assertEquals(8, constants.size()); + Assert.assertTrue(constants.contains(MethodOrder.constructors)); + Assert.assertTrue(constants.contains(MethodOrder.JAXXObject)); + Assert.assertTrue(constants.contains(MethodOrder.JAXXContext)); + Assert.assertTrue(constants.contains(MethodOrder.JAXXValidation)); + Assert.assertTrue(constants.contains(MethodOrder.events)); + Assert.assertTrue(constants.contains(MethodOrder.publicGetters)); + Assert.assertTrue(constants.contains(MethodOrder.publicSetters)); + Assert.assertTrue(constants.contains(MethodOrder.otherPublic)); + + constants = JavaMethod.getMethodOrderScope(allConstants, Modifier.PROTECTED); + + Assert.assertEquals(4, constants.size()); + Assert.assertTrue(constants.contains(MethodOrder.protectedGetters)); + Assert.assertTrue(constants.contains(MethodOrder.protecteds)); + Assert.assertTrue(constants.contains(MethodOrder.createMethod)); + Assert.assertTrue(constants.contains(MethodOrder.internalMethod)); + + constants = JavaMethod.getMethodOrderScope(allConstants, Modifier.PRIVATE); + Assert.assertEquals(3, constants.size()); + + Assert.assertTrue(constants.contains(MethodOrder.createMethod)); + Assert.assertTrue(constants.contains(MethodOrder.packageLocal)); + Assert.assertTrue(constants.contains(MethodOrder.privates)); + + } +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/java/parser/JavaParserTest.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/java/parser/JavaParserTest.java new file mode 100644 index 0000000..dd41a35 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/java/parser/JavaParserTest.java @@ -0,0 +1,128 @@ +package org.nuiton.jaxx.compiler.java.parser; + +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2015 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.compiler.CompilerException; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.MethodDescriptor; +import org.nuiton.jaxx.compiler.reflect.resolvers.ClassDescriptorResolverFromJavaFile; +import org.junit.Assert; +import org.junit.Test; +import org.nuiton.util.FileUtil; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +/** + * Created on 4/12/15. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.24 + */ +public class JavaParserTest { + + public static final List<String> DUMMY_LIST = new ArrayList<>(); + public static final List<String> DUMMY_LIST2 = new ArrayList<>(); + + @Test + public void testParseClassButNotMethodBody() throws IOException, ClassNotFoundException, NoSuchMethodException { + + File file = new File("").getAbsoluteFile(); + Path rootSourceDirectory = file.toPath().resolve("src").resolve("test").resolve("java"); + + File thisClassJavaFile = new File(FileUtil.getFileFromFQN(rootSourceDirectory.toFile(), getClass().getPackage().getName()), getClass().getSimpleName() + ".java"); + + Assert.assertTrue("Could not find java file " + thisClassJavaFile, thisClassJavaFile.exists()); + + ClassDescriptorResolverFromJavaFile resolver = new ClassDescriptorResolverFromJavaFile(); + + ClassDescriptor yo = resolver.resolvDescriptor("yo", thisClassJavaFile.toURI().toURL()); + MethodDescriptor[] methodDescriptors = yo.getMethodDescriptors(); + Assert.assertTrue(methodDescriptors.length>3); + + { + MethodDescriptor method = yo.getMethodDescriptor("testParseClassButNotMethodBody"); + Assert.assertNotNull(method); + } + + { + MethodDescriptor method = yo.getMethodDescriptor("methodWithDiamondInside"); + Assert.assertNotNull(method); + } + + { + MethodDescriptor method = yo.getMethodDescriptor("methodWithTryResourceInside"); + Assert.assertNotNull(method); + } + + } + + + @Test + public void testParseClassAndMethodBody() throws IOException, ClassNotFoundException, NoSuchMethodException { + + File file = new File("").getAbsoluteFile(); + Path rootSourceDirectory = file.toPath().resolve("src").resolve("test").resolve("java"); + + File thisClassJavaFile = new File(FileUtil.getFileFromFQN(rootSourceDirectory.toFile(), getClass().getPackage().getName()), getClass().getSimpleName() + ".java"); + + Assert.assertTrue("Could not find java file " + thisClassJavaFile, thisClassJavaFile.exists()); + + ClassDescriptorResolverFromJavaFile resolver = new ClassDescriptorResolverFromJavaFile(true); + + try { + resolver.resolvDescriptor("yo", thisClassJavaFile.toURI().toURL()); + Assert.fail("Can't compile body method (there is some jdk7 syntaxes inside them)..."); + } catch (RuntimeException e) { + Assert.assertTrue(e.getCause() instanceof CompilerException); + } + + } + + public void methodWithDiamondInside() { + + System.out.println(new ArrayList<>()); + System.out.println(DUMMY_LIST); + System.out.println(DUMMY_LIST2); + + } + + public void methodWithTryResourceInside() { + + try (BufferedReader reader = Files.newBufferedReader(new File("").toPath(), Charset.forName("UTF-8"))) { + + System.out.println(reader); + } catch (IOException | RuntimeException e ) { + e.printStackTrace(); + } + + + } + +} \ No newline at end of file diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/ClassDescriptorTest.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/ClassDescriptorTest.java new file mode 100644 index 0000000..47aa4a8 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/ClassDescriptorTest.java @@ -0,0 +1,153 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.reflect; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class ClassDescriptorTest { + + @BeforeClass + public static void before() { + ClassDescriptorHelper.setShowLoading(true); + } + + @AfterClass + public static void after() { + ClassDescriptorHelper.setShowLoading(true); + } + + /*@Test + public void testGetClassDescriptor() throws Exception { + ClassDescriptorHelper.getClassDescriptor("jaxx.runtime.swing.navigation.tree.NavigationTreeModel.NavigationTreeNode"); + }*/ + @Test + public void testBuiltInClassName() throws ClassNotFoundException, NoSuchMethodException { + ClassDescriptor object = ClassDescriptorHelper.getClassDescriptor("java.lang.Object"); + MethodDescriptor toString = object.getMethodDescriptor("toString"); + assertEquals(toString.getName(), "toString"); + assertEquals(toString.getParameterTypes().length, 0); + + MethodDescriptor equals = object.getMethodDescriptor("equals", object); + assertEquals(equals.getName(), "equals"); + assertEquals(equals.getParameterTypes().length, 1); + assertEquals(equals.getParameterTypes()[0], object); + } + + @Test + public void testBuiltInClass() throws ClassNotFoundException, NoSuchMethodException { + ClassDescriptor object1 = ClassDescriptorHelper.getClassDescriptor("java.lang.Object"); + ClassDescriptor object2 = ClassDescriptorHelper.getClassDescriptor(Object.class); + assertEquals(object1, object2); + } + + @Test + public void testUserClassName() throws ClassNotFoundException, NoSuchMethodException { + ClassDescriptor me = ClassDescriptorHelper.getClassDescriptor(ClassDescriptorTest.class.getName(), getClass().getClassLoader()); + MethodDescriptor testUserClassName = me.getMethodDescriptor("testUserClassName"); + assertEquals(testUserClassName.getName(), "testUserClassName"); + assertEquals(testUserClassName.getParameterTypes().length, 0); + } + + @Test(expected = ClassNotFoundException.class) + public void testWrongCase() throws ClassNotFoundException { + ClassDescriptorHelper.getClassDescriptor("jaxx.junit.classdescriptortest", getClass().getClassLoader()); + } + + @Test + public void testArrays() throws ClassNotFoundException { + ClassDescriptor intArray = ClassDescriptorHelper.getClassDescriptor(int[].class); + assertNotNull(intArray); + ClassDescriptor objectArray = ClassDescriptorHelper.getClassDescriptor(Object[].class); + assertNotNull(objectArray); + } + + @Test + public void testConstructorFromClass() throws ClassNotFoundException, MalformedURLException { + String className = MyClass.class.getName(); + ClassDescriptor descriptor = ClassDescriptorHelper.getClassDescriptor(className); + assertNotNull(descriptor); + ClassDescriptorHelper.ResolverType resolverType = descriptor.getResolverType(); + + //FIXME-tchemit find out why ? (https://forge.nuiton.org/issues/2203) + // using jdk 7 VM Server it found a FILE instead of a CLASS ? Wonder why? + // Need to find out why +// assertEquals(ClassDescriptorHelper.ResolverType.JAVA_CLASS, resolverType); + assertTrue(Arrays.asList(ClassDescriptorHelper.ResolverType.JAVA_CLASS, ClassDescriptorHelper.ResolverType.JAVA_FILE).contains(resolverType)); + MethodDescriptor[] constructorDescriptors = descriptor.getConstructorDescriptors(); + assertNotNull(constructorDescriptors); + assertEquals(2, constructorDescriptors.length); + } + + @Test + public void testConstructorFromJavaFile() throws ClassNotFoundException, MalformedURLException { + String className = MyClass.class.getName(); + ClassLoader classLoader = getClass().getClassLoader(); + + + File testSourceDir = new File(getBasedir(), "src" + File.separator + "test" + File.separator + "java"); + + ClassLoader myClassLoader = new URLClassLoader(new URL[]{testSourceDir.toURI().toURL()}, classLoader); + + URL javaFileUrl = ClassDescriptorHelper.getURL(myClassLoader, className, "java"); + assertNotNull(javaFileUrl); + + ClassDescriptor descriptorFromFile = ClassDescriptorHelper.getClassDescriptor0( + ClassDescriptorHelper.ResolverType.JAVA_FILE, + className, + javaFileUrl, + myClassLoader + ); + assertNotNull(descriptorFromFile); + MethodDescriptor[] constructorDescriptorsfromFile = descriptorFromFile.getConstructorDescriptors(); + assertNotNull(constructorDescriptorsfromFile); + assertEquals(2, constructorDescriptorsfromFile.length); + } + + + static File basedir; + + public static File getBasedir() { + if (basedir == null) { + String tmp = System.getProperty("basedir"); + if (tmp == null) { + tmp = new File("").getAbsolutePath(); + } + basedir = new File(tmp); + + } + return basedir; + } + +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyAbstractClass.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyAbstractClass.java new file mode 100644 index 0000000..6858255 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyAbstractClass.java @@ -0,0 +1,35 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.reflect; + +/** + * To test parser on abstract class file. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public abstract class MyAbstractClass implements MyInterface { + + protected void myAbstractMethod() { + + } +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyChildClass.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyChildClass.java new file mode 100644 index 0000000..2101e33 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyChildClass.java @@ -0,0 +1,45 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.reflect; + +/** + * A child class to test the bug https://forge.nuiton.org/issues/show/1470 + * + * To test if a child class obtains properties from his super class. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.4.2 + */ +public class MyChildClass extends MyClass implements Cloneable{ + + private static final long serialVersionUID = 2L; + + protected String childProperty; + + public String getChildProperty() { + return childProperty; + } + + public void setChildProperty(String childProperty) { + this.childProperty = childProperty; + } +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyChildClass2.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyChildClass2.java new file mode 100644 index 0000000..2f37353 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyChildClass2.java @@ -0,0 +1,37 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.reflect; + +/** + * To test the bug : https://forge.nuiton.org/issues/show/1442 + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.4.2 + */ +public class MyChildClass2 extends MyClass { + private static final long serialVersionUID = 1L; +} + +// This class will not be scanned! +class MyPackageClass { + +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyClass.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyClass.java new file mode 100644 index 0000000..d9fd8a5 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyClass.java @@ -0,0 +1,65 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.reflect; + +import java.io.Serializable; + +/** + * To test inheritance. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class MyClass extends MyAbstractClass implements Serializable { + + private static final long serialVersionUID = 1L; + + private final String myPrivateStringField = "final"; + + protected String myProtectedStringField; + + public String myPublicStringField; + + public MyClass() { + } + + public MyClass(String myProtectedStringField, String myPublicStringField) { + this.myProtectedStringField = myProtectedStringField; + this.myPublicStringField = myPublicStringField; + } + + @Override + public void myMethod() { + } + + public String getMyPrivateStringField() { + return myPrivateStringField; + } + + public String getMyProtectedStringField() { + return myProtectedStringField; + } + + public String getMyPublicStringField() { + return myPublicStringField; + } +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyEnum.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyEnum.java new file mode 100644 index 0000000..90c414d --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyEnum.java @@ -0,0 +1,42 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.reflect; + +import java.io.Serializable; + +/** + * Created: 4 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + * + * Mise a jour: $Date$ par : + * $Author$ + */ +public enum MyEnum implements Serializable, MyInterface { + + A, B; + + @Override + public void myMethod() { + } +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyInterface.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyInterface.java new file mode 100644 index 0000000..4254a73 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyInterface.java @@ -0,0 +1,35 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.reflect; + +/** + * Simple interface to test. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public interface MyInterface { + + String MY_CONSTANT = "constant"; + + void myMethod(); +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyInterface2.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyInterface2.java new file mode 100644 index 0000000..c1c5430 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyInterface2.java @@ -0,0 +1,37 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.reflect; + +import org.nuiton.config.ConfigOptionDef; + +/** + * Simple interface to test. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public interface MyInterface2 extends ConfigOptionDef { + + String MY_CONSTANT = "constant"; + + void myMethod(); +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyInterface3.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyInterface3.java new file mode 100644 index 0000000..a98eadd --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/MyInterface3.java @@ -0,0 +1,37 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.reflect; + +import org.nuiton.config.ConfigOptionDef; + +/** + * Simple interface to test. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public interface MyInterface3 extends ConfigOptionDef, Iterable<MyInterface3> { + + String MY_CONSTANT = "constant"; + + void myMethod(); +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFileTest.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFileTest.java new file mode 100644 index 0000000..c6c9ee7 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFileTest.java @@ -0,0 +1,394 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.reflect.resolvers; + +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.nuiton.jaxx.compiler.reflect.FieldDescriptor; +import org.nuiton.jaxx.compiler.reflect.MyAbstractClass; +import org.nuiton.jaxx.compiler.reflect.MyChildClass; +import org.nuiton.jaxx.compiler.reflect.MyChildClass2; +import org.nuiton.jaxx.compiler.reflect.MyClass; +import org.nuiton.jaxx.compiler.reflect.MyEnum; +import org.nuiton.jaxx.compiler.reflect.MyInterface; +import org.nuiton.jaxx.compiler.reflect.MyInterface2; +import org.nuiton.jaxx.compiler.reflect.MyInterface3; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.nuiton.config.ConfigOptionDef; +import org.nuiton.util.FileUtil; + +import java.io.File; +import java.io.Serializable; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; + +/** + * Tests the {@link ClassDescriptorResolverFromJavaFile} resolver. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.2 + */ +public class ClassDescriptorResolverFromJavaFileTest { + + /** log */ + protected static final Log log = + LogFactory.getLog(ClassDescriptorResolverFromJavaFileTest.class); + + + /** test source root directory */ + public static File testSourceRoot; + + @BeforeClass + public static void initBaseDir() { + // get maven env basedir + String basedir = System.getenv("basedir"); + if (basedir == null) { + + // says basedir is where we start tests. + basedir = new File("").getAbsolutePath(); + } + testSourceRoot = FileUtil.getFileFromPaths(new File(basedir), + "src", + "test", + "java"); + } + + protected ClassDescriptor getDescriptor(Class<?> klass) throws Exception { + + String javaFilePath = + klass.getName().replaceAll("\\.", File.separator) + ".java"; + File src = new File(testSourceRoot, javaFilePath); + Assert.assertTrue(src.exists()); + + if (log.isDebugEnabled()) { + log.debug("file to parse " + src); + } + + ClassDescriptorResolverFromJavaFile resolver = + new ClassDescriptorResolverFromJavaFile(); + + ClassDescriptor descriptor = + resolver.resolvDescriptor(klass.getName(), src.toURI().toURL()); + + Assert.assertNotNull(descriptor); + if (log.isDebugEnabled()) { + log.debug("loaded " + descriptor); + } + Assert.assertEquals(klass.getName(), descriptor.getName()); + return descriptor; + } + + @Test + public void parseClassDescriptorResolverFromJavaFileTest() throws Exception { + + ClassDescriptor descriptor = + getDescriptor(ClassDescriptorResolverFromJavaFileTest.class); + + assertInterfaces(descriptor); + assertSuperClass(descriptor, Object.class); + } + + + @Test + public void parseMyEnum() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyEnum.class); + + assertInterfaces(descriptor, Serializable.class, MyInterface.class); + assertInterfaces(descriptor, MyEnum.class.getInterfaces()); + assertSuperClass(descriptor, Enum.class); + + assertIsAssignableFrom( + descriptor, + Serializable.class, + MyInterface.class, + Enum.class + ); + } + + @Test + public void parseMyInterface() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyInterface.class); + + assertInterfaces(descriptor); + assertSuperClass(descriptor, null); + } + + @Test + public void parseMyInterface2() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyInterface2.class); + + assertInterfaces(descriptor, MyInterface2.class.getInterfaces()); + assertInterfaces(descriptor, ConfigOptionDef.class); + assertSuperClass(descriptor, null); + } + + + @Test + public void parseMyInterface3() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyInterface3.class); + + assertInterfaces(descriptor, MyInterface3.class.getInterfaces()); + assertInterfaces(descriptor, ConfigOptionDef.class, + Iterable.class); + assertSuperClass(descriptor, null); + } + + @Test + public void parseMyAbstractClass() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyAbstractClass.class); + + assertInterfaces(descriptor, MyAbstractClass.class.getInterfaces()); + assertInterfaces(descriptor, MyInterface.class); + assertSuperClass(descriptor, Object.class); + assertIsAssignableFrom(descriptor, MyInterface.class, Object.class); + } + + @Test + public void parseMyClass() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyClass.class); + + assertInterfaces(descriptor, MyClass.class.getInterfaces()); + assertInterfaces(descriptor, Serializable.class); + assertSuperClass(descriptor, MyAbstractClass.class); + assertIsAssignableFrom(descriptor, + Serializable.class, + MyInterface.class, + MyAbstractClass.class + ); + + assertDeclaredField( + descriptor, + "serialVersionUID", + long.class, + Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC + ); + + assertDeclaredField( + descriptor, + "myPrivateStringField", + String.class, + Modifier.PRIVATE | Modifier.FINAL + ); + + assertDeclaredField( + descriptor, + "myProtectedStringField", + String.class, + Modifier.PROTECTED + ); + + assertField( + descriptor, + "myPublicStringField", + String.class, + Modifier.PUBLIC + ); + } + + @Test + public void parseMyChildClass() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyChildClass.class); + + assertInterfaces(descriptor, MyChildClass.class.getInterfaces()); + assertInterfaces(descriptor, Cloneable.class); + assertSuperClass(descriptor, MyClass.class); + assertIsAssignableFrom(descriptor, + Serializable.class, + MyInterface.class, + MyAbstractClass.class, + MyClass.class + ); + + assertDeclaredField( + descriptor, + "serialVersionUID", + long.class, + Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC + ); + + assertDeclaredField( + descriptor, + "myPrivateStringField", + String.class, + Modifier.PRIVATE | Modifier.FINAL + ); + + assertDeclaredField( + descriptor, + "myProtectedStringField", + String.class, + Modifier.PROTECTED + ); + + assertDeclaredField( + descriptor, + "childProperty", + String.class, + Modifier.PROTECTED + ); + + assertField( + descriptor, + "myPublicStringField", + String.class, + Modifier.PUBLIC + ); + + } + + @Test + public void parseMyChildClass2() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyChildClass2.class); + + assertInterfaces(descriptor, MyChildClass2.class.getInterfaces()); + assertSuperClass(descriptor, MyClass.class); + assertIsAssignableFrom(descriptor, + Serializable.class, + MyInterface.class, + MyAbstractClass.class, + MyClass.class + ); + + assertDeclaredField( + descriptor, + "serialVersionUID", + long.class, + Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC + ); + + assertDeclaredField( + descriptor, + "myPrivateStringField", + String.class, + Modifier.PRIVATE | Modifier.FINAL + ); + + assertDeclaredField( + descriptor, + "myProtectedStringField", + String.class, + Modifier.PROTECTED + ); + + assertField( + descriptor, + "myPublicStringField", + String.class, + Modifier.PUBLIC + ); + + } + + public static void assertField(ClassDescriptor descriptor, + String fieldName, + Class<?> fieldType, + int fieldModifiers) throws NoSuchFieldException { + FieldDescriptor fieldDescriptor = + descriptor.getFieldDescriptor(fieldName); + Assert.assertNotNull(fieldDescriptor); + ClassDescriptor type = fieldDescriptor.getType(); + Assert.assertNotNull(type); + Assert.assertEquals(fieldType.getName(), type.getName()); + int modifiers = fieldDescriptor.getModifiers(); + Assert.assertEquals(fieldModifiers, modifiers); + } + + public static void assertDeclaredField(ClassDescriptor descriptor, + String fieldName, + Class<?> fieldType, + int fieldModifiers) throws NoSuchFieldException { + FieldDescriptor fieldDescriptor = + descriptor.getDeclaredFieldDescriptor(fieldName); + Assert.assertNotNull(fieldDescriptor); + ClassDescriptor type = fieldDescriptor.getType(); + Assert.assertNotNull(type); + Assert.assertEquals(fieldType.getName(), type.getName()); + int modifiers = fieldDescriptor.getModifiers(); + Assert.assertEquals(fieldModifiers, modifiers); + } + + + public static void assertIsAssignableFrom(ClassDescriptor descriptor, + Class<?>... interfaces) { + + for (Class<?> anInterface : interfaces) { + ClassDescriptor descriptor2 = + ClassDescriptorHelper.getClassDescriptor(anInterface); + Assert.assertNotNull(descriptor2); + boolean value = descriptor2.isAssignableFrom(descriptor); + Assert.assertTrue( + anInterface + " should be assignable from " + descriptor, + value + ); + } + } + + public static void assertInterfaces(ClassDescriptor descriptor, + Class<?>... interfaces) { + ClassDescriptor[] descriptors = descriptor.getInterfaces(); + Assert.assertEquals(interfaces.length, descriptors.length); + + List<String> doFind = new ArrayList<>(); + for (Class<?> anInterface : interfaces) { + doFind.add(anInterface.getName()); + } + + for (ClassDescriptor descriptor1 : descriptors) { + String name = descriptor1.getName(); + Assert.assertTrue(doFind.contains(name)); + doFind.remove(name); + } + Assert.assertTrue( + "The follwing interfaces were not find found : " + doFind, + doFind.isEmpty() + ); + } + + public static void assertSuperClass(ClassDescriptor descriptor, + Class<?> superClass) { + ClassDescriptor superDescriptor = descriptor.getSuperclass(); + if (superClass == null) { + Assert.assertNull( + "Should be null but was " + superDescriptor, + superDescriptor + ); + } else { + Assert.assertNotNull(superDescriptor); + Assert.assertEquals(superClass.getName(), superDescriptor.getName()); + } + + } + +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/tags/TagManagerTest.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/tags/TagManagerTest.java new file mode 100644 index 0000000..e7e4abd --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/tags/TagManagerTest.java @@ -0,0 +1,168 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.tags; + +import org.nuiton.jaxx.compiler.CompilerConfiguration; +import org.nuiton.jaxx.compiler.DefaultCompilerConfiguration; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXFactory; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptor; +import org.nuiton.jaxx.compiler.reflect.ClassDescriptorHelper; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.swing.JPopupMenu; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; + +public class TagManagerTest { + + protected static CompilerConfiguration configuration; + + protected JAXXCompiler compiler; + + public static class TestHandler extends DefaultObjectHandler { + + public TestHandler(ClassDescriptor beanClass) { + super(beanClass); + } + } + + @BeforeClass + public static void init() throws Exception { + if (configuration == null) { + configuration = new DefaultCompilerConfiguration(); + } +// TagManager.reset(); + JAXXFactory.setConfiguration(configuration); + JAXXFactory.initFactory(); + + } + + @Before + public void setUp() { + JAXXFactory.newDummyEngine(); + compiler = JAXXFactory.newDummyCompiler(JAXXCompiler.class.getClassLoader()); +// compiler = new JAXXCompiler(JAXXCompiler.class.getClassLoader()); + compiler.addImport("javax.swing.*"); + + } + + @Test + public void testRegisterBean() { + TagManager.registerBean(ClassDescriptorHelper.getClassDescriptor(InputStream.class), TestHandler.class); + + Assert.assertTrue(TagManager.getTagHandler(ClassDescriptorHelper.getClassDescriptor(InputStream.class)) instanceof TestHandler); + Assert.assertTrue(TagManager.getTagHandler(ClassDescriptorHelper.getClassDescriptor(FileInputStream.class)) instanceof TestHandler); + } + + @Test + public void testRegisterDefaultNamespace() { + + TagManager.registerBean(ClassDescriptorHelper.getClassDescriptor(OutputStream.class), TestHandler.class); + + TagManager.registerDefaultNamespace("OutputStream", "java.io.*"); + Assert.assertTrue("Could not find handler for OutputStream despite default namespace", TagManager.getTagHandler(null, "OutputStream", compiler) instanceof TestHandler); + + PrintStream oldErr = System.err; + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + System.setErr(new PrintStream(buffer)); + TagManager.registerDefaultNamespace("OutputStream", "java.dummy.*"); + Assert.assertNull("Found handler for OutputStream despite ambiguous default namespace", TagManager.getTagHandler(null, "OutputStream", compiler)); + System.setErr(oldErr); + Assert.assertTrue("No errors were produced with an ambiguous default namespace", buffer.size() > 0); + Assert.assertTrue(buffer.size() > 0); + } + + @Test + public void testResolveClassName() { + Assert.assertEquals("Could not resolve class name 'Object'", TagManager.resolveClassName("Object", compiler), "java.lang.Object"); + Assert.assertEquals("Could not resolve class name 'java.lang.Object'", TagManager.resolveClassName("java.lang.Object", compiler), "java.lang.Object"); + Assert.assertNull("Unexpectedly resolved class name 'java.awt.Object'", TagManager.resolveClassName("java.awt.Object", compiler)); + } + + @Test + public void testPackages() { + Assert.assertNull("Unexpectedly found handler for java.awt.JButton", TagManager.getTagHandler(null, "java.awt.JButton", compiler)); + Assert.assertNotNull("Did not find handler for JButton with default namespace of java.awt.*", TagManager.getTagHandler("java.awt.*", "JButton", compiler)); + Assert.assertNull("Unexpectedly found handler for java.awt.*:JButton", TagManager.getTagHandler("java.awt.*", "JButton", true, compiler)); + Assert.assertNotNull("Did not find handler for javax.swing.JButton", TagManager.getTagHandler(null, "javax.swing.JButton", compiler)); + Assert.assertNotNull("Did not find handler for JButton with default namespace of java.swing.*", TagManager.getTagHandler("java.swing.*", "JButton", compiler)); + Assert.assertNotNull("Did not find handler for javax.swing.*:JButton", TagManager.getTagHandler("javax.swing.*", "JButton", true, compiler)); + } + + @Test + public void testImport() throws Exception { + Assert.assertNull("Found handler for ActionListener despite no java.awt.event.* import", TagManager.getTagHandler(null, "ActionListener", compiler)); + + compiler.addImport("java.awt.event.*"); + + Assert.assertNotNull("Did not find ActionListener with java.awt.event.* import", TagManager.getTagHandler(null, "ActionListener", compiler)); + } + + @Test + public void testAmbiguousImport() throws Exception { + compiler.addImport("java.sql.*"); + Assert.assertNotNull("Did not find java.sql.Date with only java.sql.* imported", TagManager.getTagHandler(null, "Date", compiler)); + + PrintStream oldErr = System.err; + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + System.setErr(new PrintStream(buffer)); + compiler.addImport("java.util.*"); + init(); + Assert.assertNull("Still found a handler for Date with an ambiguous import", TagManager.getTagHandler(null, "Date", compiler)); + System.setErr(oldErr); + Assert.assertTrue("No errors were produced with an ambiguous import", buffer.size() > 0); + + compiler.addImport("java.util.Date"); + Assert.assertNotNull("Did not find java.util.Date with a disambiguating import", TagManager.getTagHandler(null, "Date", compiler)); + } + + @Test + public void testInnerClass() { + TagHandler handler = TagManager.getTagHandler(null, "JPopupMenu.Separator", compiler); + Assert.assertTrue("Unable to resolve tag <JPopupMenu.Separator>", handler instanceof DefaultComponentHandler); + Assert.assertTrue(((DefaultComponentHandler) handler).getBeanClass().getName().equals(JPopupMenu.Separator.class.getName())); + + handler = TagManager.getTagHandler(null, "javax.swing.JPopupMenu.Separator", compiler); + Assert.assertTrue("Unable to resolve tag <javax.swing.JPopupMenu.Separator>", handler instanceof DefaultComponentHandler); + Assert.assertTrue(((DefaultComponentHandler) handler).getBeanClass().getName().equals(JPopupMenu.Separator.class.getName())); + } + + @Test + public void testWrongCase() { + Assert.assertNull("Unexpectedly found handler for 'object'", TagManager.getTagHandler(null, "object", compiler)); + Assert.assertNull("Unexpectedly found handler for 'tagmanagertest'", TagManager.getTagHandler(null, "tagmanagertest", compiler)); + } + + @Test + public void testAliasing() { + Assert.assertEquals("ButtonGroup is not aliased to org.nuiton.jaxx.runtime.swing.JAXXButtonGroup", "org.nuiton.jaxx.runtime.swing.JAXXButtonGroup", TagManager.resolveClassName("ButtonGroup", compiler)); + Assert.assertEquals("javax.swing.ButtonGroup is not aliased to org.nuiton.jaxx.runtime.swing.JAXXButtonGroup", "org.nuiton.jaxx.runtime.swing.JAXXButtonGroup", TagManager.resolveClassName("javax.swing.ButtonGroup", compiler)); + } +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/types/ColorConverterTest.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/types/ColorConverterTest.java new file mode 100644 index 0000000..420cc58 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/types/ColorConverterTest.java @@ -0,0 +1,72 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.types; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.awt.*; + +public class ColorConverterTest { + + ColorConverter converter; + + @Before + public void setUp() { + converter = new ColorConverter(); + } + + @Test + public void testHexValue() { + Color value = (Color) converter.convertFromString("#3000FF", Color.class); + Assert.assertEquals(value, new Color(48, 0, 255)); + } + + @Test + public void testUpperCaseConstant() { + Color value = (Color) converter.convertFromString("RED", Color.class); + Assert.assertEquals(value, Color.RED); + } + + @Test + public void testLowerCaseConstant() { + Color value = (Color) converter.convertFromString("blue", Color.class); + Assert.assertEquals(value, Color.blue); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingHash() { + converter.convertFromString("ABCDEF", Color.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidNumber() { + converter.convertFromString("#ABCDEG", Color.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidConstant() { + converter.convertFromString("rEd", Color.class); + } +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/types/InsetsConverterTest.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/types/InsetsConverterTest.java new file mode 100644 index 0000000..836fcd5 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/types/InsetsConverterTest.java @@ -0,0 +1,71 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.types; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.awt.Insets; + +public class InsetsConverterTest { + + InsetsConverter converter; + + @Before + public void setUp() { + converter = new InsetsConverter(); + } + + @Test + public void testSingleValue() { + Insets value = (Insets) converter.convertFromString("3", Insets.class); + Assert.assertEquals(value, new Insets(3, 3, 3, 3)); + } + + @Test + public void testFourValues() { + Insets value = (Insets) converter.convertFromString("3, 0, 12, 1000000", Insets.class); + Assert.assertEquals(value, new Insets(3, 0, 12, 1000000)); + } + + @Test(expected = IllegalArgumentException.class) + public void testTwoValues() { + converter.convertFromString("0, 4", Insets.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testThreeValues() { + converter.convertFromString("0, 4, 9", Insets.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidNumber() { + converter.convertFromString("0, 4, 9, A", Insets.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testBadFormatting() { + converter.convertFromString("0 - 1 - 2 - 3", Insets.class); + } +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/types/PrimitiveConverterTest.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/types/PrimitiveConverterTest.java new file mode 100644 index 0000000..c009965 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/types/PrimitiveConverterTest.java @@ -0,0 +1,134 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.compiler.types; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class PrimitiveConverterTest { + + PrimitiveConverter converter; + + + @Before + public void setUp() { + converter = new PrimitiveConverter(); + } + + @Test + public void testBoolean() { + Boolean value = (Boolean) converter.convertFromString("true", Boolean.class); + Assert.assertTrue(value); + + value = (Boolean) converter.convertFromString("false", Boolean.class); + Assert.assertFalse(value); + + } + + @Test(expected = IllegalArgumentException.class) + public void testBoolean2() { + converter.convertFromString("yes", Boolean.class); + } + + @Test + public void testByte() { + Byte value = (Byte) converter.convertFromString(String.valueOf(Byte.MAX_VALUE), Byte.class); + Assert.assertEquals(value.byteValue(), Byte.MAX_VALUE); + + } + + @Test(expected = IllegalArgumentException.class) + public void testByte2() { + + converter.convertFromString(String.valueOf(1 + Byte.MAX_VALUE), Byte.class); + } + + @Test + public void testShort() { + Short value = (Short) converter.convertFromString(String.valueOf(Short.MAX_VALUE), Short.class); + Assert.assertEquals(value.shortValue(), Short.MAX_VALUE); + + + } + + @Test(expected = IllegalArgumentException.class) + public void testShort2() { + + converter.convertFromString(String.valueOf(1 + Short.MAX_VALUE), Short.class); + } + + @Test + public void testInteger() { + Integer value = (Integer) converter.convertFromString(String.valueOf(Integer.MAX_VALUE), Integer.class); + Assert.assertEquals(value.intValue(), Integer.MAX_VALUE); + } + + @Test(expected = IllegalArgumentException.class) + public void testInteger2() { + + converter.convertFromString(String.valueOf(1L + Integer.MAX_VALUE), Integer.class); + } + + @Test + public void testLong() { + Long value = (Long) converter.convertFromString(String.valueOf(Long.MAX_VALUE), Long.class); + Assert.assertEquals(value.longValue(), Long.MAX_VALUE); + } + + @Test + public void testFloat() { + Float value = (Float) converter.convertFromString("3.1415", Float.class); + Assert.assertTrue(value == 3.1415f); + } + + @Test + public void testDouble() { + Double value = (Double) converter.convertFromString("3.1415", Double.class); + Assert.assertTrue(value == 3.1415); + } + + @Test + public void testCharacter() { + Character value = (Character) converter.convertFromString("A", Character.class); + Assert.assertEquals(value.charValue(), 'A'); + } + + @Test(expected = IllegalArgumentException.class) + public void testCharacter2() { + + converter.convertFromString("12", Character.class); + + } + + @Test(expected = IllegalArgumentException.class) + public void testCharacter3() { + converter.convertFromString("", Character.class); + } + + @Test + public void testString() { + String value = (String) converter.convertFromString("Test", String.class); + Assert.assertEquals(value, "Test"); + } +} diff --git a/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/types/TypeManagerTest.java b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/types/TypeManagerTest.java new file mode 100644 index 0000000..84ec2c0 --- /dev/null +++ b/jaxx-compiler/src/test/java/org/nuiton/jaxx/compiler/types/TypeManagerTest.java @@ -0,0 +1,77 @@ +/* + * #%L + * JAXX :: Compiler + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.compiler.types; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created: 29 nov. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + * + * Mise a jour: $Date$ par : + * $Author$ + */ +public class TypeManagerTest { + + @Test + public void testHexValue() { + + String actual; + String expected; + + actual = TypeManager.convertVariableNameToConstantName("azerty"); + expected = "AZERTY"; + Assert.assertEquals(expected, actual); + + actual = TypeManager.convertVariableNameToConstantName("azertyQwerty"); + expected = "AZERTY_QWERTY"; + Assert.assertEquals(expected, actual); + + actual = TypeManager.convertVariableNameToConstantName("1azertyQwerty"); + expected = "1AZERTY_QWERTY"; + Assert.assertEquals(expected, actual); + + actual = TypeManager.convertVariableNameToConstantName("$1azertyQwerty"); + expected = "$1AZERTY_QWERTY"; + Assert.assertEquals(expected, actual); + + actual = TypeManager.convertVariableNameToConstantName("binding_$hum"); + expected = "BINDING_$HUM"; + Assert.assertEquals(expected, actual); + + actual = TypeManager.convertVariableNameToConstantName("BINding_$hum"); + expected = "BINDING_$HUM"; + Assert.assertEquals(expected, actual); + + actual = TypeManager.convertVariableNameToConstantName("BINding_$Hum"); + expected = "BINDING_$HUM"; + Assert.assertEquals(expected, actual); + + actual = TypeManager.convertVariableNameToConstantName("!BINding_$Hum"); + expected = "NOT_BINDING_$HUM"; + Assert.assertEquals(expected, actual); + } + +} diff --git a/jaxx-compiler/src/test/resources/log4j.properties b/jaxx-compiler/src/test/resources/log4j.properties index b049741..384fb94 100644 --- a/jaxx-compiler/src/test/resources/log4j.properties +++ b/jaxx-compiler/src/test/resources/log4j.properties @@ -26,4 +26,4 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) %M - %m%n -log4j.logger.jaxx=INFO +log4j.logger.org.nuiton.jaxx=INFO diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigCallBackUIHandler.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigCallBackUIHandler.java deleted file mode 100644 index 13e1c74..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigCallBackUIHandler.java +++ /dev/null @@ -1,191 +0,0 @@ -package jaxx.runtime.swing.config; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.SwingUtil; -import jaxx.runtime.swing.config.model.CallBackEntry; -import jaxx.runtime.swing.config.model.CallBackMap; -import jaxx.runtime.swing.config.model.OptionModel; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.JLabel; -import javax.swing.JTree; -import javax.swing.SwingUtilities; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.DefaultTreeModel; -import java.awt.Component; -import java.awt.Window; -import java.util.List; -import java.util.Map; - -import static org.nuiton.i18n.I18n.t; - -/** - * callBackUI handler - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class ConfigCallBackUIHandler { - - /** Logger */ - private static final Log log = - LogFactory.getLog(ConfigCallBackUIHandler.class); - - public void init(ConfigCallBackUI ui) { - - // build tree model - DefaultMutableTreeNode root = new DefaultMutableTreeNode(); - - CallBackMap forSaved = ui.getContextValue( - CallBackMap.class, ConfigUIHandler.CALLBACKS_WITH_OPTIONS); - - for (Map.Entry<CallBackEntry, List<OptionModel>> e : - forSaved.entrySet()) { - - CallBackEntry callBackEntry = e.getKey(); - List<OptionModel> options = e.getValue(); - - DefaultMutableTreeNode callBackNode; - callBackNode = new DefaultMutableTreeNode(callBackEntry, true); - - root.add(callBackNode); - for (OptionModel o : options) { - - DefaultMutableTreeNode optionkNode; - optionkNode = new DefaultMutableTreeNode(o, false); - - callBackNode.add(optionkNode); - } - } - - JTree tree = ui.getDetectedCallBack(); - - tree.setModel(new DefaultTreeModel(root)); - - SwingUtil.expandTree(tree); - - tree.setCellRenderer(new DefaultTreeCellRenderer() { - @Override - public Component getTreeCellRendererComponent(JTree tree, - Object value, - boolean sel, - boolean expanded, - boolean leaf, - int row, - boolean hasFocus) { - if (log.isDebugEnabled()) { - log.debug("value = " + value.getClass()); - } - if (value == null) { - return super.getTreeCellRendererComponent( - tree, - value, - sel, - expanded, - leaf, - row, - hasFocus); - } - - if (!(value instanceof DefaultMutableTreeNode)) { - return super.getTreeCellRendererComponent( - tree, - value, - sel, - expanded, - leaf, - row, - hasFocus); - } - - DefaultMutableTreeNode n = (DefaultMutableTreeNode) value; - value = n.getUserObject(); - - if (value instanceof CallBackEntry) { - CallBackEntry v = (CallBackEntry) value; - if (log.isDebugEnabled()) { - log.debug("callBackEntry detected " + v.getName()); - } - value = t(v.getDescription()); - } else if (value instanceof OptionModel) { - - OptionModel v = (OptionModel) value; - if (log.isDebugEnabled()) { - log.debug("option detected " + v.getKey()); - } - value = v.getKey() + " (" + t(v.getDescription()) + ")"; - } - - JLabel rendererComponent; - rendererComponent = (JLabel) - super.getTreeCellRendererComponent( - tree, - value, - sel, - expanded, - leaf, - row, - hasFocus); - - value = n.getUserObject(); - - if (value instanceof CallBackEntry) { - - CallBackEntry v = (CallBackEntry) value; - rendererComponent.setIcon(v.getIcon()); - } - return rendererComponent; - } - }); - } - - public void doAction(final ConfigCallBackUI ui) { - log.info("Launch callBacks..."); - Window parent = ui.getContextValue(Window.class, "parent"); - if (parent != null) { - log.info("dispose parent window..."); - parent.dispose(); - } - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - List<CallBackEntry> callBacks; - callBacks = ui.getContextValue( - List.class, - ConfigUIHandler.CALLBACKS); - for (CallBackEntry e : callBacks) { - if (log.isInfoEnabled()) { - log.info("launch callBack " + t(e.getDescription())); - } - e.getAction().run(); - } - } - }); - } -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigCategoryUI.jaxx b/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigCategoryUI.jaxx deleted file mode 100644 index 4a75bed..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigCategoryUI.jaxx +++ /dev/null @@ -1,87 +0,0 @@ -<!-- - #%L - JAXX :: Config - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<JPanel layout='{new BorderLayout()}'> - - <import> - java.awt.Color - javax.swing.DefaultListSelectionModel - javax.swing.ScrollPaneConstants - jaxx.runtime.swing.config.model.CategoryModel - jaxx.runtime.swing.config.model.ConfigTableModel - jaxx.runtime.swing.config.model.ConfigUIModel - org.jdesktop.swingx.JXTable - </import> - - <ConfigCategoryUIHandler id='handler' constructorParams='this'/> - - <script><![CDATA[ - -void $afterCompleteSetup() { - getHandler().init(); -} -]]> - </script> - - <!-- le modele de l'ui --> - <ConfigUIModel id='model' - initializer='getContextValue(ConfigUIModel.class)'/> - - <CategoryModel id='categoryModel' - javaBean='getContextValue(CategoryModel.class)'/> - - <ConfigTableModel id='tableModel' constructorParams='categoryModel' - onTableChanged='handler.updateDescriptionText()'/> - - <ListSelectionModel id='selectionModel' - javaBean='new DefaultListSelectionModel()' - onValueChanged='if (!event.getValueIsAdjusting()) {handler.updateDescriptionText(); }'/> - - <!-- categorie label --> - <JPanel id="categoryLabelPanel" constraints='BorderLayout.NORTH'> - <JLabel id='categoryLabel'/> - </JPanel> - - <!-- table of options --> - <JScrollPane id='tablePane' constraints='BorderLayout.CENTER'> - <JXTable id="table" constructorParams='tableModel' onMousePressed='handler.openTablePopupMenu(event, tablePopup)'/> - </JScrollPane> - - <JPanel layout='{new BorderLayout()}' constraints='BorderLayout.SOUTH'> - - <!-- description of selected option in table --> - <JScrollPane id="descriptionPane" constraints='BorderLayout.CENTER'> - <JTextArea id='description'/> - </JScrollPane> - - <!-- actions of the category --> - <JPanel layout='{new GridLayout(1,0)}' - constraints='BorderLayout.SOUTH'> - <JButton id='reset' onActionPerformed='model.reset()'/> - <JButton id='save' onActionPerformed='model.saveModified()'/> - </JPanel> - </JPanel> - - <JPopupMenu id='tablePopup'> - <JMenuItem id='copyCellValue' onActionPerformed='handler.copyCellValue()'/> - <JMenuItem id='resetOptionValue' onActionPerformed='handler.resetOptionValue()'/> - </JPopupMenu> -</JPanel> diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigCategoryUIHandler.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigCategoryUIHandler.java deleted file mode 100644 index dd43f0f..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigCategoryUIHandler.java +++ /dev/null @@ -1,266 +0,0 @@ -package jaxx.runtime.swing.config; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.swing.config.model.ConfigTableModel; -import jaxx.runtime.swing.config.model.OptionModel; -import jaxx.runtime.swing.renderer.ClassTableCellRenderer; -import jaxx.runtime.swing.renderer.ColorCellRenderer; -import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.JXTable; - -import javax.swing.JLabel; -import javax.swing.JPopupMenu; -import javax.swing.JTable; -import javax.swing.JTextArea; -import javax.swing.ListSelectionModel; -import javax.swing.SwingUtilities; -import javax.swing.table.TableCellRenderer; -import java.awt.Color; -import java.awt.Component; -import java.awt.Font; -import java.awt.Point; -import java.awt.event.MouseEvent; - -import static org.nuiton.i18n.I18n.n; -import static org.nuiton.i18n.I18n.t; - -/** - * Handler of {@link ConfigCategoryUI}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class ConfigCategoryUIHandler { - - /** Logger. */ - private static final Log log = - LogFactory.getLog(ConfigCategoryUIHandler.class); - - private final ConfigCategoryUI ui; - - public ConfigCategoryUIHandler(ConfigCategoryUI ui) { - this.ui = ui; - } - - public void init() { - - JTable table = ui.getTable(); - - // prepare table - SwingUtil.setI18nTableHeaderRenderer( - table, - n("config.key"), - n("config.key.tip"), - n("config.value"), - n("config.value.tip"), - n("config.defaultValue"), - n("config.defaultValue.tip")); - - ConfigTableRenderer renderer = new ConfigTableRenderer(); - SwingUtil.setTableColumnRenderer(table, 0, renderer); - SwingUtil.setTableColumnRenderer(table, 1, renderer); - SwingUtil.setTableColumnRenderer(table, 2, renderer); - Font f = table.getFont().deriveFont(Font.ITALIC | Font.BOLD); - int width = SwingUtil.computeTableColumnWidth(table, f, 0, "___*"); - SwingUtil.fixTableColumnWidth(table, 0, width); - SwingUtil.setTableColumnEditor(table, 1, new ConfigTableEditor((ConfigTableModel) table.getModel())); - table.setDefaultRenderer(Color.class, new ColorCellRenderer()); - table.setDefaultRenderer(Class.class, new ClassTableCellRenderer()); - } - - public void updateDescriptionText() { - OptionModel option; - JTable table = ui.getTable(); - JTextArea description = ui.getDescription(); - ListSelectionModel selectionModel = ui.getSelectionModel(); - - if (selectionModel.isSelectionEmpty()) { - option = null; - } else { - int row = selectionModel.getAnchorSelectionIndex(); - ConfigTableModel m = (ConfigTableModel) table.getModel(); - option = m.getEntry(row); - if (log.isDebugEnabled()) { - log.debug(row + " : " + option); - } - } - StringBuilder buffer = new StringBuilder(); - if (option == null) { - buffer.append(t("config.no.option.selected")); - } else { - buffer.append(t("config.option.label", option.getKey(), t(option.getDescription()))).append('\n'); - if (option.isModified()) { - String oValue = option.toString(option.getOriginalValue()); - String mValue = option.toString(option.getValue()); - buffer.append(t("config.option.modified", oValue, mValue)).append('\n'); - } - if (option.isFinal()) { - buffer.append(t("config.option.final")).append('\n'); - } - } - description.setText(buffer.toString()); - } - - public void copyCellValue() { - - JXTable table = ui.getTable(); - - int[] selectedRows = table.getSelectedRows(); - - int selectedRow = selectedRows[0]; - - Integer selectedColumn = (Integer) ui.getCopyCellValue().getClientProperty("selectedColumn"); - - ConfigTableModel tableModel = ui.getTableModel(); - OptionModel optionModel = tableModel.getEntry(selectedRow); - - Object value = null; - switch (selectedColumn) { - case 1: - if (log.isInfoEnabled()) { - log.info("Will copy option value from " + optionModel.getKey()); - } - value = optionModel.getValue(); - break; - case 2: - if (log.isInfoEnabled()) { - log.info("Will copy option default value from " + optionModel.getKey()); - } - value = optionModel.getOriginalValue(); - break; - } - - String text = ""; - if (value != null) { - TableCellRenderer cellRenderer = table.getCellRenderer(selectedRow, selectedColumn); - Component tableCellRendererComponent = cellRenderer.getTableCellRendererComponent(table, value, false, false, selectedRow, selectedColumn); - - text = ((JLabel) tableCellRendererComponent).getText(); - } - - if (log.isInfoEnabled()) { - log.info("Copy to clipboard cell (" + selectedRow + "-" + selectedColumn + ") value: \"" + text + "\""); - } - - JAXXUtil.copyToClipBoard(text); - - } - - public void resetOptionValue() { - - JXTable table = ui.getTable(); - - int[] selectedRows = table.getSelectedRows(); - - int selectedRow = selectedRows[0]; - - ConfigTableModel tableModel = ui.getTableModel(); - OptionModel optionModel = tableModel.getEntry(selectedRow); - - if (log.isInfoEnabled()) { - log.info("Will reset option: " + optionModel.getKey()); - } - tableModel.setValueAt(optionModel.getDefaultValue(), selectedRow, 1); - - } - - public void openTablePopupMenu(MouseEvent e, JPopupMenu popup) { - - boolean rightClick = SwingUtilities.isRightMouseButton(e); - - if (rightClick) { - - JXTable source = (JXTable) e.getSource(); - - int[] selectedRows = source.getSelectedRows(); - int[] selectedColumns = source.getSelectedColumns(); - - // get the coordinates of the mouse click - Point p = e.getPoint(); - - // get the row index at this point - int rowIndex = source.rowAtPoint(p); - - // get the column index at this point - int columnIndex = source.columnAtPoint(p); - - // select row (could empty selection) - if (rowIndex == -1) { - source.clearSelection(); - } else if (!ArrayUtils.contains(selectedRows, rowIndex)) { - - // set selection - source.setRowSelectionInterval(rowIndex, rowIndex); - } - - // select column (could empty selection) - if (columnIndex == -1) { - source.clearSelection(); - } else if (!ArrayUtils.contains(selectedColumns, columnIndex)) { - source.setColumnSelectionInterval(columnIndex, columnIndex); - } - - int selectedRowCount = source.getSelectedRowCount(); - - boolean enableCopyOptionValue = selectedRowCount == 1; - boolean enableResetOptionValue = selectedRowCount > 0; - - if (log.isDebugEnabled()) { - log.debug("At point [" + p + "] found Row " + rowIndex + ", Column " + columnIndex); - } - - boolean canContinue = true; - - if (source.isEditing()) { - - // stop editing - boolean stopEdit = source.getCellEditor().stopCellEditing(); - if (!stopEdit) { - if (log.isWarnEnabled()) { - log.warn("Could not stop edit cell..."); - } - canContinue = false; - } - } - - int selectedColumn = source.getSelectedColumn(); - ui.getCopyCellValue().putClientProperty("selectedColumn", selectedColumn); - - ui.getCopyCellValue().setEnabled(enableCopyOptionValue); - ui.getResetOptionValue().setEnabled(enableResetOptionValue); - - if (canContinue) { - - // on right click show popup - popup.show(source, e.getX(), e.getY()); - - } - } - } - -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigTableEditor.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigTableEditor.java deleted file mode 100644 index 27e9ec4..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigTableEditor.java +++ /dev/null @@ -1,173 +0,0 @@ -package jaxx.runtime.swing.config; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.io.Files; -import jaxx.runtime.swing.JAXXWidgetUtil; -import jaxx.runtime.swing.config.model.ConfigTableModel; -import jaxx.runtime.swing.config.model.OptionModel; -import jaxx.runtime.swing.editor.ClassCellEditor; -import jaxx.runtime.swing.editor.ColorCellEditor; -import jaxx.runtime.swing.editor.EnumEditor; -import jaxx.runtime.swing.editor.LocaleEditor; -import jaxx.runtime.swing.editor.cell.FileCellEditor; -import org.apache.commons.lang3.StringUtils; - -import javax.swing.DefaultCellEditor; -import javax.swing.JTable; -import javax.swing.KeyStroke; -import javax.swing.event.CellEditorListener; -import javax.swing.table.TableCellEditor; -import java.awt.Color; -import java.awt.Component; -import java.io.File; -import java.util.EventObject; -import java.util.Locale; - -/** - * L'éditeur des valeurs des propriétés d'une configuration - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class ConfigTableEditor implements TableCellEditor { - - protected TableCellEditor delegate; - - protected ConfigTableModel model; - - public ConfigTableEditor(ConfigTableModel model) { - this.model = model; - } - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - delegate = findDelegate(table, model.getEntry(row)); - return delegate.getTableCellEditorComponent(table, value, isSelected, row, column); - } - - @Override - public Object getCellEditorValue() { - return !hasDelegate() ? null : delegate.getCellEditorValue(); - } - - @Override - public boolean isCellEditable(EventObject anEvent) { - return !hasDelegate() || delegate.isCellEditable(anEvent); - } - - @Override - public boolean shouldSelectCell(EventObject anEvent) { - return hasDelegate() && delegate.shouldSelectCell(anEvent); - } - - @Override - public boolean stopCellEditing() { - return !hasDelegate() || delegate.stopCellEditing(); - } - - @Override - public void cancelCellEditing() { - if (hasDelegate()) { - delegate.cancelCellEditing(); - } - } - - @Override - public void addCellEditorListener(CellEditorListener l) { - if (hasDelegate()) { - delegate.addCellEditorListener(l); - } - } - - @Override - public void removeCellEditorListener(CellEditorListener l) { - if (hasDelegate()) { - delegate.removeCellEditorListener(l); - } - } - - protected TableCellEditor findDelegate(JTable table, OptionModel option) { - Class<?> type = option.getType(); - if (char.class.equals(type)) { - type = String.class; - } - TableCellEditor editor = table.getDefaultEditor(type); - TableCellEditor defaultEditor = table.getDefaultEditor(Object.class); - // always Search from option.getEditor() and store editor as cache - if (option.getEditor() != null) { - editor = option.getEditor(); - table.setDefaultEditor(type, editor); - - } else if (editor.equals(defaultEditor)) { - // find not a specialized editor for the type - if (type.isEnum()) { - // add a EnumEditor to table - editor = new DefaultCellEditor(EnumEditor.newEditor((Class<Enum>) type)); - - } else if (type.equals(Class.class)) { - editor = new ClassCellEditor(); - - } else if (type.equals(File.class)) { - editor = new FileCellEditorWithExtDetector(); - - } else if (type.equals(KeyStroke.class)) { - editor = JAXXWidgetUtil.newKeyStrokeTableCellEditor(); - - } else if (type.equals(Locale.class)) { - editor = new DefaultCellEditor(LocaleEditor.newEditor()); - - } else if (type.equals(Color.class)) { - editor = new ColorCellEditor(); - - } else { - editor = table.getDefaultEditor(String.class); - } - table.setDefaultEditor(type, editor); - } - if (editor == null) { - throw new IllegalStateException("could not find a editor for type +" + type); - } - return editor; - } - - protected static class FileCellEditorWithExtDetector extends FileCellEditor { - - private static final long serialVersionUID = 1L; - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - - String fileExtension = value == null ? null : Files.getFileExtension(((File) value).getName()); - if (StringUtils.isNotEmpty(fileExtension)) { - fileEditor.setExts(fileExtension); - fileEditor.setAcceptAllFileFilterUsed(true); - } - return super.getTableCellEditorComponent(table, value, isSelected, row, column); - } - } - - protected boolean hasDelegate() { - return delegate != null; - } -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigTableRenderer.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigTableRenderer.java deleted file mode 100644 index 57e87b8..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigTableRenderer.java +++ /dev/null @@ -1,126 +0,0 @@ -package jaxx.runtime.swing.config; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.swing.config.model.ConfigTableModel; -import jaxx.runtime.swing.config.model.OptionModel; - -import javax.swing.JComponent; -import javax.swing.JTable; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableCellRenderer; -import java.awt.Color; -import java.awt.Component; -import java.awt.Font; - -import static org.nuiton.i18n.I18n.t; - -/** - * Pour le rendu du tableau des options d'une categorie - * - * @author Tony Chemit - chemit@codelutin.com - * @see ConfigTableModel - * @since 2.5.11 - */ -public class ConfigTableRenderer extends DefaultTableCellRenderer { - - private static final long serialVersionUID = 1L; - - protected static Color col; - - protected static Font font; - - protected static Font font2; - - public ConfigTableRenderer() { - col = getForeground(); - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - int modelRow = table.convertRowIndexToModel(row); - int modelColumn = table.convertColumnIndexToModel(column); - ConfigTableModel model = (ConfigTableModel) table.getModel(); - OptionModel key = model.getEntry(modelRow); - boolean isModified = key.isModified(); - - boolean isValid = key.isValid(); - - if (font == null) { - font = getFont(); - font2 = font.deriveFont(Font.ITALIC | Font.BOLD); - } - Component cellRenderer; - switch (modelColumn) { - case 0: - cellRenderer = getKeyCellRenderer(table, value, isSelected, hasFocus, modelRow, modelColumn, key, isValid, isModified); - break; - case 1: - cellRenderer = getValueCellRenderer(table, value, isSelected, hasFocus, modelRow, modelColumn, key, isValid, isModified); - break; - case 2: - cellRenderer = getValueCellRenderer(table, value, isSelected, hasFocus, modelRow, modelColumn, key, isValid, isModified); - break; - default: - throw new IllegalStateException("no renderer find for column " + modelColumn); - } - return cellRenderer; - } - - protected Component getKeyCellRenderer(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column, OptionModel key, boolean isValid, boolean isModified) { - String tooltip = t(key.getDescription()) + " (" + key.getKey() + ")"; - String originalValue = key.toString(key.getOriginalValue()); - boolean isFinal = key.isFinal(); - if (isFinal) { - tooltip += " [" + t("config.unmodifiable") + ']'; - } - if (isModified) { - String s = t("config.modified", originalValue); - value = value + " *"; - tooltip += " [" + s + ']'; - } - if (!isValid) { - String s2 = t("config.unvalid", originalValue, key.getType()); - tooltip += " (" + s2 + ")"; - value = value + " !"; - } - JComponent result = (JComponent) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - result.setToolTipText(tooltip); - result.setForeground(isValid ? col : Color.RED); - result.setFont(isModified || !isValid ? font2 : font); - result.setEnabled(!isFinal); - return result; - } - - protected Component getValueCellRenderer(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column, OptionModel key, boolean isValid, boolean isModified) { - Component result; - if (key.getRenderer() != null) { - result = key.getRenderer().getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - - } else { - TableCellRenderer defaultRenderer = table.getDefaultRenderer(key.getType()); - result = defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - } - return result; - } -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigUI.jaxx b/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigUI.jaxx deleted file mode 100644 index 4597fdd..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigUI.jaxx +++ /dev/null @@ -1,56 +0,0 @@ -<!-- - #%L - JAXX :: Config - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<JPanel layout='{new BorderLayout()}'> - - <import> - jaxx.runtime.swing.config.model.ConfigUIModel - </import> - - <script><![CDATA[ - -public void init(String defaultCategory) { - getHandler().initUI(defaultCategory); -} - -@Override -protected void finalize() throws Throwable { - super.finalize(); - getHandler().destroy(); -} - ]]> - </script> - - <ConfigUIHandler id='handler' constructorParams='this'/> - - <!-- le modele de l'ui --> - <ConfigUIModel id='model' - initializer='getContextValue(ConfigUIModel.class)'/> - - <!-- les differentes categories de la configuration --> - <JTabbedPane id='categories' constraints='BorderLayout.CENTER' - onStateChanged='getHandler().changeCategory(event)'/> - - <!-- pour quitter l'ui --> - <JPanel layout='{new GridLayout(1,0)}' constraints='BorderLayout.SOUTH'> - <JButton id='quit'/> - </JPanel> -</JPanel> diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigUIHandler.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigUIHandler.java deleted file mode 100644 index edbcc7a..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigUIHandler.java +++ /dev/null @@ -1,433 +0,0 @@ -package jaxx.runtime.swing.config; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.context.JAXXInitialContext; -import jaxx.runtime.swing.config.model.CallBackEntry; -import jaxx.runtime.swing.config.model.CallBackMap; -import jaxx.runtime.swing.config.model.CategoryModel; -import jaxx.runtime.swing.config.model.ConfigUIModel; -import jaxx.runtime.swing.config.model.OptionModel; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.DefaultSingleSelectionModel; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JRootPane; -import javax.swing.JTabbedPane; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; -import javax.swing.event.ChangeEvent; -import java.awt.Container; -import java.awt.Frame; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.util.ArrayList; - -import static org.nuiton.i18n.I18n.t; - -/** - * Handler of the {@link ConfigUI} ui. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class ConfigUIHandler { - - public static final Log log = LogFactory.getLog(ConfigUIHandler.class); - - public static final String CALLBACKS_WITH_OPTIONS = "callbacksWithOptions"; - - public static final String CALLBACKS = "callbacks"; - - public static final String QUIT_ACTION = "quit"; - - private final ConfigUI ui; - - /** - * Set this container if you want to use the ui inside another one (a.k.a not in standalone mode). - */ - private Container topContainer; - - - /** - * To customize the config call back ui before showning it. - * - * @since 2.37 - */ - private ConfigCallBackUICustomizer configCallBackUICustomizer; - - /** - * To be able to veto a change of a category. - * - * @since 2.6 - */ - public static interface ChangeCategoryCallBack { - boolean canChangeCategory(String categoryName); - } - - private ChangeCategoryCallBack changeCategoryCallBack; - - public ConfigUIHandler(ConfigUI ui) { - this.ui = ui; - } - - public void setChangeCategoryCallBack(ChangeCategoryCallBack changeCategoryCallBack) { - this.changeCategoryCallBack = changeCategoryCallBack; - } - - public void initUI(String defaultCategory) { - - ConfigUIModel model = ui.getModel(); - - JTabbedPane categories = ui.getCategories(); - - categories.setModel(new DefaultSingleSelectionModel() { - - private static final long serialVersionUID = 1L; - - @Override - public void setSelectedIndex(int index) { - // check if catgeory can be quit - boolean canContinue = !isSelected() || canQuitCategory(); - if (canContinue) { - // was authorized to leave previous category - if (log.isDebugEnabled()) { - log.debug("new index : " + index); - } - String categoryName = ConfigUIHandler.this.ui.getModel().getCategoryName(index); - if (changeCategoryCallBack == null || changeCategoryCallBack.canChangeCategory(categoryName)) { - // can change category - super.setSelectedIndex(index); - } - } - } - }); - - JButton quitButton = ui.getQuit(); - - // prepare quit action - Action quitAction = createQuitAction(); - - String tip = quitButton.getToolTipText(); - quitButton.setAction(quitAction); - quitButton.setToolTipText(tip); - - // build categories tabs - for (CategoryModel categoryModel : model) { - String category = categoryModel.getCategory(); - String categoryLabel = t(categoryModel.getCategoryLabel()); - ConfigCategoryUI p = new ConfigCategoryUI( - new JAXXInitialContext().add(ui).add(categoryModel)); - p.getCategoryLabel().setText(categoryLabel); - p.setName(category); - categories.addTab(t(category), null, p, categoryLabel); - } - - model.setCategory(defaultCategory); - int categoryIndex = model.getCategoryIndex(defaultCategory); - if (log.isDebugEnabled()) { - log.debug("index of default category (" + defaultCategory + ") : " - + categoryIndex); - } - categories.setSelectedIndex(categoryIndex); - } - - public void destroy() { - if (log.isDebugEnabled()) { - log.debug("destroy ui " + ui.getName()); - } - JAXXUtil.destroy(ui); - ui.getModel().destroy(); - } - - public void changeCategory(ChangeEvent e) { - JPanel p = (JPanel) ui.getCategories().getSelectedComponent(); - if (p == null) { - // pas de selection - return; - } - ui.getModel().setCategory(p.getName()); - ui.getCategories().invalidate(); - } - - public void displayUI(Frame parentUI, boolean undecorated) { - JDialog f = new JDialog(parentUI, true); - f.setTitle(t("config.title")); - f.add(ui); - if (parentUI != null) { - f.setIconImage(parentUI.getIconImage()); - } - // pour savoir si l'ui est autonome - ui.getModel().setStandalone(parentUI == null); - - f.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); - f.addWindowListener(new WindowAdapter() { - - @Override - public void windowClosing(WindowEvent e) { - ActionEvent myEvent = new ActionEvent(e.getSource(), 1, QUIT_ACTION); - ui.getQuit().getAction().actionPerformed(myEvent); - } - }); - f.setUndecorated(undecorated); - JRootPane rootPane = f.getRootPane(); - rootPane.setDefaultButton(ui.getQuit()); - rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( - KeyStroke.getKeyStroke("ESCAPE"), QUIT_ACTION); - rootPane.getActionMap().put(QUIT_ACTION, ui.getQuit().getAction()); - f.pack(); - SwingUtil.center(parentUI, f); - f.setVisible(true); - } - - protected Action createQuitAction() { - - JButton button = ui.getQuit(); - - return new AbstractAction(button.getText(), - button.getIcon()) { - - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent e) { - if (!canQuitCategory()) { - return; - } - - Window parentWindow; - - final Container parentContainer; - - if (topContainer == null) { - - // no top container given, still use the parent frame - - parentWindow = ui.getParentContainer(Window.class); - parentContainer = parentWindow; - - } else { - - // use only given topContainer - parentWindow = null; - parentContainer = topContainer; - } - - ConfigUIModel model = ui.getModel(); - if (!model.isSaved() || model.isStandalone()) { - - // just quit, no callBack can be apply here - closeUI(parentWindow, model); - return; - } - - CallBackMap forSaved = model.getCallBacksForSaved(); - - if (forSaved.isEmpty()) { - - // just quit, no callBack to call - closeUI(parentWindow, model); - return; - } - - forSaved = model.getCallBacksForSaved(); - - // init callBackUI - - JAXXInitialContext context = new JAXXInitialContext(). - add(ui). - add(CALLBACKS_WITH_OPTIONS, forSaved). - add(CALLBACKS, - new ArrayList<CallBackEntry>(forSaved.keySet())). - add(new ConfigCallBackUIHandler()); - - if (topContainer == null) { - - // still add parent window (to close ui) - context.add("parent", parentWindow); - } - - ConfigCallBackUI lastUI = new ConfigCallBackUI(context); - lastUI.init(); - - if (configCallBackUICustomizer != null) { - configCallBackUICustomizer.customize(lastUI); - } - ui.setVisible(false); - parentContainer.remove(ui); - parentContainer.add(lastUI); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - parentContainer.validate(); - } - }); - } - }; - } - - public void setConfigCallBackUICustomizer(ConfigCallBackUICustomizer configCallBackUICustomizer) { - this.configCallBackUICustomizer = configCallBackUICustomizer; - } - - /** - * To customize config call back ui. - * - * @since 2.37 - */ - public interface ConfigCallBackUICustomizer { - - void customize(ConfigCallBackUI callBackUI); - } - - - protected void closeUI(Window parentWindow, ConfigUIModel model) { - - destroy(); - - if (parentWindow != null) { - - // close the config ui - parentWindow.dispose(); - } - - Runnable runnable = model.getCloseAction(); - if (runnable != null) { - log.info("execute close action"); - runnable.run(); - } - } - - protected boolean canQuitCategory() { - boolean canContinue = true; - ConfigUIModel model = ui.getModel(); - CategoryModel categoryModel = model.getCategoryModel(); - String categoryName = t(categoryModel.getCategory()); - if (!categoryModel.isValid()) { - - // the category is not valid - // get all the invalid options - - StringBuilder buffer = new StringBuilder(); - buffer.append(t("config.message.quit.invalid.category", - categoryName)); - buffer.append('\n'); - for (OptionModel m : categoryModel.getInvalidOptions()) { - buffer.append("\n- ").append(m.getKey()); - } - buffer.append('\n'); - int reponse = askUser(t("config.title.need.confirm"), - buffer.toString(), - JOptionPane.ERROR_MESSAGE, - new Object[]{ - t("config.choice.continue"), - t("config.choice.cancel")}, - 0); - - switch (reponse) { - case JOptionPane.CLOSED_OPTION: - case 1: - canContinue = false; - break; - case 0: - if (categoryModel.isModified()) { - // wil reset category - model.reset(); - } - break; - } - } else if (categoryModel.isModified()) { - - // category was modified, ask user if wants to save - - StringBuilder buffer = new StringBuilder(); - buffer.append(t("config.message.quit.valid.and.modified.category", - categoryName)).append('\n'); - for (OptionModel m : categoryModel.getModifiedOptions()) { - buffer.append("\n- ").append(m.getKey()); - } - buffer.append('\n'); - - int reponse = askUser(t("config.title.need.confirm"), - buffer.toString(), - JOptionPane.WARNING_MESSAGE, - new Object[]{ - t("config.choice.save"), - t("config.choice.doNotSave"), - t("config.choice.cancel")}, - 0); - - switch (reponse) { - case JOptionPane.CLOSED_OPTION: - case 2: - canContinue = false; - break; - case 0: - // will save ui - model.saveModified(); - break; - case 1: - // wil reset ui - model.reset(); - break; - } - } - return canContinue; - } - - public int askUser(String title, - String message, - int typeMessage, - Object[] options, - int defaultOption) { - - return JOptionPane.showOptionDialog( - ui, - message, - title, - JOptionPane.DEFAULT_OPTION, - typeMessage, - null, - options, - options[defaultOption] - ); - } - - public void setTopContainer(Container topContainer) { - this.topContainer = topContainer; - } - -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigUIHelper.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigUIHelper.java deleted file mode 100644 index 455ec75..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigUIHelper.java +++ /dev/null @@ -1,221 +0,0 @@ -package jaxx.runtime.swing.config; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Preconditions; -import com.google.common.base.Supplier; -import jaxx.runtime.JAXXContext; -import jaxx.runtime.context.JAXXInitialContext; -import jaxx.runtime.swing.config.model.CallBackFinalizer; -import jaxx.runtime.swing.config.model.CategoryModel; -import jaxx.runtime.swing.config.model.ConfigUIModel; -import jaxx.runtime.swing.config.model.ConfigUIModelBuilder; -import jaxx.runtime.swing.config.model.OptionModel; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.config.ApplicationConfig; -import org.nuiton.config.ConfigOptionDef; - -import javax.swing.Icon; -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableCellRenderer; -import java.awt.Frame; -import java.io.File; - -/** - * A helper to build a config ui. - * - * contains all states as method to build model, then ui and finally display it. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class ConfigUIHelper { - - public static final Log log = LogFactory.getLog(ConfigUIHelper.class); - - /** internal model builder */ - protected final ConfigUIModelBuilder modelBuilder; - - /** internal model after builder flush */ - protected ConfigUIModel model; - - protected ConfigUI ui; - - public ConfigUIHelper(Object configurationBean, ApplicationConfig config, File configFile) { - modelBuilder = new ConfigUIModelBuilder(); - modelBuilder.createModel(configurationBean, config, configFile); - } - - @Deprecated - public ConfigUIHelper(Supplier<ApplicationConfig> config) { - modelBuilder = new ConfigUIModelBuilder(); - modelBuilder.createModel(config, config.get(), config.get().getUserConfigFile()); - } - - @Deprecated - public ConfigUIHelper(Supplier<ApplicationConfig> config, File configFile) { - modelBuilder = new ConfigUIModelBuilder(); - modelBuilder.createModel(config, config.get(), configFile); - } - - @Deprecated - public ConfigUIHelper(Object configurationBean, ApplicationConfig config) { - modelBuilder = new ConfigUIModelBuilder(); - modelBuilder.createModel(configurationBean, config, config.getUserConfigFile()); - } - - @Deprecated - public ConfigUIHelper(ApplicationConfig config, File configFile) { - modelBuilder = new ConfigUIModelBuilder(); - modelBuilder.createModel(config, config, configFile); - } - - @Deprecated - public ConfigUIHelper(ApplicationConfig config) { - modelBuilder = new ConfigUIModelBuilder(); - modelBuilder.createModel(config, config, config.getUserConfigFile()); - } - - public ConfigUIModel getModel() { - if (model == null) { - model = modelBuilder.flushModel(); - } - return model; - } - - public ConfigUIModelBuilder addCategory(String categoryName, String categoryLabel) - throws IllegalStateException, NullPointerException { - modelBuilder.addCategory(categoryName, categoryLabel); - return modelBuilder; - } - - public ConfigUIModelBuilder addCategory(String categoryName, String categoryLabel, String categoryCallback) - throws IllegalStateException, NullPointerException { - modelBuilder.addCategory(categoryName, categoryLabel, categoryCallback); - return modelBuilder; - } - - public ConfigUIModelBuilder addOption(ConfigOptionDef def) - throws IllegalStateException, NullPointerException { - modelBuilder.addOption(def); - return modelBuilder; - } - - @Deprecated - public ConfigUIModelBuilder addOption(ConfigOptionDef def, String propertyName) - throws IllegalStateException, NullPointerException { - modelBuilder.addOption(def, propertyName); - return modelBuilder; - } - - public ConfigUIModelBuilder setOptionPropertyName(String propertyName) - throws IllegalStateException, NullPointerException { - modelBuilder.setOptionPropertyName(propertyName); - return modelBuilder; - } - - public ConfigUIModelBuilder setOptionShortLabel(String shortLabel) - throws IllegalStateException, NullPointerException { - modelBuilder.setOptionShortLabel(shortLabel); - return modelBuilder; - } - - public ConfigUIModelBuilder setOptionEditor(TableCellEditor editor) - throws IllegalStateException, NullPointerException { - modelBuilder.setOptionEditor(editor); - return modelBuilder; - } - - public ConfigUIModelBuilder setOptionRenderer(TableCellRenderer renderer) - throws IllegalStateException, NullPointerException { - modelBuilder.setOptionRenderer(renderer); - return modelBuilder; - } - - public ConfigUIModelBuilder registerCallBack(String name, - String description, - Icon icon, - Runnable action) { - modelBuilder.registerCallBack(name, description, icon, action); - return modelBuilder; - } - - public ConfigUIModelBuilder setOptionCallBack(String name) { - modelBuilder.setOptionCallBack(name); - return modelBuilder; - } - - public ConfigUIModelBuilder setModel(ConfigUIModel model) throws IllegalStateException { - modelBuilder.setModel(model); - return modelBuilder; - } - - public ConfigUIModelBuilder setCategory(CategoryModel categoryModel) - throws IllegalStateException { - modelBuilder.setCategory(categoryModel); - return modelBuilder; - } - - public ConfigUIModelBuilder setOption(OptionModel optionModel) - throws IllegalStateException { - modelBuilder.setOption(optionModel); - return modelBuilder; - } - - public ConfigUIModelBuilder setFinalizer(CallBackFinalizer finalizer) { - modelBuilder.setFinalizer(finalizer); - return modelBuilder; - } - - public ConfigUIModelBuilder setCloseAction(Runnable runnable) { - modelBuilder.setCloseAction(runnable); - return modelBuilder; - } - - /** - * Construire l'ui de configuration (sous forme de panel) - * - * @param parentContext le context applicatif - * @param defaultCategory la categorie a selectionner - * @return l'ui instanciate - */ - public ConfigUI buildUI(JAXXContext parentContext, - String defaultCategory) { - - ConfigUIModel model = getModel(); - - JAXXContext tx = new JAXXInitialContext().add(parentContext).add(model); - - ui = new ConfigUI(tx); - - ui.init(defaultCategory); - - return ui; - } - - public void displayUI(Frame parentUI, boolean undecorated) { - Preconditions.checkNotNull(ui, "UI was not build, use before the *buildUI* method"); - ui.getHandler().displayUI(parentUI, undecorated); - } -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CallBackEntry.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CallBackEntry.java deleted file mode 100644 index e5ccc77..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CallBackEntry.java +++ /dev/null @@ -1,79 +0,0 @@ -package jaxx.runtime.swing.config.model; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import javax.swing.*; -import java.util.ArrayList; -import java.util.List; - -/** - * A call back with his attached options. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class CallBackEntry { - - protected final String name; - protected final String description; - protected final Icon icon; - protected final Runnable action; - protected List<OptionModel> options; - - public CallBackEntry(String name, - String description, - Icon icon, - Runnable action) { - this.description = description; - this.icon = icon; - options = new ArrayList<OptionModel>(); - this.name = name; - this.action = action; - } - - public Runnable getAction() { - return action; - } - - public String getName() { - return name; - } - - public String getDescription() { - return description; - } - - public Icon getIcon() { - return icon; - } - - public List<OptionModel> getOptions() { - // always send a copy - return new ArrayList<OptionModel>(options); - } - - protected void addOption(OptionModel option) { - options.add(option); - - } -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CallBackFinalizer.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CallBackFinalizer.java deleted file mode 100644 index 38b89e2..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CallBackFinalizer.java +++ /dev/null @@ -1,40 +0,0 @@ -package jaxx.runtime.swing.config.model; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -/** - * Contract to finalize the callbacks to launch. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public interface CallBackFinalizer { - - /** - * Do finalize the result. - * - * @param result unfinalized result - * @return the finalized result - */ - CallBackMap finalize(CallBackMap result); -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CallBackMap.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CallBackMap.java deleted file mode 100644 index 9ebe904..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CallBackMap.java +++ /dev/null @@ -1,56 +0,0 @@ -package jaxx.runtime.swing.config.model; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import java.util.LinkedHashMap; -import java.util.List; - -/** - * A convient map of callback entry for a list of option. - * - * This model is used to store callbacks to use before a saving action. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class CallBackMap extends LinkedHashMap<CallBackEntry, List<OptionModel>> { - private static final long serialVersionUID = 1L; - - public boolean containsCallBack(String callBackName) { - for (CallBackEntry entry : keySet()) { - if (callBackName.equals(entry.getName())) { - return true; - } - } - return false; - } - - public CallBackEntry getCallBack(String callBackName) { - for (CallBackEntry entry : keySet()) { - if (callBackName.equals(entry.getName())) { - return entry; - } - } - return null; - } -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CallBacksManager.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CallBacksManager.java deleted file mode 100644 index 4a4db2b..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CallBacksManager.java +++ /dev/null @@ -1,248 +0,0 @@ -package jaxx.runtime.swing.config.model; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import javax.swing.*; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * CallBack manager. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class CallBacksManager { - - /** lists of registred callback. */ - protected List<CallBackEntry> callbacks; - - /** optional callbacks finalizer */ - protected CallBackFinalizer finalizer; - - public CallBacksManager() { - callbacks = new ArrayList<CallBackEntry>(); - } - - /** - * Obtain the finalizer to use. - * - * @return the finalizer (can be {@code null}). - * @see CallBackFinalizer - */ - public CallBackFinalizer getFinalizer() { - return finalizer; - } - - /** - * Sets the finalizer. - * - * @param finalizer the new finalizer - * @see CallBackFinalizer - */ - public void setFinalizer(CallBackFinalizer finalizer) { - this.finalizer = finalizer; - } - - /** - * Registers a new callback. - * - * <b>Note:</b> the order of registred callback is used to determine - * the higher priority of callback to launch if required. - * - * @param name the unique name of a callback - * @param description the i18n key to describe the action - * @param icon icon of callBack (used in ui) - * @param action the action of the callback - */ - public void registerCallBack(String name, - String description, - Icon icon, - Runnable action) { - if (name == null) { - throw new NullPointerException( - "parameter 'name' can not be null"); - } - if (action == null) { - throw new NullPointerException( - "parameter 'action' can not be null"); - } - if (description == null) { - throw new NullPointerException( - "parameter 'description' can not be null"); - } - if (icon == null) { - throw new NullPointerException("parameter 'icon' can not be null"); - } - if (getCallBack(name) != null) { - throw new IllegalArgumentException( - "there is already a callback with name '" + name + "'"); - } - callbacks.add(new CallBackEntry(name, description, icon, action)); - } - - /** - * Registers a option into a known callback. - * - * @param name the name of the callback - * @param option the option to register for the given callback - */ - public void registerOption(String name, OptionModel option) { - if (name == null) { - throw new NullPointerException("parameter 'name' can not be null"); - } - if (option == null) { - throw new NullPointerException( - "parameter 'option' can not be null"); - } - CallBackEntry callback = getCallBack(name); - if (callback == null) { - throw new IllegalArgumentException( - "could not find a callback with name '" + name + "'"); - } - callback.addOption(option); - } - - /** - * Scan a model and grab per callBack the options saved. - * - * @param model the model to scan - * @return the dictionnary of options for each callback to launch - */ - public CallBackMap getCallBacksForSaved(ConfigUIModel model) { - - return getCallBacks(model, true, false); - } - - /** - * Scan a category and grab per callBack the options saved. - * - * @param category the category to scan - * @return the dictionnary of options for each callBack to launch - */ - public CallBackMap getCallBacksForSaved(CategoryModel category) { - - return getCallBacks(category, true, false); - } - - /** - * Scan a model and grab per callBack the options. - * - * @param model the model to scan - * @param modified {@code true} to include modified options - * @param saved {@code true} to include saved options - * @return the dictionnary of options for each callback to launch - */ - public CallBackMap getCallBacks(ConfigUIModel model, - boolean saved, - boolean modified) { - - CallBackMap result = new CallBackMap(); - - for (CategoryModel categoryModel : model) { - CallBackMap callBacks = - getCallBacks(categoryModel, saved, modified); - for (Map.Entry<CallBackEntry, List<OptionModel>> entry : - callBacks.entrySet()) { - CallBackEntry key = entry.getKey(); - List<OptionModel> value = entry.getValue(); - if (result.containsKey(key)) { - result.get(key).addAll(value); - } else { - result.put(key, value); - } - } - callBacks.clear(); - } - - CallBackFinalizer finalizer = getFinalizer(); - if (finalizer != null) { - result = finalizer.finalize(result); - } - return result; - } - - /** - * Scan a category and grab per callBack the options. - * - * @param category the category to scan - * @param modified {@code true} to include modified options - * @param saved {@code true} to include saved options - * @return the dictionnary of options for each callBack to launch - */ - public CallBackMap getCallBacks(CategoryModel category, - boolean saved, - boolean modified) { - - CallBackMap result = new CallBackMap(); - - for (OptionModel optionModel : category) { - if (modified && optionModel.isModified() || - saved && optionModel.isSaved()) { - CallBackEntry callBackEntry = getCallBack(optionModel); - if (callBackEntry != null) { - List<OptionModel> models = result.get(callBackEntry); - if (models == null) { - models = new ArrayList<OptionModel>(); - result.put(callBackEntry, models); - } - models.add(optionModel); - } - } - } - return result; - } - - /** - * Get the first callBack for a given option. - * - * @param option the option - * @return the first callBack (so the most important) on which the given - * option is attacjed. (can be null) - */ - protected CallBackEntry getCallBack(OptionModel option) { - for (CallBackEntry callback : callbacks) { - if (callback.getOptions().contains(option)) { - return callback; - } - } - return null; - } - - /** - * Obtain a registred callBack from his name. - * - * @param name the name of the searched callBack - * @return the callBack for the given name (or {@code null} if not found). - */ - protected CallBackEntry getCallBack(String name) { - for (CallBackEntry callback : callbacks) { - if (callback.getName().equals(name)) { - return callback; - } - } - return null; - } - -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CategoryModel.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CategoryModel.java deleted file mode 100644 index b43c89b..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/CategoryModel.java +++ /dev/null @@ -1,223 +0,0 @@ -package jaxx.runtime.swing.config.model; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.JAXXUtil; - -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -/** - * le modele d'une categorie d'options. - * - * Une categorie est un ensemble d'options. - * - * @author tchemit - * @since 2.5.11 - */ -public class CategoryModel implements Iterable<OptionModel>, Serializable { - - private static final long serialVersionUID = 1L; - - public static final String RELOAD_PROPERTY_NAME = "reload"; - - public static final String MODIFIED_PROPERTY_NAME = "modified"; - - public static final String VALID_PROPERTY_NAME = "valid"; - - /** category short name (i18n key) */ - protected String category; - - /** category long name (i18n key) */ - protected String categoryLabel; - - /** options of the category */ - protected List<OptionModel> entries; - - /** suport of modification */ - protected PropertyChangeSupport pcs = new PropertyChangeSupport(this); - - protected CategoryModel(String category, String categoryLabel) { - this.category = category; - this.categoryLabel = categoryLabel; - entries = new ArrayList<OptionModel>(); - } - - protected void addOption(OptionModel option) { - entries.add(option); - } - - @Deprecated - public CategoryModel(String category, - String categoryLabel, - OptionModel[] entries) { - this.category = category; - this.categoryLabel = categoryLabel; - this.entries = Collections.unmodifiableList(Arrays.asList(entries)); - } - - public String getCategory() { - return category; - } - - public String getCategoryLabel() { - return categoryLabel; - } - - public List<OptionModel> getEntries() { - return entries; - } - - public boolean isModified() { - boolean modified = false; - for (OptionModel m : this) { - if (m.isModified()) { - modified = true; - break; - } - } - return modified; - } - - public boolean isValid() { - boolean valid = true; - for (OptionModel m : this) { - if (!m.isValid()) { - valid = false; - break; - } - } - return valid; - } - - public OptionModel getOptionModel(String optionModelKey) { - OptionModel result = null; - for (OptionModel optionModel : this) { - if (optionModelKey.endsWith(optionModel.getKey())) { - result = optionModel; - break; - } - } - return result; - } - public void setValue(OptionModel key, Object val) { - boolean wasModified = isModified(); - boolean wasValid = isValid(); - key.setValue(val); - boolean modified = isModified(); - boolean valid = isValid(); - if (wasModified != modified) { - // change modified state - firePropertyChange(MODIFIED_PROPERTY_NAME, wasModified, modified); - } - if (wasValid != valid) { - // change valid state - firePropertyChange(VALID_PROPERTY_NAME, wasValid, valid); - } - } - - @Override - public Iterator<OptionModel> iterator() { - return entries.iterator(); - } - - public List<OptionModel> getInvalidOptions() { - - List<OptionModel> result = new ArrayList<OptionModel>(); - for (OptionModel m : this) { - if (!m.isValid()) { - result.add(m); - } - } - return result; - } - - public List<OptionModel> getModifiedOptions() { - - List<OptionModel> result = new ArrayList<OptionModel>(); - for (OptionModel m : this) { - if (m.isModified()) { - result.add(m); - } - } - return result; - } - - public List<OptionModel> getSavedOptions() { - List<OptionModel> result = new ArrayList<OptionModel>(); - for (OptionModel option : this) { - if (option.isSaved()) { - result.add(option); - } - } - return result; - } - - public void firePropertyChange(String propertyName, Object oldValue, Object newValue) { - pcs.firePropertyChange(propertyName, oldValue, newValue); - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - pcs.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { - pcs.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - pcs.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { - pcs.removePropertyChangeListener(propertyName, listener); - } - - public boolean hasListeners(String propertyName) { - return pcs.hasListeners(propertyName); - } - - public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) { - return pcs.getPropertyChangeListeners(propertyName); - } - - public PropertyChangeListener[] getPropertyChangeListeners() { - return pcs.getPropertyChangeListeners(); - } - - public void destroy() { - JAXXUtil.destroy(pcs); - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - destroy(); - } -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/ConfigTableModel.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/ConfigTableModel.java deleted file mode 100644 index b8fd5a2..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/ConfigTableModel.java +++ /dev/null @@ -1,155 +0,0 @@ -package jaxx.runtime.swing.config.model; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.lang3.StringUtils; -import org.nuiton.converter.ConverterUtil; - -import javax.swing.table.AbstractTableModel; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -/** - * le modele du tableau d'options pour une categorie donnee. - * - * Le modele se base sur le modele d'une categorie d'option. - * - * @author tchemit - * @see CategoryModel - * @since 2.5.11 - */ -public class ConfigTableModel extends AbstractTableModel { - - private static final long serialVersionUID = 1L; - - private static final Class<?>[] columnClass = {String.class, Object.class, String.class}; - - /** le modele d'une categorie */ - protected final CategoryModel categoryModel; - - public ConfigTableModel(CategoryModel categoryModel) { - this.categoryModel = categoryModel; - // listen of property reload of the category model - // to known when to refresh table - this.categoryModel.addPropertyChangeListener(CategoryModel.RELOAD_PROPERTY_NAME, new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - fireTableDataChanged(); - } - }); - } - - public CategoryModel getCategoryModel() { - return categoryModel; - } - - public OptionModel getEntry(int rowIndex) { - return categoryModel.getEntries().get(rowIndex); - } - - @Override - public int getRowCount() { - return categoryModel.getEntries().size(); - } - - @Override - public int getColumnCount() { - return columnClass.length; - } - - @Override - public Class<?> getColumnClass(int columnIndex) { - return columnClass[columnIndex]; - } - - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - return columnIndex == 1 && !getEntry(rowIndex).isFinal(); - } - - @Override - public Object getValueAt(int row, int column) { - OptionModel key = getEntry(row); - Object value = null; - switch (column) { - case 0: - // try first to use the shortLabel - value = key.getShortLabel(); - if (StringUtils.isBlank((String) value)) { - - // fallback to key - value = key.getKey(); - } - break; - case 1: - value = key.getValue(); - break; - case 2: - value = key.getDefaultValue(); - if (value != null) { - value = ConverterUtil.convert(key.getType(), value); - } - break; - } - return value; - } - - @Override - public void setValueAt(Object aValue, int row, int column) { - if (column != 1) { - // seul la colonne 1 est editable (valeur de l'option) - throw new IllegalArgumentException("can not edit column " + column); - } - OptionModel key = getEntry(row); - Object val; - if (aValue == null || key.getType().equals(aValue.getClass())) { - val = aValue; - } else { - String valStr = String.valueOf(aValue).trim(); - try { - val = ConverterUtil.convert(key.getType(), valStr); - if (val != null && val instanceof Integer) { - if (new Integer(0).equals(val) && !valStr.equals("0")) { - val = null; - } - } - } catch (Exception e) { - val = null; - } - } - categoryModel.setValue(key, val); - fireTableRowsUpdated(row, row); - } - - - public void destroy() { - categoryModel.destroy(); - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - destroy(); - } -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/ConfigUIModel.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/ConfigUIModel.java deleted file mode 100644 index c3b3760..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/ConfigUIModel.java +++ /dev/null @@ -1,443 +0,0 @@ -package jaxx.runtime.swing.config.model; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Joiner; -import com.google.common.base.Supplier; -import com.google.common.collect.Lists; -import jaxx.runtime.JAXXUtil; -import org.apache.commons.beanutils.PropertyUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.config.ApplicationConfig; - -import javax.swing.Icon; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import static org.nuiton.i18n.I18n.t; - -/** - * Le modele de l'ui des preferences. - * - * Ce modele contient les catégories des options. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class ConfigUIModel implements Iterable<CategoryModel> { - - /** Logger. */ - private static final Log log = LogFactory.getLog(ConfigUIModel.class); - - public static final String CATEGORY_MODEL_PROPERTY_NAME = "categoryModel"; - - /** le dictionnaire des options disponibles par categorie */ - protected final Map<String, CategoryModel> categories; - - /** - * Le fichier où sauvegarder la configuration. - * @since 2.5.21 - */ - protected final File configFile; - - /** La configuration de l'application */ - protected final Object configBean; - - /** La configuration de l'application */ - protected final ApplicationConfig applicationConfig; - - /** la cateogrie en cours d'utilisation */ - protected CategoryModel categoryModel; - - /** - * un drapeau pour savoir si la configuration a été modifiée au moins une - * fois. - * - * On utilise ce drapeau lors de la sortie pour verifier s'il faut ou non - * redemarer l'application (si non en mode standalone) - */ - protected boolean saved; - - /** - * un drapeau pour savoir si l'ui de configuration a été lancée en mode - * standalone ou pas. - * - * Si pas lancée en mode standalone, et si la confi a été sauvé on vérifie - * s'il ne faut pas relancer l'application. - */ - protected boolean standalone; - - /** Callbacks manager */ - protected CallBacksManager callBacksManager; - - /** - * optional action to execute (if not null) if no call backs fits. - * - * @since 1.4.2 - */ - protected Runnable closeAction; - - /** support of modification notifications */ - protected final PropertyChangeSupport pcs; - - public ConfigUIModel(Object configBean, ApplicationConfig applicationConfig, File configFile) { - this.configBean = configBean; - this.applicationConfig = applicationConfig; - this.configFile = configFile; - categories = new LinkedHashMap<String, CategoryModel>(); - callBacksManager = new CallBacksManager(); - pcs = new PropertyChangeSupport(this); - } - - @Deprecated - public ConfigUIModel(Supplier<ApplicationConfig> config) { - this(config, config.get(), config.get().getUserConfigFile()); - } - - @Deprecated - public ConfigUIModel(Object configBean, ApplicationConfig applicationConfig) { - this(configBean, applicationConfig, applicationConfig.getUserConfigFile()); - } - - @Deprecated - public ConfigUIModel(Supplier<ApplicationConfig> config, File configFile) { - this(config, config.get(), configFile); - } - - @Deprecated - public ConfigUIModel(ApplicationConfig applicationConfig) { - this(applicationConfig, applicationConfig, applicationConfig.getUserConfigFile()); - } - - @Deprecated - public ConfigUIModel(ApplicationConfig applicationConfig, File configFile) { - this(applicationConfig, applicationConfig, configFile); - } - - /** - * Ajoute une categorie dans le modele. - * - * @param category la categorie a ajouter au modèle. - */ - public void addCategory(CategoryModel category) { - if (categories.containsKey(category.getCategory())) { - throw new IllegalArgumentException( - t("config.error.category.already.exists", - category.getCategory())); - } - categories.put(category.getCategory(), category); - } - - /** - * Change la categorie en cours d'édition. - * - * @param category l'id de la categorie courante - */ - public void setCategory(String category) { - if (!categories.containsKey(category)) { - throw new IllegalArgumentException( - t("config.error.category.not.found", category)); - } - CategoryModel newCategoryModel = categories.get(category); - setCategoryModel(newCategoryModel); - newCategoryModel.firePropertyChange( - CategoryModel.MODIFIED_PROPERTY_NAME, false, - getCategoryModel().isModified()); - newCategoryModel.firePropertyChange( - CategoryModel.VALID_PROPERTY_NAME, false, - getCategoryModel().isValid()); - } - - /** - * Registers a new callback. - * - * <b>Note:</b> the order of registred callback is used to determine - * the higher priority of callback to launch if required. - * - * @param name the unique name of a callback - * @param description the i18n key to describe the action - * @param icon the icon of the callBack (used in ui) - * @param action the action of the callback - */ - public void registerCallBack(String name, - String description, - Icon icon, - Runnable action) { - callBacksManager.registerCallBack(name, description, icon, action); - } - - /** - * Registers a option into a known callback. - * - * @param name the name of the callback - * @param option the option to register for the given callback - */ - public void registerOptionCallBack(String name, OptionModel option) { - callBacksManager.registerOption(name, option); - } - - public void setFinalizer(CallBackFinalizer finalizer) { - callBacksManager.setFinalizer(finalizer); - } - - public Runnable getCloseAction() { - return closeAction; - } - - public void setCloseAction(Runnable closeAction) { - this.closeAction = closeAction; - } - - /** - * Obtain the dictionnary of callback for all to saved modified options. - * - * @return the dictonnary - */ - public CallBackMap getCallBacksForSaved() { - return callBacksManager.getCallBacksForSaved(this); - } - - @Override - public Iterator<CategoryModel> iterator() { - return categories.values().iterator(); - } - - public CategoryModel getCategoryModel() { - return categoryModel; - } - - public void setCategoryModel(CategoryModel categoryModel) { - CategoryModel old = this.categoryModel; - this.categoryModel = categoryModel; - firePropertyChange(CATEGORY_MODEL_PROPERTY_NAME, old, categoryModel); - } - - public boolean isSaved() { - return saved; - } - - public void setSaved(boolean saved) { - this.saved = saved; - } - - public boolean isStandalone() { - return standalone; - } - - public void setStandalone(boolean standalone) { - this.standalone = standalone; - } - - public void saveModified() { - // compute transients keys (to never be saved) - List<String> transients = new ArrayList<String>(); - - applicationConfig.setAdjusting(true); - - try { - for (OptionModel option : categoryModel) { - if (option.isModified()) { - Object value = option.getValue(); - if (option.getPropertyName() != null) { - - // this is a javaBean option, push value via mutator - try { - PropertyUtils.setProperty(configBean, - option.getPropertyName(), value); - } catch (Exception e) { - throw new RuntimeException( - "could not set property [" + - option.getPropertyName() + - "] with value = " + value, e); - } - } else { - - // simple option with no javabeans, just push the option - // value - - String toSave; - if (value == null) { - toSave = null; - } else { - - if (option.isArrayType()) { - int length = Array.getLength(value); - List<Object> values = Lists.newArrayListWithCapacity(length); - for (int i = 0; i < length; i++) { - values.add(Array.get(value, i)); - } - toSave = Joiner.on(",").join(values); - } else { - toSave = value.toString(); - } - } - applicationConfig.setOption(option.getKey(), toSave); - - } - // l'option a été sauvegardée, on la marque - option.setSaved(true); - // this is the new original value - option.initValue(value); - } - if (option.isTransient()) { - transients.add(option.getKey()); - } - } - } finally { - applicationConfig.setAdjusting(false); - } - - setSaved(true); - // save config - // Ano -// applicationConfig.saveForUser(transients.toArray(new String[transients.size()])); - try { - applicationConfig.save(configFile, false, transients.toArray(new String[transients.size()])); - } catch (IOException eee) { - if (log.isWarnEnabled()) { - log.warn(t("config.error.applicationconfig.save", configFile), - eee); - } - } - - // notify data has changed - categoryModel.firePropertyChange( - CategoryModel.MODIFIED_PROPERTY_NAME, - categoryModel.isModified(), true); - categoryModel.firePropertyChange( - CategoryModel.VALID_PROPERTY_NAME, - false, categoryModel.isValid()); - categoryModel.firePropertyChange( - CategoryModel.RELOAD_PROPERTY_NAME, false, true); - } - - public void reset() { - // reset all modified options of the current category - for (OptionModel key : categoryModel) { - if (key.isModified()) { - key.initValue(key.getOriginalValue()); - } - } - // notify data has changed - categoryModel.firePropertyChange( - CategoryModel.MODIFIED_PROPERTY_NAME, - categoryModel.isModified(), true); - categoryModel.firePropertyChange( - CategoryModel.VALID_PROPERTY_NAME, - false, categoryModel.isValid()); - categoryModel.firePropertyChange( - CategoryModel.RELOAD_PROPERTY_NAME, false, true); - } - - public int getCategoryIndex(String category) { - int i = 0; - for (CategoryModel m : this) { - if (category.equals(m.getCategory())) { - return i; - } - i++; - } - // not found - return -1; - } - - public void firePropertyChange(String propertyName, - Object oldValue, - Object newValue) { - pcs.firePropertyChange(propertyName, oldValue, newValue); - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - pcs.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - pcs.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.removePropertyChangeListener(propertyName, listener); - } - - public boolean hasListeners(String propertyName) { - return pcs.hasListeners(propertyName); - } - - public PropertyChangeListener[] getPropertyChangeListeners( - String propertyName) { - return pcs.getPropertyChangeListeners(propertyName); - } - - public PropertyChangeListener[] getPropertyChangeListeners() { - return pcs.getPropertyChangeListeners(); - } - - public void destroy() { - JAXXUtil.destroy(pcs); - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - destroy(); - } - - /** - * @return the underlined application config - * @deprecated since 2.5.4 use now {@link #getApplicationConfig()}. - */ - protected ApplicationConfig getConfig() { - return applicationConfig; - } - - /** - * @return the underlined application config - * @since 2.5.4 - */ - protected ApplicationConfig getApplicationConfig() { - return applicationConfig; - } - - protected CallBacksManager getCallBacksManager() { - return callBacksManager; - } - - public String getCategoryName(int index) { - return Lists.newArrayList(categories.keySet()).get(index); - } -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/ConfigUIModelBuilder.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/ConfigUIModelBuilder.java deleted file mode 100644 index 26d0c6a..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/ConfigUIModelBuilder.java +++ /dev/null @@ -1,550 +0,0 @@ -package jaxx.runtime.swing.config.model; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Preconditions; -import com.google.common.base.Supplier; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.config.ApplicationConfig; -import org.nuiton.config.ConfigOptionDef; - -import javax.swing.Icon; -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableCellRenderer; -import java.io.File; - -/** - * A builder of {@link ConfigUIModel} - * Created: 22 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class ConfigUIModelBuilder { - - /** Logger */ - private static final Log log = LogFactory.getLog(ConfigUIModelBuilder.class); - - /** current model used */ - ConfigUIModel model; - - /** current category used */ - CategoryModel category; - - /** Current default callback used by a category. */ - String categoryDefaultCallBack; - - /** current option used */ - OptionModel option; - - /** - * Create a new model and set it as current model. - * - * @param configurationBean configuration bean used in model (optional) - * @param config the configuration used in model (can not be null) - * @param configFile configuration file where to save (can not be null) - * @return the builder - * @throws IllegalStateException if there is already a current model - * @throws NullPointerException if config or configFile is {@code null} - * @since 2.33 - */ - public ConfigUIModelBuilder createModel(Object configurationBean, ApplicationConfig config, File configFile) throws IllegalStateException, NullPointerException { - checkNoCurrent(model, "model"); - // configuration bean can be null - checkNotNull(config, "createModel", "config"); - checkNotNull(configFile, "createModel", "configFile"); - model = new ConfigUIModel(configurationBean, config, configFile); - - if (log.isDebugEnabled()) { - log.debug("model created : " + model); - } - return this; - } - - /** - * Create a new model and set it as current model. - * - * @param config the configuration used in model - * @return the builder - * @throws IllegalStateException if there is already a current model - * @throws NullPointerException if config is {@code null} - * @deprecated since 2.33, prefer use the {@link #createModel(Object, ApplicationConfig, File)} method instead, will be removed soon - */ - @Deprecated - public ConfigUIModelBuilder createModel(Supplier<ApplicationConfig> config) - throws IllegalStateException, NullPointerException { - return createModel(config, config.get(), config.get().getUserConfigFile()); - } - - /** - * Create a new model and set it as current model. - * - * @param config the configuration used in model - * @param configFile configuration file where to save (can not be null) - * @return the builder - * @throws IllegalStateException if there is already a current model - * @throws NullPointerException if config or configFile is {@code null} - * @since 2.5.21 - * @deprecated since 2.33, prefer use the {@link #createModel(Object, ApplicationConfig, File)} method instead, will be removed soon - */ - @Deprecated - public ConfigUIModelBuilder createModel(Supplier<ApplicationConfig> config, File configFile) - throws IllegalStateException, NullPointerException { - return createModel(config, config.get(), configFile); - } - - /** - * Create a new model and set it as current model. - * - * @param configurationBean configuration bean used in model - * @param config the configuration used in model - * @return the builder - * @throws IllegalStateException if there is already a current model - * @throws NullPointerException if there is some null parameters - * @deprecated since 2.33, prefer use the {@link #createModel(Object, ApplicationConfig, File)} method instead, will be removed soon - */ - @Deprecated - public ConfigUIModelBuilder createModel(Object configurationBean, ApplicationConfig config) - throws IllegalStateException, NullPointerException { - return createModel(configurationBean, config, config.getUserConfigFile()); - } - - /** - * Create a new model and set it as current model. - * - * @param config the configuration used in model - * @return the builder - * @throws IllegalStateException if there is already a current model - * @throws NullPointerException if config is {@code null} - * @deprecated since 2.33, prefer use the {@link #createModel(Object, ApplicationConfig, File)} method instead, will be removed soon - */ - @Deprecated - public ConfigUIModelBuilder createModel(ApplicationConfig config) throws IllegalStateException, NullPointerException { - return createModel(config, config, config.getUserConfigFile()); - } - - /** - * Create a new model and set it as current model. - * - * @param config the configuration used in model - * @param configFile configuration file where to save (can not be null) - * @return the builder - * @throws IllegalStateException if there is already a current model - * @throws NullPointerException if config or configFile is {@code null} - * @since 2.5.21 - * @deprecated since 2.33, prefer use the {@link #createModel(Object, ApplicationConfig, File)} method instead, will be removed soon - */ - @Deprecated - public ConfigUIModelBuilder createModel(ApplicationConfig config, File configFile) - throws IllegalStateException, NullPointerException { - return createModel(config, config, configFile); - } - - /** - * Add a new category, and set it as current. - * - * <b>Note:</b> As side effets, if a previous category, then store it to - * the model. - * - * @param categoryName the name of the new category - * (can not to be {@code null}) - * @param categoryLabel the label of the new category - * (can not to be {@code null}) - * @return the builder - * @throws IllegalStateException if there is not a current model, - * nor category - * @throws NullPointerException if any of parameter is {@code null} - */ - public ConfigUIModelBuilder addCategory(String categoryName, String categoryLabel) - throws IllegalStateException, NullPointerException { - checkCurrent(model, "model"); - checkNotNull(categoryName, "addCategory", "categoryName"); - checkNotNull(categoryLabel, "addCategory", "categoryLabel"); - flushCategory(); - category = new CategoryModel(categoryName, categoryLabel); - if (log.isDebugEnabled()) { - log.debug("category created : " + category); - } - return this; - } - - /** - * Add a new category, and set it as current. - * - * <b>Note:</b> As side effets, if a previous category, then store it to - * the model. - * - * @param categoryName the name of the new category - * (can not to be {@code null}) - * @param categoryLabel the label of the new category - * (can not to be {@code null}) - * @return the builder - * @throws IllegalStateException if there is not a current model, - * nor category - * @throws NullPointerException if any of parameter is {@code null} - */ - public ConfigUIModelBuilder addCategory(String categoryName, String categoryLabel, String defaultCallback) - throws IllegalStateException, NullPointerException { - checkCurrent(model, "model"); - checkNotNull(categoryName, "addCategory", "categoryName"); - checkNotNull(categoryLabel, "addCategory", "categoryLabel"); - flushCategory(); - categoryDefaultCallBack = defaultCallback; - category = new CategoryModel(categoryName, categoryLabel); - if (log.isDebugEnabled()) { - log.debug("category created : " + category); - } - return this; - } - - /** - * Add a new option, and set it as current. - * - * <b>Note:</b> As side effets, if a previous option, then store it to - * the model. - * - * @param def the def ot the new option - * @return the builder - * @throws IllegalStateException if there is not a current model, - * nor category - * @throws NullPointerException if any of parameter is {@code null} - */ - public ConfigUIModelBuilder addOption(ConfigOptionDef def) - throws IllegalStateException, NullPointerException { - checkCurrent(model, "model"); - checkCurrent(category, "category"); - checkNotNull(def, "addOption", "def"); - flushOption(); - Object value = model.getApplicationConfig().getOption(def); - option = new OptionModel(def, value); - if (categoryDefaultCallBack != null) { - - // use default callback - model.registerOptionCallBack(categoryDefaultCallBack, option); - } - if (log.isDebugEnabled()) { - log.debug("option created : " + option); - } - return this; - } - - /** - * Add a new option with a propertyName, and set it as current. - * - * <b>Note:</b> As side effets, if a previous option, then store it to - * the model. - * - * <b>Note:</b> This method is a short-cut for - * {@link #addOption(ConfigOptionDef)} then - * {@link #setOptionPropertyName(String)}. - * - * @param def the def ot the new option - * @param propertyName the propertyName to set on the option - * @return the builder - * @throws IllegalStateException if there is not a current model, nor - * category - * @throws NullPointerException if any of parameter is {@code null} - * @deprecated since 2.5.29, prefer use the {@link #setOptionPropertyName(String)} method instead, will be removed soon - */ - @Deprecated - public ConfigUIModelBuilder addOption(ConfigOptionDef def, - String propertyName) - throws IllegalStateException, NullPointerException { - addOption(def); - checkNotNull(propertyName, "setOptionPropertyName", "propertyName"); - option.setPropertyName(propertyName); - return this; - } - - /** - * Set the propertyName on the current option. - * - * @param propertyName the propertyName to set in the current option. - * @return the builder - * @throws IllegalStateException if there is not a current option set. - * @throws NullPointerException if any of parameter is {@code null} - * @see OptionModel#setPropertyName(String) - */ - public ConfigUIModelBuilder setOptionPropertyName(String propertyName) - throws IllegalStateException, NullPointerException { - checkCurrent(option, "option"); - checkNotNull(propertyName, "setOptionPropertyName", "propertyName"); - option.setPropertyName(propertyName); - return this; - } - - /** - * Set the short label on the current option. - * - * @param shortLabel the propertyName to set in the current option. - * @return the builder - * @throws IllegalStateException if there is not a current option set. - * @throws NullPointerException if any of parameter is {@code null} - * @see OptionModel#setShortLabel(String) - * @since 2.5.29 - */ - public ConfigUIModelBuilder setOptionShortLabel(String shortLabel) - throws IllegalStateException, NullPointerException { - checkCurrent(option, "option"); - checkNotNull(shortLabel, "setShortLabel", "shortLabel"); - option.setShortLabel(shortLabel); - return this; - } - - /** - * Set the editor on the current option. - * - * @param editor the editor to set in the current option. - * @return the builder - * @throws IllegalStateException if there is not a current option set. - * @throws NullPointerException if any of parameter is {@code null} - * @see OptionModel#setEditor(TableCellEditor) - */ - public ConfigUIModelBuilder setOptionEditor(TableCellEditor editor) - throws IllegalStateException, NullPointerException { - checkCurrent(option, "option"); - checkNotNull(editor, "setOptionEditor", "editor"); - option.setEditor(editor); - return this; - } - - /** - * Set the renderer on the current option. - * - * @param renderer the renderer to set in the current option. - * @return the builder - * @throws IllegalStateException if there is not a current option set. - * @throws NullPointerException if any of parameter is {@code null} - * @see OptionModel#setRenderer(TableCellRenderer) - */ - public ConfigUIModelBuilder setOptionRenderer(TableCellRenderer renderer) - throws IllegalStateException, NullPointerException { - checkCurrent(option, "option"); - checkNotNull(renderer, "setOptionRenderer", "renderer"); - option.setRenderer(renderer); - return this; - } - - /** - * Registers a new callback. - * - * <b>Note:</b> the order of registred callback is used to determine - * the higher priority of callback to launch if required. - * - * @param name the unique name of a callback - * @param description the i18n key to describe the action - * @param icon the icon of the callBack (used in ui) - * @param action the action of the callback - * @return the builder - */ - public ConfigUIModelBuilder registerCallBack(String name, - String description, - Icon icon, - Runnable action) { - checkCurrent(model, "model"); - checkNotNull(name, "registerCallBack", "name"); - checkNotNull(description, "registerCallBack", "description"); - checkNotNull(action, "registerCallBack", "action"); - model.registerCallBack(name, description, icon, action); - return this; - } - - /** - * Registers the current option into a known callback. - * - * @param name the name of the callback - * @return the builder - */ - public ConfigUIModelBuilder setOptionCallBack(String name) { - checkCurrent(option, "option"); - checkNotNull(name, "setOptionCallBack", "name"); - Preconditions.checkArgument( - categoryDefaultCallBack == null, - "You can not use the method *setOptionCallBack* when " + - "a default callback has been assigned to a category"); - - model.registerOptionCallBack(name, option); - return this; - } - - /** - * Sets the callback finalizet - * - * @param finalizer callback finalize - * @return the builder - * @see CallBackFinalizer - */ - public ConfigUIModelBuilder setFinalizer(CallBackFinalizer finalizer) { - model.setFinalizer(finalizer); - return this; - } - - /** - * Sets the default callback to use for this category (the call back - * will be add to all options of this category until you set another one or - * nullify it). - * - * @param categoryDefaultCallBack default callbakc name for the category - * @return the buider - */ - public ConfigUIModelBuilder setCategoryDefaultCallBack(String categoryDefaultCallBack) { - checkCurrent(model, "model"); - checkCurrent(category, "category"); - this.categoryDefaultCallBack = categoryDefaultCallBack; - return this; - } - - - /** - * Flush the model and return it. - * - * <b>Note:</b> As a side effect, nothing is available in the builder - * after this operation. - * To reuse the builder on a model, use the dedicated setter. - * - * @return the final model - * @throws IllegalStateException if there is not a current model set. - */ - public ConfigUIModel flushModel() throws IllegalStateException { - checkCurrent(model, "model"); - flushCategory(); - ConfigUIModel result = model; - model = null; - return result; - } - - /** - * Set the given model as current model. - * - * <b>Note:</b> As side effets, il will clean current category and option. - * - * @param model the model to use - * @return the buider - * @throws IllegalStateException if there is already a current model - */ - public ConfigUIModelBuilder setModel(ConfigUIModel model) throws IllegalStateException { - checkNoCurrent(model, "model"); - this.model = model; - if (log.isDebugEnabled()) { - log.debug("new current model : " + this.model); - } - category = null; - categoryDefaultCallBack = null; - option = null; - return this; - } - - /** - * Set the given category as current category. - * - * <b>Note:</b> As side effets, il will clean current option. - * - * @param categoryModel the category to use - * @return the buider - * @throws IllegalStateException if there is not a current model or a - * current category - */ - public ConfigUIModelBuilder setCategory(CategoryModel categoryModel) - throws IllegalStateException { - checkCurrent(model, "model"); - checkNoCurrent(category, "category"); - category = categoryModel; - categoryDefaultCallBack = null; - if (log.isDebugEnabled()) { - log.debug("new current category : " + category); - } - option = null; - return this; - } - - /** - * Sets the given option as current option. - * - * @param optionModel the option to use - * @return the buider - * @throws IllegalStateException if there is not a current model, nor - * category, or a current option - */ - public ConfigUIModelBuilder setOption(OptionModel optionModel) - throws IllegalStateException { - checkCurrent(model, "model"); - checkCurrent(category, "category"); - checkNoCurrent(option, "option"); - option = optionModel; - if (log.isDebugEnabled()) { - log.debug("new current option : " + option); - } - return this; - } - - public ConfigUIModelBuilder setCloseAction(Runnable runnable) { - checkNotNull(runnable, "setCloseAction", "runnable"); - checkCurrent(model, "model"); - model.setCloseAction(runnable); - return this; - } - - protected CategoryModel flushCategory() { - CategoryModel result = category; - if (category != null) { - flushOption(); - // add the previous category to the model - model.addCategory(category); - category = null; - categoryDefaultCallBack = null; - } - return result; - } - - protected OptionModel flushOption() { - OptionModel result = option; - if (option != null) { - // add the previous option to the category - category.addOption(option); - option = null; - } - return result; - } - - protected void checkCurrent(Object o, String type) { - if (o == null) { - throw new IllegalStateException("no current " + type + "!"); - } - } - - protected void checkNoCurrent(Object o, String type) { - if (o != null) { - throw new IllegalStateException( - "there is already a current " + type + "!"); - } - } - - protected void checkNotNull(Object o, String method, String parameter) { - if (o == null) { - throw new NullPointerException( - "method " + method + " does not support null parameter " + - parameter + "!"); - } - } -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/MainCallBackFinalizer.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/MainCallBackFinalizer.java deleted file mode 100644 index bfba1e1..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/MainCallBackFinalizer.java +++ /dev/null @@ -1,63 +0,0 @@ -package jaxx.runtime.swing.config.model; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import java.util.ArrayList; -import java.util.List; - -/** - * A finalizer to mark a special category to eat every others categories - * when finalizing. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class MainCallBackFinalizer implements CallBackFinalizer { - - /** name of call back which eats everybody */ - protected final String mainCallBack; - - public MainCallBackFinalizer(String mainCallBack) { - this.mainCallBack = mainCallBack; - } - - @Override - public CallBackMap finalize(CallBackMap result) { - CallBackEntry applicationEntry = result.getCallBack(mainCallBack); - CallBackMap newResult; - if (applicationEntry == null) { - // rien n'a change - newResult = result; - } else { - newResult = new CallBackMap(); - // on passe toutes les options sur ce callback - List<OptionModel> options = new ArrayList<OptionModel>(); - - for (List<OptionModel> optionModels : result.values()) { - options.addAll(optionModels); - } - newResult.put(applicationEntry, options); - } - return newResult; - } -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/OptionModel.java b/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/OptionModel.java deleted file mode 100644 index 415c308..0000000 --- a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/OptionModel.java +++ /dev/null @@ -1,224 +0,0 @@ -package jaxx.runtime.swing.config.model; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.ObjectUtils; -import org.nuiton.config.ConfigOptionDef; - -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableCellRenderer; - -/** - * le modele d'une option de la configuration a editer. - * - * @author tchemit - * @since 2.5.11 - */ -public class OptionModel implements ConfigOptionDef { - - private static final long serialVersionUID = 1L; - - /** la definition de l'option (venant de la config) */ - protected final ConfigOptionDef def; - - /** un drapeau pour savoir si l'option est valide (n'est pas utilisé actuellement) */ - protected boolean valid = true; - - /** un drapeau pour savoir si l'option a été sauvée */ - protected boolean saved; - - /** la valeur non modifié de l'option */ - protected Object originalValue; - - /** la valeur actuelle de l'option (peut être la valeur orignal si non modifée) */ - protected Object value; - - /** le nom de la propriété javaBean (peut etre null, si option sans support javaBean) */ - protected String propertyName; - - /** - * Une description courte à utiliser à la place de la clef i18n. - * - * @since 2.5.29 - */ - protected String shortLabel; - - /** l'editeur utilise pour modifier graphiquement l'option */ - protected TableCellEditor editor; - - /** le renderer utilise pour afficher graphiquement l'option */ - protected TableCellRenderer renderer; - - protected OptionModel(ConfigOptionDef def, Object value) { - this.def = def; - initValue(value); - } - - public String getShortLabel() { - return shortLabel; - } - - public void setShortLabel(String shortLabel) { - this.shortLabel = shortLabel; - } - - @Override - public String getKey() { - return def.getKey(); - } - - @Override - public Class<?> getType() { - return def.getType(); - } - - public boolean isArrayType() { - return getType().isArray(); - } - - @Override - public String getDescription() { - return def.getDescription(); - } - - @Override - public String getDefaultValue() { - return def.getDefaultValue(); - } - - @Override - public boolean isTransient() { - return def.isTransient(); - } - - @Override - public boolean isFinal() { - return def.isFinal(); - } - - public Object getOriginalValue() { - return originalValue; - } - - public Object getValue() { - return value; - } - - @Override - public void setDefaultValue(String defaultValue) { - def.setDefaultValue(defaultValue); - } - - @Override - public void setTransient(boolean isTransient) { - def.setTransient(isTransient); - } - - @Override - public void setFinal(boolean isFinal) { - def.setFinal(isFinal); - } - - public void setValue(Object value) { - this.value = value; - } - - public boolean isModified() { - boolean result; - if (isArrayType()) { - result = !ArrayUtils.isEquals(originalValue, value); - } else { - result = ObjectUtils.notEqual(originalValue, value); - } - return result; - } - - public boolean isValid() { - return valid; - } - - public void setValid(boolean valid) { - this.valid = valid; - } - - public boolean isSaved() { - return saved; - } - - public void setSaved(boolean saved) { - this.saved = saved; - } - - public void initValue(Object originalValue) { - this.originalValue = originalValue; - value = originalValue; - } - - public String getPropertyName() { - return propertyName; - } - - public TableCellEditor getEditor() { - return editor; - } - - protected void setEditor(TableCellEditor editor) { - this.editor = editor; - } - - public TableCellRenderer getRenderer() { - return renderer; - } - - public void setRenderer(TableCellRenderer renderer) { - this.renderer = renderer; - } - - protected void setPropertyName(String propertyName) { - this.propertyName = propertyName; - } - - /** - * Get a string value of the given {@code value} considered as a value of - * this option, means if option is array type, then we will decorate the - * value as a array. - * - * @param value value to decorate - * @return decorated value - * @since 2.5.14 - */ - public String toString( Object value) { - String result; - if (value == null) { - result = null; - } else { - if (isArrayType()) { - result = ArrayUtils.toString(value); - } else { - result = String.valueOf(value); - } - } - return result; - } -} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigCallBackUI.jaxx b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigCallBackUI.jaxx similarity index 100% rename from jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigCallBackUI.jaxx rename to jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigCallBackUI.jaxx diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigCallBackUIHandler.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigCallBackUIHandler.java new file mode 100644 index 0000000..952148a --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigCallBackUIHandler.java @@ -0,0 +1,191 @@ +package org.nuiton.jaxx.config; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.config.model.CallBackEntry; +import org.nuiton.jaxx.config.model.CallBackMap; +import org.nuiton.jaxx.config.model.OptionModel; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JLabel; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; +import java.awt.Component; +import java.awt.Window; +import java.util.List; +import java.util.Map; + +import static org.nuiton.i18n.I18n.t; + +/** + * callBackUI handler + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class ConfigCallBackUIHandler { + + /** Logger */ + private static final Log log = + LogFactory.getLog(ConfigCallBackUIHandler.class); + + public void init(ConfigCallBackUI ui) { + + // build tree model + DefaultMutableTreeNode root = new DefaultMutableTreeNode(); + + CallBackMap forSaved = ui.getContextValue( + CallBackMap.class, ConfigUIHandler.CALLBACKS_WITH_OPTIONS); + + for (Map.Entry<CallBackEntry, List<OptionModel>> e : + forSaved.entrySet()) { + + CallBackEntry callBackEntry = e.getKey(); + List<OptionModel> options = e.getValue(); + + DefaultMutableTreeNode callBackNode; + callBackNode = new DefaultMutableTreeNode(callBackEntry, true); + + root.add(callBackNode); + for (OptionModel o : options) { + + DefaultMutableTreeNode optionkNode; + optionkNode = new DefaultMutableTreeNode(o, false); + + callBackNode.add(optionkNode); + } + } + + JTree tree = ui.getDetectedCallBack(); + + tree.setModel(new DefaultTreeModel(root)); + + SwingUtil.expandTree(tree); + + tree.setCellRenderer(new DefaultTreeCellRenderer() { + @Override + public Component getTreeCellRendererComponent(JTree tree, + Object value, + boolean sel, + boolean expanded, + boolean leaf, + int row, + boolean hasFocus) { + if (log.isDebugEnabled()) { + log.debug("value = " + value.getClass()); + } + if (value == null) { + return super.getTreeCellRendererComponent( + tree, + value, + sel, + expanded, + leaf, + row, + hasFocus); + } + + if (!(value instanceof DefaultMutableTreeNode)) { + return super.getTreeCellRendererComponent( + tree, + value, + sel, + expanded, + leaf, + row, + hasFocus); + } + + DefaultMutableTreeNode n = (DefaultMutableTreeNode) value; + value = n.getUserObject(); + + if (value instanceof CallBackEntry) { + CallBackEntry v = (CallBackEntry) value; + if (log.isDebugEnabled()) { + log.debug("callBackEntry detected " + v.getName()); + } + value = t(v.getDescription()); + } else if (value instanceof OptionModel) { + + OptionModel v = (OptionModel) value; + if (log.isDebugEnabled()) { + log.debug("option detected " + v.getKey()); + } + value = v.getKey() + " (" + t(v.getDescription()) + ")"; + } + + JLabel rendererComponent; + rendererComponent = (JLabel) + super.getTreeCellRendererComponent( + tree, + value, + sel, + expanded, + leaf, + row, + hasFocus); + + value = n.getUserObject(); + + if (value instanceof CallBackEntry) { + + CallBackEntry v = (CallBackEntry) value; + rendererComponent.setIcon(v.getIcon()); + } + return rendererComponent; + } + }); + } + + public void doAction(final ConfigCallBackUI ui) { + log.info("Launch callBacks..."); + Window parent = ui.getContextValue(Window.class, "parent"); + if (parent != null) { + log.info("dispose parent window..."); + parent.dispose(); + } + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + List<CallBackEntry> callBacks; + callBacks = ui.getContextValue( + List.class, + ConfigUIHandler.CALLBACKS); + for (CallBackEntry e : callBacks) { + if (log.isInfoEnabled()) { + log.info("launch callBack " + t(e.getDescription())); + } + e.getAction().run(); + } + } + }); + } +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigCategoryUI.jaxx b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigCategoryUI.jaxx new file mode 100644 index 0000000..57ea543 --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigCategoryUI.jaxx @@ -0,0 +1,87 @@ +<!-- + #%L + JAXX :: Config + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel layout='{new BorderLayout()}'> + + <import> + java.awt.Color + javax.swing.DefaultListSelectionModel + javax.swing.ScrollPaneConstants + org.nuiton.jaxx.config.model.CategoryModel + org.nuiton.jaxx.config.model.ConfigTableModel + org.nuiton.jaxx.config.model.ConfigUIModel + org.jdesktop.swingx.JXTable + </import> + + <ConfigCategoryUIHandler id='handler' constructorParams='this'/> + + <script><![CDATA[ + +void $afterCompleteSetup() { + getHandler().init(); +} +]]> + </script> + + <!-- le modele de l'ui --> + <ConfigUIModel id='model' + initializer='getContextValue(ConfigUIModel.class)'/> + + <CategoryModel id='categoryModel' + javaBean='getContextValue(CategoryModel.class)'/> + + <ConfigTableModel id='tableModel' constructorParams='categoryModel' + onTableChanged='handler.updateDescriptionText()'/> + + <ListSelectionModel id='selectionModel' + javaBean='new DefaultListSelectionModel()' + onValueChanged='if (!event.getValueIsAdjusting()) {handler.updateDescriptionText(); }'/> + + <!-- categorie label --> + <JPanel id="categoryLabelPanel" constraints='BorderLayout.NORTH'> + <JLabel id='categoryLabel'/> + </JPanel> + + <!-- table of options --> + <JScrollPane id='tablePane' constraints='BorderLayout.CENTER'> + <JXTable id="table" constructorParams='tableModel' onMousePressed='handler.openTablePopupMenu(event, tablePopup)'/> + </JScrollPane> + + <JPanel layout='{new BorderLayout()}' constraints='BorderLayout.SOUTH'> + + <!-- description of selected option in table --> + <JScrollPane id="descriptionPane" constraints='BorderLayout.CENTER'> + <JTextArea id='description'/> + </JScrollPane> + + <!-- actions of the category --> + <JPanel layout='{new GridLayout(1,0)}' + constraints='BorderLayout.SOUTH'> + <JButton id='reset' onActionPerformed='model.reset()'/> + <JButton id='save' onActionPerformed='model.saveModified()'/> + </JPanel> + </JPanel> + + <JPopupMenu id='tablePopup'> + <JMenuItem id='copyCellValue' onActionPerformed='handler.copyCellValue()'/> + <JMenuItem id='resetOptionValue' onActionPerformed='handler.resetOptionValue()'/> + </JPopupMenu> +</JPanel> diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigCategoryUI.jcss b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigCategoryUI.jcss similarity index 100% rename from jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigCategoryUI.jcss rename to jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigCategoryUI.jcss diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigCategoryUIHandler.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigCategoryUIHandler.java new file mode 100644 index 0000000..2b2368b --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigCategoryUIHandler.java @@ -0,0 +1,266 @@ +package org.nuiton.jaxx.config; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.config.model.ConfigTableModel; +import org.nuiton.jaxx.config.model.OptionModel; +import org.nuiton.jaxx.runtime.swing.renderer.ClassTableCellRenderer; +import org.nuiton.jaxx.runtime.swing.renderer.ColorCellRenderer; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTable; + +import javax.swing.JLabel; +import javax.swing.JPopupMenu; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import javax.swing.table.TableCellRenderer; +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.Point; +import java.awt.event.MouseEvent; + +import static org.nuiton.i18n.I18n.n; +import static org.nuiton.i18n.I18n.t; + +/** + * Handler of {@link ConfigCategoryUI}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class ConfigCategoryUIHandler { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(ConfigCategoryUIHandler.class); + + private final ConfigCategoryUI ui; + + public ConfigCategoryUIHandler(ConfigCategoryUI ui) { + this.ui = ui; + } + + public void init() { + + JTable table = ui.getTable(); + + // prepare table + SwingUtil.setI18nTableHeaderRenderer( + table, + n("config.key"), + n("config.key.tip"), + n("config.value"), + n("config.value.tip"), + n("config.defaultValue"), + n("config.defaultValue.tip")); + + ConfigTableRenderer renderer = new ConfigTableRenderer(); + SwingUtil.setTableColumnRenderer(table, 0, renderer); + SwingUtil.setTableColumnRenderer(table, 1, renderer); + SwingUtil.setTableColumnRenderer(table, 2, renderer); + Font f = table.getFont().deriveFont(Font.ITALIC | Font.BOLD); + int width = SwingUtil.computeTableColumnWidth(table, f, 0, "___*"); + SwingUtil.fixTableColumnWidth(table, 0, width); + SwingUtil.setTableColumnEditor(table, 1, new ConfigTableEditor((ConfigTableModel) table.getModel())); + table.setDefaultRenderer(Color.class, new ColorCellRenderer()); + table.setDefaultRenderer(Class.class, new ClassTableCellRenderer()); + } + + public void updateDescriptionText() { + OptionModel option; + JTable table = ui.getTable(); + JTextArea description = ui.getDescription(); + ListSelectionModel selectionModel = ui.getSelectionModel(); + + if (selectionModel.isSelectionEmpty()) { + option = null; + } else { + int row = selectionModel.getAnchorSelectionIndex(); + ConfigTableModel m = (ConfigTableModel) table.getModel(); + option = m.getEntry(row); + if (log.isDebugEnabled()) { + log.debug(row + " : " + option); + } + } + StringBuilder buffer = new StringBuilder(); + if (option == null) { + buffer.append(t("config.no.option.selected")); + } else { + buffer.append(t("config.option.label", option.getKey(), t(option.getDescription()))).append('\n'); + if (option.isModified()) { + String oValue = option.toString(option.getOriginalValue()); + String mValue = option.toString(option.getValue()); + buffer.append(t("config.option.modified", oValue, mValue)).append('\n'); + } + if (option.isFinal()) { + buffer.append(t("config.option.final")).append('\n'); + } + } + description.setText(buffer.toString()); + } + + public void copyCellValue() { + + JXTable table = ui.getTable(); + + int[] selectedRows = table.getSelectedRows(); + + int selectedRow = selectedRows[0]; + + Integer selectedColumn = (Integer) ui.getCopyCellValue().getClientProperty("selectedColumn"); + + ConfigTableModel tableModel = ui.getTableModel(); + OptionModel optionModel = tableModel.getEntry(selectedRow); + + Object value = null; + switch (selectedColumn) { + case 1: + if (log.isInfoEnabled()) { + log.info("Will copy option value from " + optionModel.getKey()); + } + value = optionModel.getValue(); + break; + case 2: + if (log.isInfoEnabled()) { + log.info("Will copy option default value from " + optionModel.getKey()); + } + value = optionModel.getOriginalValue(); + break; + } + + String text = ""; + if (value != null) { + TableCellRenderer cellRenderer = table.getCellRenderer(selectedRow, selectedColumn); + Component tableCellRendererComponent = cellRenderer.getTableCellRendererComponent(table, value, false, false, selectedRow, selectedColumn); + + text = ((JLabel) tableCellRendererComponent).getText(); + } + + if (log.isInfoEnabled()) { + log.info("Copy to clipboard cell (" + selectedRow + "-" + selectedColumn + ") value: \"" + text + "\""); + } + + JAXXUtil.copyToClipBoard(text); + + } + + public void resetOptionValue() { + + JXTable table = ui.getTable(); + + int[] selectedRows = table.getSelectedRows(); + + int selectedRow = selectedRows[0]; + + ConfigTableModel tableModel = ui.getTableModel(); + OptionModel optionModel = tableModel.getEntry(selectedRow); + + if (log.isInfoEnabled()) { + log.info("Will reset option: " + optionModel.getKey()); + } + tableModel.setValueAt(optionModel.getDefaultValue(), selectedRow, 1); + + } + + public void openTablePopupMenu(MouseEvent e, JPopupMenu popup) { + + boolean rightClick = SwingUtilities.isRightMouseButton(e); + + if (rightClick) { + + JXTable source = (JXTable) e.getSource(); + + int[] selectedRows = source.getSelectedRows(); + int[] selectedColumns = source.getSelectedColumns(); + + // get the coordinates of the mouse click + Point p = e.getPoint(); + + // get the row index at this point + int rowIndex = source.rowAtPoint(p); + + // get the column index at this point + int columnIndex = source.columnAtPoint(p); + + // select row (could empty selection) + if (rowIndex == -1) { + source.clearSelection(); + } else if (!ArrayUtils.contains(selectedRows, rowIndex)) { + + // set selection + source.setRowSelectionInterval(rowIndex, rowIndex); + } + + // select column (could empty selection) + if (columnIndex == -1) { + source.clearSelection(); + } else if (!ArrayUtils.contains(selectedColumns, columnIndex)) { + source.setColumnSelectionInterval(columnIndex, columnIndex); + } + + int selectedRowCount = source.getSelectedRowCount(); + + boolean enableCopyOptionValue = selectedRowCount == 1; + boolean enableResetOptionValue = selectedRowCount > 0; + + if (log.isDebugEnabled()) { + log.debug("At point [" + p + "] found Row " + rowIndex + ", Column " + columnIndex); + } + + boolean canContinue = true; + + if (source.isEditing()) { + + // stop editing + boolean stopEdit = source.getCellEditor().stopCellEditing(); + if (!stopEdit) { + if (log.isWarnEnabled()) { + log.warn("Could not stop edit cell..."); + } + canContinue = false; + } + } + + int selectedColumn = source.getSelectedColumn(); + ui.getCopyCellValue().putClientProperty("selectedColumn", selectedColumn); + + ui.getCopyCellValue().setEnabled(enableCopyOptionValue); + ui.getResetOptionValue().setEnabled(enableResetOptionValue); + + if (canContinue) { + + // on right click show popup + popup.show(source, e.getX(), e.getY()); + + } + } + } + +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigTableEditor.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigTableEditor.java new file mode 100644 index 0000000..d28b723 --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigTableEditor.java @@ -0,0 +1,173 @@ +package org.nuiton.jaxx.config; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.io.Files; +import org.nuiton.jaxx.runtime.swing.JAXXWidgetUtil; +import org.nuiton.jaxx.config.model.ConfigTableModel; +import org.nuiton.jaxx.config.model.OptionModel; +import org.nuiton.jaxx.runtime.swing.editor.ClassCellEditor; +import org.nuiton.jaxx.runtime.swing.editor.ColorCellEditor; +import org.nuiton.jaxx.runtime.swing.editor.EnumEditor; +import org.nuiton.jaxx.runtime.swing.editor.LocaleEditor; +import org.nuiton.jaxx.runtime.swing.editor.cell.FileCellEditor; +import org.apache.commons.lang3.StringUtils; + +import javax.swing.DefaultCellEditor; +import javax.swing.JTable; +import javax.swing.KeyStroke; +import javax.swing.event.CellEditorListener; +import javax.swing.table.TableCellEditor; +import java.awt.Color; +import java.awt.Component; +import java.io.File; +import java.util.EventObject; +import java.util.Locale; + +/** + * L'éditeur des valeurs des propriétés d'une configuration + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class ConfigTableEditor implements TableCellEditor { + + protected TableCellEditor delegate; + + protected ConfigTableModel model; + + public ConfigTableEditor(ConfigTableModel model) { + this.model = model; + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + delegate = findDelegate(table, model.getEntry(row)); + return delegate.getTableCellEditorComponent(table, value, isSelected, row, column); + } + + @Override + public Object getCellEditorValue() { + return !hasDelegate() ? null : delegate.getCellEditorValue(); + } + + @Override + public boolean isCellEditable(EventObject anEvent) { + return !hasDelegate() || delegate.isCellEditable(anEvent); + } + + @Override + public boolean shouldSelectCell(EventObject anEvent) { + return hasDelegate() && delegate.shouldSelectCell(anEvent); + } + + @Override + public boolean stopCellEditing() { + return !hasDelegate() || delegate.stopCellEditing(); + } + + @Override + public void cancelCellEditing() { + if (hasDelegate()) { + delegate.cancelCellEditing(); + } + } + + @Override + public void addCellEditorListener(CellEditorListener l) { + if (hasDelegate()) { + delegate.addCellEditorListener(l); + } + } + + @Override + public void removeCellEditorListener(CellEditorListener l) { + if (hasDelegate()) { + delegate.removeCellEditorListener(l); + } + } + + protected TableCellEditor findDelegate(JTable table, OptionModel option) { + Class<?> type = option.getType(); + if (char.class.equals(type)) { + type = String.class; + } + TableCellEditor editor = table.getDefaultEditor(type); + TableCellEditor defaultEditor = table.getDefaultEditor(Object.class); + // always Search from option.getEditor() and store editor as cache + if (option.getEditor() != null) { + editor = option.getEditor(); + table.setDefaultEditor(type, editor); + + } else if (editor.equals(defaultEditor)) { + // find not a specialized editor for the type + if (type.isEnum()) { + // add a EnumEditor to table + editor = new DefaultCellEditor(EnumEditor.newEditor((Class<Enum>) type)); + + } else if (type.equals(Class.class)) { + editor = new ClassCellEditor(); + + } else if (type.equals(File.class)) { + editor = new FileCellEditorWithExtDetector(); + + } else if (type.equals(KeyStroke.class)) { + editor = JAXXWidgetUtil.newKeyStrokeTableCellEditor(); + + } else if (type.equals(Locale.class)) { + editor = new DefaultCellEditor(LocaleEditor.newEditor()); + + } else if (type.equals(Color.class)) { + editor = new ColorCellEditor(); + + } else { + editor = table.getDefaultEditor(String.class); + } + table.setDefaultEditor(type, editor); + } + if (editor == null) { + throw new IllegalStateException("could not find a editor for type +" + type); + } + return editor; + } + + protected static class FileCellEditorWithExtDetector extends FileCellEditor { + + private static final long serialVersionUID = 1L; + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + + String fileExtension = value == null ? null : Files.getFileExtension(((File) value).getName()); + if (StringUtils.isNotEmpty(fileExtension)) { + fileEditor.setExts(fileExtension); + fileEditor.setAcceptAllFileFilterUsed(true); + } + return super.getTableCellEditorComponent(table, value, isSelected, row, column); + } + } + + protected boolean hasDelegate() { + return delegate != null; + } +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigTableRenderer.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigTableRenderer.java new file mode 100644 index 0000000..361daf2 --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigTableRenderer.java @@ -0,0 +1,126 @@ +package org.nuiton.jaxx.config; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.config.model.ConfigTableModel; +import org.nuiton.jaxx.config.model.OptionModel; + +import javax.swing.JComponent; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; + +import static org.nuiton.i18n.I18n.t; + +/** + * Pour le rendu du tableau des options d'une categorie + * + * @author Tony Chemit - chemit@codelutin.com + * @see ConfigTableModel + * @since 2.5.11 + */ +public class ConfigTableRenderer extends DefaultTableCellRenderer { + + private static final long serialVersionUID = 1L; + + protected static Color col; + + protected static Font font; + + protected static Font font2; + + public ConfigTableRenderer() { + col = getForeground(); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + int modelRow = table.convertRowIndexToModel(row); + int modelColumn = table.convertColumnIndexToModel(column); + ConfigTableModel model = (ConfigTableModel) table.getModel(); + OptionModel key = model.getEntry(modelRow); + boolean isModified = key.isModified(); + + boolean isValid = key.isValid(); + + if (font == null) { + font = getFont(); + font2 = font.deriveFont(Font.ITALIC | Font.BOLD); + } + Component cellRenderer; + switch (modelColumn) { + case 0: + cellRenderer = getKeyCellRenderer(table, value, isSelected, hasFocus, modelRow, modelColumn, key, isValid, isModified); + break; + case 1: + cellRenderer = getValueCellRenderer(table, value, isSelected, hasFocus, modelRow, modelColumn, key, isValid, isModified); + break; + case 2: + cellRenderer = getValueCellRenderer(table, value, isSelected, hasFocus, modelRow, modelColumn, key, isValid, isModified); + break; + default: + throw new IllegalStateException("no renderer find for column " + modelColumn); + } + return cellRenderer; + } + + protected Component getKeyCellRenderer(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column, OptionModel key, boolean isValid, boolean isModified) { + String tooltip = t(key.getDescription()) + " (" + key.getKey() + ")"; + String originalValue = key.toString(key.getOriginalValue()); + boolean isFinal = key.isFinal(); + if (isFinal) { + tooltip += " [" + t("config.unmodifiable") + ']'; + } + if (isModified) { + String s = t("config.modified", originalValue); + value = value + " *"; + tooltip += " [" + s + ']'; + } + if (!isValid) { + String s2 = t("config.unvalid", originalValue, key.getType()); + tooltip += " (" + s2 + ")"; + value = value + " !"; + } + JComponent result = (JComponent) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + result.setToolTipText(tooltip); + result.setForeground(isValid ? col : Color.RED); + result.setFont(isModified || !isValid ? font2 : font); + result.setEnabled(!isFinal); + return result; + } + + protected Component getValueCellRenderer(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column, OptionModel key, boolean isValid, boolean isModified) { + Component result; + if (key.getRenderer() != null) { + result = key.getRenderer().getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + + } else { + TableCellRenderer defaultRenderer = table.getDefaultRenderer(key.getType()); + result = defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + } + return result; + } +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigUI.jaxx b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigUI.jaxx new file mode 100644 index 0000000..664c9c7 --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigUI.jaxx @@ -0,0 +1,56 @@ +<!-- + #%L + JAXX :: Config + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.config.model.ConfigUIModel + </import> + + <script><![CDATA[ + +public void init(String defaultCategory) { + getHandler().initUI(defaultCategory); +} + +@Override +protected void finalize() throws Throwable { + super.finalize(); + getHandler().destroy(); +} + ]]> + </script> + + <ConfigUIHandler id='handler' constructorParams='this'/> + + <!-- le modele de l'ui --> + <ConfigUIModel id='model' + initializer='getContextValue(ConfigUIModel.class)'/> + + <!-- les differentes categories de la configuration --> + <JTabbedPane id='categories' constraints='BorderLayout.CENTER' + onStateChanged='getHandler().changeCategory(event)'/> + + <!-- pour quitter l'ui --> + <JPanel layout='{new GridLayout(1,0)}' constraints='BorderLayout.SOUTH'> + <JButton id='quit'/> + </JPanel> +</JPanel> diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigUI.jcss b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigUI.jcss similarity index 100% rename from jaxx-config/src/main/java/jaxx/runtime/swing/config/ConfigUI.jcss rename to jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigUI.jcss diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigUIHandler.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigUIHandler.java new file mode 100644 index 0000000..18a2170 --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigUIHandler.java @@ -0,0 +1,433 @@ +package org.nuiton.jaxx.config; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.context.JAXXInitialContext; +import org.nuiton.jaxx.config.model.CallBackEntry; +import org.nuiton.jaxx.config.model.CallBackMap; +import org.nuiton.jaxx.config.model.CategoryModel; +import org.nuiton.jaxx.config.model.ConfigUIModel; +import org.nuiton.jaxx.config.model.OptionModel; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.DefaultSingleSelectionModel; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRootPane; +import javax.swing.JTabbedPane; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import java.awt.Container; +import java.awt.Frame; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.ArrayList; + +import static org.nuiton.i18n.I18n.t; + +/** + * Handler of the {@link ConfigUI} ui. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class ConfigUIHandler { + + public static final Log log = LogFactory.getLog(ConfigUIHandler.class); + + public static final String CALLBACKS_WITH_OPTIONS = "callbacksWithOptions"; + + public static final String CALLBACKS = "callbacks"; + + public static final String QUIT_ACTION = "quit"; + + private final ConfigUI ui; + + /** + * Set this container if you want to use the ui inside another one (a.k.a not in standalone mode). + */ + private Container topContainer; + + + /** + * To customize the config call back ui before showning it. + * + * @since 2.37 + */ + private ConfigCallBackUICustomizer configCallBackUICustomizer; + + /** + * To be able to veto a change of a category. + * + * @since 2.6 + */ + public static interface ChangeCategoryCallBack { + boolean canChangeCategory(String categoryName); + } + + private ChangeCategoryCallBack changeCategoryCallBack; + + public ConfigUIHandler(ConfigUI ui) { + this.ui = ui; + } + + public void setChangeCategoryCallBack(ChangeCategoryCallBack changeCategoryCallBack) { + this.changeCategoryCallBack = changeCategoryCallBack; + } + + public void initUI(String defaultCategory) { + + ConfigUIModel model = ui.getModel(); + + JTabbedPane categories = ui.getCategories(); + + categories.setModel(new DefaultSingleSelectionModel() { + + private static final long serialVersionUID = 1L; + + @Override + public void setSelectedIndex(int index) { + // check if catgeory can be quit + boolean canContinue = !isSelected() || canQuitCategory(); + if (canContinue) { + // was authorized to leave previous category + if (log.isDebugEnabled()) { + log.debug("new index : " + index); + } + String categoryName = ConfigUIHandler.this.ui.getModel().getCategoryName(index); + if (changeCategoryCallBack == null || changeCategoryCallBack.canChangeCategory(categoryName)) { + // can change category + super.setSelectedIndex(index); + } + } + } + }); + + JButton quitButton = ui.getQuit(); + + // prepare quit action + Action quitAction = createQuitAction(); + + String tip = quitButton.getToolTipText(); + quitButton.setAction(quitAction); + quitButton.setToolTipText(tip); + + // build categories tabs + for (CategoryModel categoryModel : model) { + String category = categoryModel.getCategory(); + String categoryLabel = t(categoryModel.getCategoryLabel()); + ConfigCategoryUI p = new ConfigCategoryUI( + new JAXXInitialContext().add(ui).add(categoryModel)); + p.getCategoryLabel().setText(categoryLabel); + p.setName(category); + categories.addTab(t(category), null, p, categoryLabel); + } + + model.setCategory(defaultCategory); + int categoryIndex = model.getCategoryIndex(defaultCategory); + if (log.isDebugEnabled()) { + log.debug("index of default category (" + defaultCategory + ") : " + + categoryIndex); + } + categories.setSelectedIndex(categoryIndex); + } + + public void destroy() { + if (log.isDebugEnabled()) { + log.debug("destroy ui " + ui.getName()); + } + JAXXUtil.destroy(ui); + ui.getModel().destroy(); + } + + public void changeCategory(ChangeEvent e) { + JPanel p = (JPanel) ui.getCategories().getSelectedComponent(); + if (p == null) { + // pas de selection + return; + } + ui.getModel().setCategory(p.getName()); + ui.getCategories().invalidate(); + } + + public void displayUI(Frame parentUI, boolean undecorated) { + JDialog f = new JDialog(parentUI, true); + f.setTitle(t("config.title")); + f.add(ui); + if (parentUI != null) { + f.setIconImage(parentUI.getIconImage()); + } + // pour savoir si l'ui est autonome + ui.getModel().setStandalone(parentUI == null); + + f.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); + f.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + ActionEvent myEvent = new ActionEvent(e.getSource(), 1, QUIT_ACTION); + ui.getQuit().getAction().actionPerformed(myEvent); + } + }); + f.setUndecorated(undecorated); + JRootPane rootPane = f.getRootPane(); + rootPane.setDefaultButton(ui.getQuit()); + rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( + KeyStroke.getKeyStroke("ESCAPE"), QUIT_ACTION); + rootPane.getActionMap().put(QUIT_ACTION, ui.getQuit().getAction()); + f.pack(); + SwingUtil.center(parentUI, f); + f.setVisible(true); + } + + protected Action createQuitAction() { + + JButton button = ui.getQuit(); + + return new AbstractAction(button.getText(), + button.getIcon()) { + + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + if (!canQuitCategory()) { + return; + } + + Window parentWindow; + + final Container parentContainer; + + if (topContainer == null) { + + // no top container given, still use the parent frame + + parentWindow = ui.getParentContainer(Window.class); + parentContainer = parentWindow; + + } else { + + // use only given topContainer + parentWindow = null; + parentContainer = topContainer; + } + + ConfigUIModel model = ui.getModel(); + if (!model.isSaved() || model.isStandalone()) { + + // just quit, no callBack can be apply here + closeUI(parentWindow, model); + return; + } + + CallBackMap forSaved = model.getCallBacksForSaved(); + + if (forSaved.isEmpty()) { + + // just quit, no callBack to call + closeUI(parentWindow, model); + return; + } + + forSaved = model.getCallBacksForSaved(); + + // init callBackUI + + JAXXInitialContext context = new JAXXInitialContext(). + add(ui). + add(CALLBACKS_WITH_OPTIONS, forSaved). + add(CALLBACKS, + new ArrayList<CallBackEntry>(forSaved.keySet())). + add(new ConfigCallBackUIHandler()); + + if (topContainer == null) { + + // still add parent window (to close ui) + context.add("parent", parentWindow); + } + + ConfigCallBackUI lastUI = new ConfigCallBackUI(context); + lastUI.init(); + + if (configCallBackUICustomizer != null) { + configCallBackUICustomizer.customize(lastUI); + } + ui.setVisible(false); + parentContainer.remove(ui); + parentContainer.add(lastUI); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + parentContainer.validate(); + } + }); + } + }; + } + + public void setConfigCallBackUICustomizer(ConfigCallBackUICustomizer configCallBackUICustomizer) { + this.configCallBackUICustomizer = configCallBackUICustomizer; + } + + /** + * To customize config call back ui. + * + * @since 2.37 + */ + public interface ConfigCallBackUICustomizer { + + void customize(ConfigCallBackUI callBackUI); + } + + + protected void closeUI(Window parentWindow, ConfigUIModel model) { + + destroy(); + + if (parentWindow != null) { + + // close the config ui + parentWindow.dispose(); + } + + Runnable runnable = model.getCloseAction(); + if (runnable != null) { + log.info("execute close action"); + runnable.run(); + } + } + + protected boolean canQuitCategory() { + boolean canContinue = true; + ConfigUIModel model = ui.getModel(); + CategoryModel categoryModel = model.getCategoryModel(); + String categoryName = t(categoryModel.getCategory()); + if (!categoryModel.isValid()) { + + // the category is not valid + // get all the invalid options + + StringBuilder buffer = new StringBuilder(); + buffer.append(t("config.message.quit.invalid.category", + categoryName)); + buffer.append('\n'); + for (OptionModel m : categoryModel.getInvalidOptions()) { + buffer.append("\n- ").append(m.getKey()); + } + buffer.append('\n'); + int reponse = askUser(t("config.title.need.confirm"), + buffer.toString(), + JOptionPane.ERROR_MESSAGE, + new Object[]{ + t("config.choice.continue"), + t("config.choice.cancel")}, + 0); + + switch (reponse) { + case JOptionPane.CLOSED_OPTION: + case 1: + canContinue = false; + break; + case 0: + if (categoryModel.isModified()) { + // wil reset category + model.reset(); + } + break; + } + } else if (categoryModel.isModified()) { + + // category was modified, ask user if wants to save + + StringBuilder buffer = new StringBuilder(); + buffer.append(t("config.message.quit.valid.and.modified.category", + categoryName)).append('\n'); + for (OptionModel m : categoryModel.getModifiedOptions()) { + buffer.append("\n- ").append(m.getKey()); + } + buffer.append('\n'); + + int reponse = askUser(t("config.title.need.confirm"), + buffer.toString(), + JOptionPane.WARNING_MESSAGE, + new Object[]{ + t("config.choice.save"), + t("config.choice.doNotSave"), + t("config.choice.cancel")}, + 0); + + switch (reponse) { + case JOptionPane.CLOSED_OPTION: + case 2: + canContinue = false; + break; + case 0: + // will save ui + model.saveModified(); + break; + case 1: + // wil reset ui + model.reset(); + break; + } + } + return canContinue; + } + + public int askUser(String title, + String message, + int typeMessage, + Object[] options, + int defaultOption) { + + return JOptionPane.showOptionDialog( + ui, + message, + title, + JOptionPane.DEFAULT_OPTION, + typeMessage, + null, + options, + options[defaultOption] + ); + } + + public void setTopContainer(Container topContainer) { + this.topContainer = topContainer; + } + +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigUIHelper.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigUIHelper.java new file mode 100644 index 0000000..4bfedc4 --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/ConfigUIHelper.java @@ -0,0 +1,221 @@ +package org.nuiton.jaxx.config; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import org.nuiton.jaxx.runtime.JAXXContext; +import org.nuiton.jaxx.runtime.context.JAXXInitialContext; +import org.nuiton.jaxx.config.model.CallBackFinalizer; +import org.nuiton.jaxx.config.model.CategoryModel; +import org.nuiton.jaxx.config.model.ConfigUIModel; +import org.nuiton.jaxx.config.model.ConfigUIModelBuilder; +import org.nuiton.jaxx.config.model.OptionModel; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.config.ApplicationConfig; +import org.nuiton.config.ConfigOptionDef; + +import javax.swing.Icon; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import java.awt.Frame; +import java.io.File; + +/** + * A helper to build a config ui. + * + * contains all states as method to build model, then ui and finally display it. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class ConfigUIHelper { + + public static final Log log = LogFactory.getLog(ConfigUIHelper.class); + + /** internal model builder */ + protected final ConfigUIModelBuilder modelBuilder; + + /** internal model after builder flush */ + protected ConfigUIModel model; + + protected ConfigUI ui; + + public ConfigUIHelper(Object configurationBean, ApplicationConfig config, File configFile) { + modelBuilder = new ConfigUIModelBuilder(); + modelBuilder.createModel(configurationBean, config, configFile); + } + + @Deprecated + public ConfigUIHelper(Supplier<ApplicationConfig> config) { + modelBuilder = new ConfigUIModelBuilder(); + modelBuilder.createModel(config, config.get(), config.get().getUserConfigFile()); + } + + @Deprecated + public ConfigUIHelper(Supplier<ApplicationConfig> config, File configFile) { + modelBuilder = new ConfigUIModelBuilder(); + modelBuilder.createModel(config, config.get(), configFile); + } + + @Deprecated + public ConfigUIHelper(Object configurationBean, ApplicationConfig config) { + modelBuilder = new ConfigUIModelBuilder(); + modelBuilder.createModel(configurationBean, config, config.getUserConfigFile()); + } + + @Deprecated + public ConfigUIHelper(ApplicationConfig config, File configFile) { + modelBuilder = new ConfigUIModelBuilder(); + modelBuilder.createModel(config, config, configFile); + } + + @Deprecated + public ConfigUIHelper(ApplicationConfig config) { + modelBuilder = new ConfigUIModelBuilder(); + modelBuilder.createModel(config, config, config.getUserConfigFile()); + } + + public ConfigUIModel getModel() { + if (model == null) { + model = modelBuilder.flushModel(); + } + return model; + } + + public ConfigUIModelBuilder addCategory(String categoryName, String categoryLabel) + throws IllegalStateException, NullPointerException { + modelBuilder.addCategory(categoryName, categoryLabel); + return modelBuilder; + } + + public ConfigUIModelBuilder addCategory(String categoryName, String categoryLabel, String categoryCallback) + throws IllegalStateException, NullPointerException { + modelBuilder.addCategory(categoryName, categoryLabel, categoryCallback); + return modelBuilder; + } + + public ConfigUIModelBuilder addOption(ConfigOptionDef def) + throws IllegalStateException, NullPointerException { + modelBuilder.addOption(def); + return modelBuilder; + } + + @Deprecated + public ConfigUIModelBuilder addOption(ConfigOptionDef def, String propertyName) + throws IllegalStateException, NullPointerException { + modelBuilder.addOption(def, propertyName); + return modelBuilder; + } + + public ConfigUIModelBuilder setOptionPropertyName(String propertyName) + throws IllegalStateException, NullPointerException { + modelBuilder.setOptionPropertyName(propertyName); + return modelBuilder; + } + + public ConfigUIModelBuilder setOptionShortLabel(String shortLabel) + throws IllegalStateException, NullPointerException { + modelBuilder.setOptionShortLabel(shortLabel); + return modelBuilder; + } + + public ConfigUIModelBuilder setOptionEditor(TableCellEditor editor) + throws IllegalStateException, NullPointerException { + modelBuilder.setOptionEditor(editor); + return modelBuilder; + } + + public ConfigUIModelBuilder setOptionRenderer(TableCellRenderer renderer) + throws IllegalStateException, NullPointerException { + modelBuilder.setOptionRenderer(renderer); + return modelBuilder; + } + + public ConfigUIModelBuilder registerCallBack(String name, + String description, + Icon icon, + Runnable action) { + modelBuilder.registerCallBack(name, description, icon, action); + return modelBuilder; + } + + public ConfigUIModelBuilder setOptionCallBack(String name) { + modelBuilder.setOptionCallBack(name); + return modelBuilder; + } + + public ConfigUIModelBuilder setModel(ConfigUIModel model) throws IllegalStateException { + modelBuilder.setModel(model); + return modelBuilder; + } + + public ConfigUIModelBuilder setCategory(CategoryModel categoryModel) + throws IllegalStateException { + modelBuilder.setCategory(categoryModel); + return modelBuilder; + } + + public ConfigUIModelBuilder setOption(OptionModel optionModel) + throws IllegalStateException { + modelBuilder.setOption(optionModel); + return modelBuilder; + } + + public ConfigUIModelBuilder setFinalizer(CallBackFinalizer finalizer) { + modelBuilder.setFinalizer(finalizer); + return modelBuilder; + } + + public ConfigUIModelBuilder setCloseAction(Runnable runnable) { + modelBuilder.setCloseAction(runnable); + return modelBuilder; + } + + /** + * Construire l'ui de configuration (sous forme de panel) + * + * @param parentContext le context applicatif + * @param defaultCategory la categorie a selectionner + * @return l'ui instanciate + */ + public ConfigUI buildUI(JAXXContext parentContext, + String defaultCategory) { + + ConfigUIModel model = getModel(); + + JAXXContext tx = new JAXXInitialContext().add(parentContext).add(model); + + ui = new ConfigUI(tx); + + ui.init(defaultCategory); + + return ui; + } + + public void displayUI(Frame parentUI, boolean undecorated) { + Preconditions.checkNotNull(ui, "UI was not build, use before the *buildUI* method"); + ui.getHandler().displayUI(parentUI, undecorated); + } +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CallBackEntry.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CallBackEntry.java new file mode 100644 index 0000000..fe9564d --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CallBackEntry.java @@ -0,0 +1,79 @@ +package org.nuiton.jaxx.config.model; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; + +/** + * A call back with his attached options. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class CallBackEntry { + + protected final String name; + protected final String description; + protected final Icon icon; + protected final Runnable action; + protected List<OptionModel> options; + + public CallBackEntry(String name, + String description, + Icon icon, + Runnable action) { + this.description = description; + this.icon = icon; + options = new ArrayList<OptionModel>(); + this.name = name; + this.action = action; + } + + public Runnable getAction() { + return action; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public Icon getIcon() { + return icon; + } + + public List<OptionModel> getOptions() { + // always send a copy + return new ArrayList<OptionModel>(options); + } + + protected void addOption(OptionModel option) { + options.add(option); + + } +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CallBackFinalizer.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CallBackFinalizer.java new file mode 100644 index 0000000..83ccbfd --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CallBackFinalizer.java @@ -0,0 +1,40 @@ +package org.nuiton.jaxx.config.model; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/** + * Contract to finalize the callbacks to launch. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public interface CallBackFinalizer { + + /** + * Do finalize the result. + * + * @param result unfinalized result + * @return the finalized result + */ + CallBackMap finalize(CallBackMap result); +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CallBackMap.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CallBackMap.java new file mode 100644 index 0000000..5589664 --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CallBackMap.java @@ -0,0 +1,56 @@ +package org.nuiton.jaxx.config.model; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import java.util.LinkedHashMap; +import java.util.List; + +/** + * A convient map of callback entry for a list of option. + * + * This model is used to store callbacks to use before a saving action. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class CallBackMap extends LinkedHashMap<CallBackEntry, List<OptionModel>> { + private static final long serialVersionUID = 1L; + + public boolean containsCallBack(String callBackName) { + for (CallBackEntry entry : keySet()) { + if (callBackName.equals(entry.getName())) { + return true; + } + } + return false; + } + + public CallBackEntry getCallBack(String callBackName) { + for (CallBackEntry entry : keySet()) { + if (callBackName.equals(entry.getName())) { + return entry; + } + } + return null; + } +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CallBacksManager.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CallBacksManager.java new file mode 100644 index 0000000..231b639 --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CallBacksManager.java @@ -0,0 +1,248 @@ +package org.nuiton.jaxx.config.model; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * CallBack manager. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class CallBacksManager { + + /** lists of registred callback. */ + protected List<CallBackEntry> callbacks; + + /** optional callbacks finalizer */ + protected CallBackFinalizer finalizer; + + public CallBacksManager() { + callbacks = new ArrayList<CallBackEntry>(); + } + + /** + * Obtain the finalizer to use. + * + * @return the finalizer (can be {@code null}). + * @see CallBackFinalizer + */ + public CallBackFinalizer getFinalizer() { + return finalizer; + } + + /** + * Sets the finalizer. + * + * @param finalizer the new finalizer + * @see CallBackFinalizer + */ + public void setFinalizer(CallBackFinalizer finalizer) { + this.finalizer = finalizer; + } + + /** + * Registers a new callback. + * + * <b>Note:</b> the order of registred callback is used to determine + * the higher priority of callback to launch if required. + * + * @param name the unique name of a callback + * @param description the i18n key to describe the action + * @param icon icon of callBack (used in ui) + * @param action the action of the callback + */ + public void registerCallBack(String name, + String description, + Icon icon, + Runnable action) { + if (name == null) { + throw new NullPointerException( + "parameter 'name' can not be null"); + } + if (action == null) { + throw new NullPointerException( + "parameter 'action' can not be null"); + } + if (description == null) { + throw new NullPointerException( + "parameter 'description' can not be null"); + } + if (icon == null) { + throw new NullPointerException("parameter 'icon' can not be null"); + } + if (getCallBack(name) != null) { + throw new IllegalArgumentException( + "there is already a callback with name '" + name + "'"); + } + callbacks.add(new CallBackEntry(name, description, icon, action)); + } + + /** + * Registers a option into a known callback. + * + * @param name the name of the callback + * @param option the option to register for the given callback + */ + public void registerOption(String name, OptionModel option) { + if (name == null) { + throw new NullPointerException("parameter 'name' can not be null"); + } + if (option == null) { + throw new NullPointerException( + "parameter 'option' can not be null"); + } + CallBackEntry callback = getCallBack(name); + if (callback == null) { + throw new IllegalArgumentException( + "could not find a callback with name '" + name + "'"); + } + callback.addOption(option); + } + + /** + * Scan a model and grab per callBack the options saved. + * + * @param model the model to scan + * @return the dictionnary of options for each callback to launch + */ + public CallBackMap getCallBacksForSaved(ConfigUIModel model) { + + return getCallBacks(model, true, false); + } + + /** + * Scan a category and grab per callBack the options saved. + * + * @param category the category to scan + * @return the dictionnary of options for each callBack to launch + */ + public CallBackMap getCallBacksForSaved(CategoryModel category) { + + return getCallBacks(category, true, false); + } + + /** + * Scan a model and grab per callBack the options. + * + * @param model the model to scan + * @param modified {@code true} to include modified options + * @param saved {@code true} to include saved options + * @return the dictionnary of options for each callback to launch + */ + public CallBackMap getCallBacks(ConfigUIModel model, + boolean saved, + boolean modified) { + + CallBackMap result = new CallBackMap(); + + for (CategoryModel categoryModel : model) { + CallBackMap callBacks = + getCallBacks(categoryModel, saved, modified); + for (Map.Entry<CallBackEntry, List<OptionModel>> entry : + callBacks.entrySet()) { + CallBackEntry key = entry.getKey(); + List<OptionModel> value = entry.getValue(); + if (result.containsKey(key)) { + result.get(key).addAll(value); + } else { + result.put(key, value); + } + } + callBacks.clear(); + } + + CallBackFinalizer finalizer = getFinalizer(); + if (finalizer != null) { + result = finalizer.finalize(result); + } + return result; + } + + /** + * Scan a category and grab per callBack the options. + * + * @param category the category to scan + * @param modified {@code true} to include modified options + * @param saved {@code true} to include saved options + * @return the dictionnary of options for each callBack to launch + */ + public CallBackMap getCallBacks(CategoryModel category, + boolean saved, + boolean modified) { + + CallBackMap result = new CallBackMap(); + + for (OptionModel optionModel : category) { + if (modified && optionModel.isModified() || + saved && optionModel.isSaved()) { + CallBackEntry callBackEntry = getCallBack(optionModel); + if (callBackEntry != null) { + List<OptionModel> models = result.get(callBackEntry); + if (models == null) { + models = new ArrayList<OptionModel>(); + result.put(callBackEntry, models); + } + models.add(optionModel); + } + } + } + return result; + } + + /** + * Get the first callBack for a given option. + * + * @param option the option + * @return the first callBack (so the most important) on which the given + * option is attacjed. (can be null) + */ + protected CallBackEntry getCallBack(OptionModel option) { + for (CallBackEntry callback : callbacks) { + if (callback.getOptions().contains(option)) { + return callback; + } + } + return null; + } + + /** + * Obtain a registred callBack from his name. + * + * @param name the name of the searched callBack + * @return the callBack for the given name (or {@code null} if not found). + */ + protected CallBackEntry getCallBack(String name) { + for (CallBackEntry callback : callbacks) { + if (callback.getName().equals(name)) { + return callback; + } + } + return null; + } + +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CategoryModel.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CategoryModel.java new file mode 100644 index 0000000..9a2add5 --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/CategoryModel.java @@ -0,0 +1,223 @@ +package org.nuiton.jaxx.config.model; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.JAXXUtil; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * le modele d'une categorie d'options. + * + * Une categorie est un ensemble d'options. + * + * @author tchemit + * @since 2.5.11 + */ +public class CategoryModel implements Iterable<OptionModel>, Serializable { + + private static final long serialVersionUID = 1L; + + public static final String RELOAD_PROPERTY_NAME = "reload"; + + public static final String MODIFIED_PROPERTY_NAME = "modified"; + + public static final String VALID_PROPERTY_NAME = "valid"; + + /** category short name (i18n key) */ + protected String category; + + /** category long name (i18n key) */ + protected String categoryLabel; + + /** options of the category */ + protected List<OptionModel> entries; + + /** suport of modification */ + protected PropertyChangeSupport pcs = new PropertyChangeSupport(this); + + protected CategoryModel(String category, String categoryLabel) { + this.category = category; + this.categoryLabel = categoryLabel; + entries = new ArrayList<OptionModel>(); + } + + protected void addOption(OptionModel option) { + entries.add(option); + } + + @Deprecated + public CategoryModel(String category, + String categoryLabel, + OptionModel[] entries) { + this.category = category; + this.categoryLabel = categoryLabel; + this.entries = Collections.unmodifiableList(Arrays.asList(entries)); + } + + public String getCategory() { + return category; + } + + public String getCategoryLabel() { + return categoryLabel; + } + + public List<OptionModel> getEntries() { + return entries; + } + + public boolean isModified() { + boolean modified = false; + for (OptionModel m : this) { + if (m.isModified()) { + modified = true; + break; + } + } + return modified; + } + + public boolean isValid() { + boolean valid = true; + for (OptionModel m : this) { + if (!m.isValid()) { + valid = false; + break; + } + } + return valid; + } + + public OptionModel getOptionModel(String optionModelKey) { + OptionModel result = null; + for (OptionModel optionModel : this) { + if (optionModelKey.endsWith(optionModel.getKey())) { + result = optionModel; + break; + } + } + return result; + } + public void setValue(OptionModel key, Object val) { + boolean wasModified = isModified(); + boolean wasValid = isValid(); + key.setValue(val); + boolean modified = isModified(); + boolean valid = isValid(); + if (wasModified != modified) { + // change modified state + firePropertyChange(MODIFIED_PROPERTY_NAME, wasModified, modified); + } + if (wasValid != valid) { + // change valid state + firePropertyChange(VALID_PROPERTY_NAME, wasValid, valid); + } + } + + @Override + public Iterator<OptionModel> iterator() { + return entries.iterator(); + } + + public List<OptionModel> getInvalidOptions() { + + List<OptionModel> result = new ArrayList<OptionModel>(); + for (OptionModel m : this) { + if (!m.isValid()) { + result.add(m); + } + } + return result; + } + + public List<OptionModel> getModifiedOptions() { + + List<OptionModel> result = new ArrayList<OptionModel>(); + for (OptionModel m : this) { + if (m.isModified()) { + result.add(m); + } + } + return result; + } + + public List<OptionModel> getSavedOptions() { + List<OptionModel> result = new ArrayList<OptionModel>(); + for (OptionModel option : this) { + if (option.isSaved()) { + result.add(option); + } + } + return result; + } + + public void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + public boolean hasListeners(String propertyName) { + return pcs.hasListeners(propertyName); + } + + public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) { + return pcs.getPropertyChangeListeners(propertyName); + } + + public PropertyChangeListener[] getPropertyChangeListeners() { + return pcs.getPropertyChangeListeners(); + } + + public void destroy() { + JAXXUtil.destroy(pcs); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + destroy(); + } +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/ConfigTableModel.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/ConfigTableModel.java new file mode 100644 index 0000000..4d0d610 --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/ConfigTableModel.java @@ -0,0 +1,155 @@ +package org.nuiton.jaxx.config.model; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.lang3.StringUtils; +import org.nuiton.converter.ConverterUtil; + +import javax.swing.table.AbstractTableModel; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * le modele du tableau d'options pour une categorie donnee. + * + * Le modele se base sur le modele d'une categorie d'option. + * + * @author tchemit + * @see CategoryModel + * @since 2.5.11 + */ +public class ConfigTableModel extends AbstractTableModel { + + private static final long serialVersionUID = 1L; + + private static final Class<?>[] columnClass = {String.class, Object.class, String.class}; + + /** le modele d'une categorie */ + protected final CategoryModel categoryModel; + + public ConfigTableModel(CategoryModel categoryModel) { + this.categoryModel = categoryModel; + // listen of property reload of the category model + // to known when to refresh table + this.categoryModel.addPropertyChangeListener(CategoryModel.RELOAD_PROPERTY_NAME, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + fireTableDataChanged(); + } + }); + } + + public CategoryModel getCategoryModel() { + return categoryModel; + } + + public OptionModel getEntry(int rowIndex) { + return categoryModel.getEntries().get(rowIndex); + } + + @Override + public int getRowCount() { + return categoryModel.getEntries().size(); + } + + @Override + public int getColumnCount() { + return columnClass.length; + } + + @Override + public Class<?> getColumnClass(int columnIndex) { + return columnClass[columnIndex]; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return columnIndex == 1 && !getEntry(rowIndex).isFinal(); + } + + @Override + public Object getValueAt(int row, int column) { + OptionModel key = getEntry(row); + Object value = null; + switch (column) { + case 0: + // try first to use the shortLabel + value = key.getShortLabel(); + if (StringUtils.isBlank((String) value)) { + + // fallback to key + value = key.getKey(); + } + break; + case 1: + value = key.getValue(); + break; + case 2: + value = key.getDefaultValue(); + if (value != null) { + value = ConverterUtil.convert(key.getType(), value); + } + break; + } + return value; + } + + @Override + public void setValueAt(Object aValue, int row, int column) { + if (column != 1) { + // seul la colonne 1 est editable (valeur de l'option) + throw new IllegalArgumentException("can not edit column " + column); + } + OptionModel key = getEntry(row); + Object val; + if (aValue == null || key.getType().equals(aValue.getClass())) { + val = aValue; + } else { + String valStr = String.valueOf(aValue).trim(); + try { + val = ConverterUtil.convert(key.getType(), valStr); + if (val != null && val instanceof Integer) { + if (new Integer(0).equals(val) && !valStr.equals("0")) { + val = null; + } + } + } catch (Exception e) { + val = null; + } + } + categoryModel.setValue(key, val); + fireTableRowsUpdated(row, row); + } + + + public void destroy() { + categoryModel.destroy(); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + destroy(); + } +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/ConfigUIModel.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/ConfigUIModel.java new file mode 100644 index 0000000..2f0727e --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/ConfigUIModel.java @@ -0,0 +1,443 @@ +package org.nuiton.jaxx.config.model; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Joiner; +import com.google.common.base.Supplier; +import com.google.common.collect.Lists; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.config.ApplicationConfig; + +import javax.swing.Icon; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static org.nuiton.i18n.I18n.t; + +/** + * Le modele de l'ui des preferences. + * + * Ce modele contient les catégories des options. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class ConfigUIModel implements Iterable<CategoryModel> { + + /** Logger. */ + private static final Log log = LogFactory.getLog(ConfigUIModel.class); + + public static final String CATEGORY_MODEL_PROPERTY_NAME = "categoryModel"; + + /** le dictionnaire des options disponibles par categorie */ + protected final Map<String, CategoryModel> categories; + + /** + * Le fichier où sauvegarder la configuration. + * @since 2.5.21 + */ + protected final File configFile; + + /** La configuration de l'application */ + protected final Object configBean; + + /** La configuration de l'application */ + protected final ApplicationConfig applicationConfig; + + /** la cateogrie en cours d'utilisation */ + protected CategoryModel categoryModel; + + /** + * un drapeau pour savoir si la configuration a été modifiée au moins une + * fois. + * + * On utilise ce drapeau lors de la sortie pour verifier s'il faut ou non + * redemarer l'application (si non en mode standalone) + */ + protected boolean saved; + + /** + * un drapeau pour savoir si l'ui de configuration a été lancée en mode + * standalone ou pas. + * + * Si pas lancée en mode standalone, et si la confi a été sauvé on vérifie + * s'il ne faut pas relancer l'application. + */ + protected boolean standalone; + + /** Callbacks manager */ + protected CallBacksManager callBacksManager; + + /** + * optional action to execute (if not null) if no call backs fits. + * + * @since 1.4.2 + */ + protected Runnable closeAction; + + /** support of modification notifications */ + protected final PropertyChangeSupport pcs; + + public ConfigUIModel(Object configBean, ApplicationConfig applicationConfig, File configFile) { + this.configBean = configBean; + this.applicationConfig = applicationConfig; + this.configFile = configFile; + categories = new LinkedHashMap<String, CategoryModel>(); + callBacksManager = new CallBacksManager(); + pcs = new PropertyChangeSupport(this); + } + + @Deprecated + public ConfigUIModel(Supplier<ApplicationConfig> config) { + this(config, config.get(), config.get().getUserConfigFile()); + } + + @Deprecated + public ConfigUIModel(Object configBean, ApplicationConfig applicationConfig) { + this(configBean, applicationConfig, applicationConfig.getUserConfigFile()); + } + + @Deprecated + public ConfigUIModel(Supplier<ApplicationConfig> config, File configFile) { + this(config, config.get(), configFile); + } + + @Deprecated + public ConfigUIModel(ApplicationConfig applicationConfig) { + this(applicationConfig, applicationConfig, applicationConfig.getUserConfigFile()); + } + + @Deprecated + public ConfigUIModel(ApplicationConfig applicationConfig, File configFile) { + this(applicationConfig, applicationConfig, configFile); + } + + /** + * Ajoute une categorie dans le modele. + * + * @param category la categorie a ajouter au modèle. + */ + public void addCategory(CategoryModel category) { + if (categories.containsKey(category.getCategory())) { + throw new IllegalArgumentException( + t("config.error.category.already.exists", + category.getCategory())); + } + categories.put(category.getCategory(), category); + } + + /** + * Change la categorie en cours d'édition. + * + * @param category l'id de la categorie courante + */ + public void setCategory(String category) { + if (!categories.containsKey(category)) { + throw new IllegalArgumentException( + t("config.error.category.not.found", category)); + } + CategoryModel newCategoryModel = categories.get(category); + setCategoryModel(newCategoryModel); + newCategoryModel.firePropertyChange( + CategoryModel.MODIFIED_PROPERTY_NAME, false, + getCategoryModel().isModified()); + newCategoryModel.firePropertyChange( + CategoryModel.VALID_PROPERTY_NAME, false, + getCategoryModel().isValid()); + } + + /** + * Registers a new callback. + * + * <b>Note:</b> the order of registred callback is used to determine + * the higher priority of callback to launch if required. + * + * @param name the unique name of a callback + * @param description the i18n key to describe the action + * @param icon the icon of the callBack (used in ui) + * @param action the action of the callback + */ + public void registerCallBack(String name, + String description, + Icon icon, + Runnable action) { + callBacksManager.registerCallBack(name, description, icon, action); + } + + /** + * Registers a option into a known callback. + * + * @param name the name of the callback + * @param option the option to register for the given callback + */ + public void registerOptionCallBack(String name, OptionModel option) { + callBacksManager.registerOption(name, option); + } + + public void setFinalizer(CallBackFinalizer finalizer) { + callBacksManager.setFinalizer(finalizer); + } + + public Runnable getCloseAction() { + return closeAction; + } + + public void setCloseAction(Runnable closeAction) { + this.closeAction = closeAction; + } + + /** + * Obtain the dictionnary of callback for all to saved modified options. + * + * @return the dictonnary + */ + public CallBackMap getCallBacksForSaved() { + return callBacksManager.getCallBacksForSaved(this); + } + + @Override + public Iterator<CategoryModel> iterator() { + return categories.values().iterator(); + } + + public CategoryModel getCategoryModel() { + return categoryModel; + } + + public void setCategoryModel(CategoryModel categoryModel) { + CategoryModel old = this.categoryModel; + this.categoryModel = categoryModel; + firePropertyChange(CATEGORY_MODEL_PROPERTY_NAME, old, categoryModel); + } + + public boolean isSaved() { + return saved; + } + + public void setSaved(boolean saved) { + this.saved = saved; + } + + public boolean isStandalone() { + return standalone; + } + + public void setStandalone(boolean standalone) { + this.standalone = standalone; + } + + public void saveModified() { + // compute transients keys (to never be saved) + List<String> transients = new ArrayList<String>(); + + applicationConfig.setAdjusting(true); + + try { + for (OptionModel option : categoryModel) { + if (option.isModified()) { + Object value = option.getValue(); + if (option.getPropertyName() != null) { + + // this is a javaBean option, push value via mutator + try { + PropertyUtils.setProperty(configBean, + option.getPropertyName(), value); + } catch (Exception e) { + throw new RuntimeException( + "could not set property [" + + option.getPropertyName() + + "] with value = " + value, e); + } + } else { + + // simple option with no javabeans, just push the option + // value + + String toSave; + if (value == null) { + toSave = null; + } else { + + if (option.isArrayType()) { + int length = Array.getLength(value); + List<Object> values = Lists.newArrayListWithCapacity(length); + for (int i = 0; i < length; i++) { + values.add(Array.get(value, i)); + } + toSave = Joiner.on(",").join(values); + } else { + toSave = value.toString(); + } + } + applicationConfig.setOption(option.getKey(), toSave); + + } + // l'option a été sauvegardée, on la marque + option.setSaved(true); + // this is the new original value + option.initValue(value); + } + if (option.isTransient()) { + transients.add(option.getKey()); + } + } + } finally { + applicationConfig.setAdjusting(false); + } + + setSaved(true); + // save config + // Ano +// applicationConfig.saveForUser(transients.toArray(new String[transients.size()])); + try { + applicationConfig.save(configFile, false, transients.toArray(new String[transients.size()])); + } catch (IOException eee) { + if (log.isWarnEnabled()) { + log.warn(t("config.error.applicationconfig.save", configFile), + eee); + } + } + + // notify data has changed + categoryModel.firePropertyChange( + CategoryModel.MODIFIED_PROPERTY_NAME, + categoryModel.isModified(), true); + categoryModel.firePropertyChange( + CategoryModel.VALID_PROPERTY_NAME, + false, categoryModel.isValid()); + categoryModel.firePropertyChange( + CategoryModel.RELOAD_PROPERTY_NAME, false, true); + } + + public void reset() { + // reset all modified options of the current category + for (OptionModel key : categoryModel) { + if (key.isModified()) { + key.initValue(key.getOriginalValue()); + } + } + // notify data has changed + categoryModel.firePropertyChange( + CategoryModel.MODIFIED_PROPERTY_NAME, + categoryModel.isModified(), true); + categoryModel.firePropertyChange( + CategoryModel.VALID_PROPERTY_NAME, + false, categoryModel.isValid()); + categoryModel.firePropertyChange( + CategoryModel.RELOAD_PROPERTY_NAME, false, true); + } + + public int getCategoryIndex(String category) { + int i = 0; + for (CategoryModel m : this) { + if (category.equals(m.getCategory())) { + return i; + } + i++; + } + // not found + return -1; + } + + public void firePropertyChange(String propertyName, + Object oldValue, + Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + public boolean hasListeners(String propertyName) { + return pcs.hasListeners(propertyName); + } + + public PropertyChangeListener[] getPropertyChangeListeners( + String propertyName) { + return pcs.getPropertyChangeListeners(propertyName); + } + + public PropertyChangeListener[] getPropertyChangeListeners() { + return pcs.getPropertyChangeListeners(); + } + + public void destroy() { + JAXXUtil.destroy(pcs); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + destroy(); + } + + /** + * @return the underlined application config + * @deprecated since 2.5.4 use now {@link #getApplicationConfig()}. + */ + protected ApplicationConfig getConfig() { + return applicationConfig; + } + + /** + * @return the underlined application config + * @since 2.5.4 + */ + protected ApplicationConfig getApplicationConfig() { + return applicationConfig; + } + + protected CallBacksManager getCallBacksManager() { + return callBacksManager; + } + + public String getCategoryName(int index) { + return Lists.newArrayList(categories.keySet()).get(index); + } +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/ConfigUIModelBuilder.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/ConfigUIModelBuilder.java new file mode 100644 index 0000000..2ff8e25 --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/ConfigUIModelBuilder.java @@ -0,0 +1,550 @@ +package org.nuiton.jaxx.config.model; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.config.ApplicationConfig; +import org.nuiton.config.ConfigOptionDef; + +import javax.swing.Icon; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import java.io.File; + +/** + * A builder of {@link ConfigUIModel} + * Created: 22 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class ConfigUIModelBuilder { + + /** Logger */ + private static final Log log = LogFactory.getLog(ConfigUIModelBuilder.class); + + /** current model used */ + ConfigUIModel model; + + /** current category used */ + CategoryModel category; + + /** Current default callback used by a category. */ + String categoryDefaultCallBack; + + /** current option used */ + OptionModel option; + + /** + * Create a new model and set it as current model. + * + * @param configurationBean configuration bean used in model (optional) + * @param config the configuration used in model (can not be null) + * @param configFile configuration file where to save (can not be null) + * @return the builder + * @throws IllegalStateException if there is already a current model + * @throws NullPointerException if config or configFile is {@code null} + * @since 2.33 + */ + public ConfigUIModelBuilder createModel(Object configurationBean, ApplicationConfig config, File configFile) throws IllegalStateException, NullPointerException { + checkNoCurrent(model, "model"); + // configuration bean can be null + checkNotNull(config, "createModel", "config"); + checkNotNull(configFile, "createModel", "configFile"); + model = new ConfigUIModel(configurationBean, config, configFile); + + if (log.isDebugEnabled()) { + log.debug("model created : " + model); + } + return this; + } + + /** + * Create a new model and set it as current model. + * + * @param config the configuration used in model + * @return the builder + * @throws IllegalStateException if there is already a current model + * @throws NullPointerException if config is {@code null} + * @deprecated since 2.33, prefer use the {@link #createModel(Object, ApplicationConfig, File)} method instead, will be removed soon + */ + @Deprecated + public ConfigUIModelBuilder createModel(Supplier<ApplicationConfig> config) + throws IllegalStateException, NullPointerException { + return createModel(config, config.get(), config.get().getUserConfigFile()); + } + + /** + * Create a new model and set it as current model. + * + * @param config the configuration used in model + * @param configFile configuration file where to save (can not be null) + * @return the builder + * @throws IllegalStateException if there is already a current model + * @throws NullPointerException if config or configFile is {@code null} + * @since 2.5.21 + * @deprecated since 2.33, prefer use the {@link #createModel(Object, ApplicationConfig, File)} method instead, will be removed soon + */ + @Deprecated + public ConfigUIModelBuilder createModel(Supplier<ApplicationConfig> config, File configFile) + throws IllegalStateException, NullPointerException { + return createModel(config, config.get(), configFile); + } + + /** + * Create a new model and set it as current model. + * + * @param configurationBean configuration bean used in model + * @param config the configuration used in model + * @return the builder + * @throws IllegalStateException if there is already a current model + * @throws NullPointerException if there is some null parameters + * @deprecated since 2.33, prefer use the {@link #createModel(Object, ApplicationConfig, File)} method instead, will be removed soon + */ + @Deprecated + public ConfigUIModelBuilder createModel(Object configurationBean, ApplicationConfig config) + throws IllegalStateException, NullPointerException { + return createModel(configurationBean, config, config.getUserConfigFile()); + } + + /** + * Create a new model and set it as current model. + * + * @param config the configuration used in model + * @return the builder + * @throws IllegalStateException if there is already a current model + * @throws NullPointerException if config is {@code null} + * @deprecated since 2.33, prefer use the {@link #createModel(Object, ApplicationConfig, File)} method instead, will be removed soon + */ + @Deprecated + public ConfigUIModelBuilder createModel(ApplicationConfig config) throws IllegalStateException, NullPointerException { + return createModel(config, config, config.getUserConfigFile()); + } + + /** + * Create a new model and set it as current model. + * + * @param config the configuration used in model + * @param configFile configuration file where to save (can not be null) + * @return the builder + * @throws IllegalStateException if there is already a current model + * @throws NullPointerException if config or configFile is {@code null} + * @since 2.5.21 + * @deprecated since 2.33, prefer use the {@link #createModel(Object, ApplicationConfig, File)} method instead, will be removed soon + */ + @Deprecated + public ConfigUIModelBuilder createModel(ApplicationConfig config, File configFile) + throws IllegalStateException, NullPointerException { + return createModel(config, config, configFile); + } + + /** + * Add a new category, and set it as current. + * + * <b>Note:</b> As side effets, if a previous category, then store it to + * the model. + * + * @param categoryName the name of the new category + * (can not to be {@code null}) + * @param categoryLabel the label of the new category + * (can not to be {@code null}) + * @return the builder + * @throws IllegalStateException if there is not a current model, + * nor category + * @throws NullPointerException if any of parameter is {@code null} + */ + public ConfigUIModelBuilder addCategory(String categoryName, String categoryLabel) + throws IllegalStateException, NullPointerException { + checkCurrent(model, "model"); + checkNotNull(categoryName, "addCategory", "categoryName"); + checkNotNull(categoryLabel, "addCategory", "categoryLabel"); + flushCategory(); + category = new CategoryModel(categoryName, categoryLabel); + if (log.isDebugEnabled()) { + log.debug("category created : " + category); + } + return this; + } + + /** + * Add a new category, and set it as current. + * + * <b>Note:</b> As side effets, if a previous category, then store it to + * the model. + * + * @param categoryName the name of the new category + * (can not to be {@code null}) + * @param categoryLabel the label of the new category + * (can not to be {@code null}) + * @return the builder + * @throws IllegalStateException if there is not a current model, + * nor category + * @throws NullPointerException if any of parameter is {@code null} + */ + public ConfigUIModelBuilder addCategory(String categoryName, String categoryLabel, String defaultCallback) + throws IllegalStateException, NullPointerException { + checkCurrent(model, "model"); + checkNotNull(categoryName, "addCategory", "categoryName"); + checkNotNull(categoryLabel, "addCategory", "categoryLabel"); + flushCategory(); + categoryDefaultCallBack = defaultCallback; + category = new CategoryModel(categoryName, categoryLabel); + if (log.isDebugEnabled()) { + log.debug("category created : " + category); + } + return this; + } + + /** + * Add a new option, and set it as current. + * + * <b>Note:</b> As side effets, if a previous option, then store it to + * the model. + * + * @param def the def ot the new option + * @return the builder + * @throws IllegalStateException if there is not a current model, + * nor category + * @throws NullPointerException if any of parameter is {@code null} + */ + public ConfigUIModelBuilder addOption(ConfigOptionDef def) + throws IllegalStateException, NullPointerException { + checkCurrent(model, "model"); + checkCurrent(category, "category"); + checkNotNull(def, "addOption", "def"); + flushOption(); + Object value = model.getApplicationConfig().getOption(def); + option = new OptionModel(def, value); + if (categoryDefaultCallBack != null) { + + // use default callback + model.registerOptionCallBack(categoryDefaultCallBack, option); + } + if (log.isDebugEnabled()) { + log.debug("option created : " + option); + } + return this; + } + + /** + * Add a new option with a propertyName, and set it as current. + * + * <b>Note:</b> As side effets, if a previous option, then store it to + * the model. + * + * <b>Note:</b> This method is a short-cut for + * {@link #addOption(ConfigOptionDef)} then + * {@link #setOptionPropertyName(String)}. + * + * @param def the def ot the new option + * @param propertyName the propertyName to set on the option + * @return the builder + * @throws IllegalStateException if there is not a current model, nor + * category + * @throws NullPointerException if any of parameter is {@code null} + * @deprecated since 2.5.29, prefer use the {@link #setOptionPropertyName(String)} method instead, will be removed soon + */ + @Deprecated + public ConfigUIModelBuilder addOption(ConfigOptionDef def, + String propertyName) + throws IllegalStateException, NullPointerException { + addOption(def); + checkNotNull(propertyName, "setOptionPropertyName", "propertyName"); + option.setPropertyName(propertyName); + return this; + } + + /** + * Set the propertyName on the current option. + * + * @param propertyName the propertyName to set in the current option. + * @return the builder + * @throws IllegalStateException if there is not a current option set. + * @throws NullPointerException if any of parameter is {@code null} + * @see OptionModel#setPropertyName(String) + */ + public ConfigUIModelBuilder setOptionPropertyName(String propertyName) + throws IllegalStateException, NullPointerException { + checkCurrent(option, "option"); + checkNotNull(propertyName, "setOptionPropertyName", "propertyName"); + option.setPropertyName(propertyName); + return this; + } + + /** + * Set the short label on the current option. + * + * @param shortLabel the propertyName to set in the current option. + * @return the builder + * @throws IllegalStateException if there is not a current option set. + * @throws NullPointerException if any of parameter is {@code null} + * @see OptionModel#setShortLabel(String) + * @since 2.5.29 + */ + public ConfigUIModelBuilder setOptionShortLabel(String shortLabel) + throws IllegalStateException, NullPointerException { + checkCurrent(option, "option"); + checkNotNull(shortLabel, "setShortLabel", "shortLabel"); + option.setShortLabel(shortLabel); + return this; + } + + /** + * Set the editor on the current option. + * + * @param editor the editor to set in the current option. + * @return the builder + * @throws IllegalStateException if there is not a current option set. + * @throws NullPointerException if any of parameter is {@code null} + * @see OptionModel#setEditor(TableCellEditor) + */ + public ConfigUIModelBuilder setOptionEditor(TableCellEditor editor) + throws IllegalStateException, NullPointerException { + checkCurrent(option, "option"); + checkNotNull(editor, "setOptionEditor", "editor"); + option.setEditor(editor); + return this; + } + + /** + * Set the renderer on the current option. + * + * @param renderer the renderer to set in the current option. + * @return the builder + * @throws IllegalStateException if there is not a current option set. + * @throws NullPointerException if any of parameter is {@code null} + * @see OptionModel#setRenderer(TableCellRenderer) + */ + public ConfigUIModelBuilder setOptionRenderer(TableCellRenderer renderer) + throws IllegalStateException, NullPointerException { + checkCurrent(option, "option"); + checkNotNull(renderer, "setOptionRenderer", "renderer"); + option.setRenderer(renderer); + return this; + } + + /** + * Registers a new callback. + * + * <b>Note:</b> the order of registred callback is used to determine + * the higher priority of callback to launch if required. + * + * @param name the unique name of a callback + * @param description the i18n key to describe the action + * @param icon the icon of the callBack (used in ui) + * @param action the action of the callback + * @return the builder + */ + public ConfigUIModelBuilder registerCallBack(String name, + String description, + Icon icon, + Runnable action) { + checkCurrent(model, "model"); + checkNotNull(name, "registerCallBack", "name"); + checkNotNull(description, "registerCallBack", "description"); + checkNotNull(action, "registerCallBack", "action"); + model.registerCallBack(name, description, icon, action); + return this; + } + + /** + * Registers the current option into a known callback. + * + * @param name the name of the callback + * @return the builder + */ + public ConfigUIModelBuilder setOptionCallBack(String name) { + checkCurrent(option, "option"); + checkNotNull(name, "setOptionCallBack", "name"); + Preconditions.checkArgument( + categoryDefaultCallBack == null, + "You can not use the method *setOptionCallBack* when " + + "a default callback has been assigned to a category"); + + model.registerOptionCallBack(name, option); + return this; + } + + /** + * Sets the callback finalizet + * + * @param finalizer callback finalize + * @return the builder + * @see CallBackFinalizer + */ + public ConfigUIModelBuilder setFinalizer(CallBackFinalizer finalizer) { + model.setFinalizer(finalizer); + return this; + } + + /** + * Sets the default callback to use for this category (the call back + * will be add to all options of this category until you set another one or + * nullify it). + * + * @param categoryDefaultCallBack default callbakc name for the category + * @return the buider + */ + public ConfigUIModelBuilder setCategoryDefaultCallBack(String categoryDefaultCallBack) { + checkCurrent(model, "model"); + checkCurrent(category, "category"); + this.categoryDefaultCallBack = categoryDefaultCallBack; + return this; + } + + + /** + * Flush the model and return it. + * + * <b>Note:</b> As a side effect, nothing is available in the builder + * after this operation. + * To reuse the builder on a model, use the dedicated setter. + * + * @return the final model + * @throws IllegalStateException if there is not a current model set. + */ + public ConfigUIModel flushModel() throws IllegalStateException { + checkCurrent(model, "model"); + flushCategory(); + ConfigUIModel result = model; + model = null; + return result; + } + + /** + * Set the given model as current model. + * + * <b>Note:</b> As side effets, il will clean current category and option. + * + * @param model the model to use + * @return the buider + * @throws IllegalStateException if there is already a current model + */ + public ConfigUIModelBuilder setModel(ConfigUIModel model) throws IllegalStateException { + checkNoCurrent(model, "model"); + this.model = model; + if (log.isDebugEnabled()) { + log.debug("new current model : " + this.model); + } + category = null; + categoryDefaultCallBack = null; + option = null; + return this; + } + + /** + * Set the given category as current category. + * + * <b>Note:</b> As side effets, il will clean current option. + * + * @param categoryModel the category to use + * @return the buider + * @throws IllegalStateException if there is not a current model or a + * current category + */ + public ConfigUIModelBuilder setCategory(CategoryModel categoryModel) + throws IllegalStateException { + checkCurrent(model, "model"); + checkNoCurrent(category, "category"); + category = categoryModel; + categoryDefaultCallBack = null; + if (log.isDebugEnabled()) { + log.debug("new current category : " + category); + } + option = null; + return this; + } + + /** + * Sets the given option as current option. + * + * @param optionModel the option to use + * @return the buider + * @throws IllegalStateException if there is not a current model, nor + * category, or a current option + */ + public ConfigUIModelBuilder setOption(OptionModel optionModel) + throws IllegalStateException { + checkCurrent(model, "model"); + checkCurrent(category, "category"); + checkNoCurrent(option, "option"); + option = optionModel; + if (log.isDebugEnabled()) { + log.debug("new current option : " + option); + } + return this; + } + + public ConfigUIModelBuilder setCloseAction(Runnable runnable) { + checkNotNull(runnable, "setCloseAction", "runnable"); + checkCurrent(model, "model"); + model.setCloseAction(runnable); + return this; + } + + protected CategoryModel flushCategory() { + CategoryModel result = category; + if (category != null) { + flushOption(); + // add the previous category to the model + model.addCategory(category); + category = null; + categoryDefaultCallBack = null; + } + return result; + } + + protected OptionModel flushOption() { + OptionModel result = option; + if (option != null) { + // add the previous option to the category + category.addOption(option); + option = null; + } + return result; + } + + protected void checkCurrent(Object o, String type) { + if (o == null) { + throw new IllegalStateException("no current " + type + "!"); + } + } + + protected void checkNoCurrent(Object o, String type) { + if (o != null) { + throw new IllegalStateException( + "there is already a current " + type + "!"); + } + } + + protected void checkNotNull(Object o, String method, String parameter) { + if (o == null) { + throw new NullPointerException( + "method " + method + " does not support null parameter " + + parameter + "!"); + } + } +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/MainCallBackFinalizer.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/MainCallBackFinalizer.java new file mode 100644 index 0000000..3d5754e --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/MainCallBackFinalizer.java @@ -0,0 +1,63 @@ +package org.nuiton.jaxx.config.model; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import java.util.ArrayList; +import java.util.List; + +/** + * A finalizer to mark a special category to eat every others categories + * when finalizing. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class MainCallBackFinalizer implements CallBackFinalizer { + + /** name of call back which eats everybody */ + protected final String mainCallBack; + + public MainCallBackFinalizer(String mainCallBack) { + this.mainCallBack = mainCallBack; + } + + @Override + public CallBackMap finalize(CallBackMap result) { + CallBackEntry applicationEntry = result.getCallBack(mainCallBack); + CallBackMap newResult; + if (applicationEntry == null) { + // rien n'a change + newResult = result; + } else { + newResult = new CallBackMap(); + // on passe toutes les options sur ce callback + List<OptionModel> options = new ArrayList<OptionModel>(); + + for (List<OptionModel> optionModels : result.values()) { + options.addAll(optionModels); + } + newResult.put(applicationEntry, options); + } + return newResult; + } +} diff --git a/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/OptionModel.java b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/OptionModel.java new file mode 100644 index 0000000..6505bb4 --- /dev/null +++ b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/OptionModel.java @@ -0,0 +1,224 @@ +package org.nuiton.jaxx.config.model; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.nuiton.config.ConfigOptionDef; + +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; + +/** + * le modele d'une option de la configuration a editer. + * + * @author tchemit + * @since 2.5.11 + */ +public class OptionModel implements ConfigOptionDef { + + private static final long serialVersionUID = 1L; + + /** la definition de l'option (venant de la config) */ + protected final ConfigOptionDef def; + + /** un drapeau pour savoir si l'option est valide (n'est pas utilisé actuellement) */ + protected boolean valid = true; + + /** un drapeau pour savoir si l'option a été sauvée */ + protected boolean saved; + + /** la valeur non modifié de l'option */ + protected Object originalValue; + + /** la valeur actuelle de l'option (peut être la valeur orignal si non modifée) */ + protected Object value; + + /** le nom de la propriété javaBean (peut etre null, si option sans support javaBean) */ + protected String propertyName; + + /** + * Une description courte à utiliser à la place de la clef i18n. + * + * @since 2.5.29 + */ + protected String shortLabel; + + /** l'editeur utilise pour modifier graphiquement l'option */ + protected TableCellEditor editor; + + /** le renderer utilise pour afficher graphiquement l'option */ + protected TableCellRenderer renderer; + + protected OptionModel(ConfigOptionDef def, Object value) { + this.def = def; + initValue(value); + } + + public String getShortLabel() { + return shortLabel; + } + + public void setShortLabel(String shortLabel) { + this.shortLabel = shortLabel; + } + + @Override + public String getKey() { + return def.getKey(); + } + + @Override + public Class<?> getType() { + return def.getType(); + } + + public boolean isArrayType() { + return getType().isArray(); + } + + @Override + public String getDescription() { + return def.getDescription(); + } + + @Override + public String getDefaultValue() { + return def.getDefaultValue(); + } + + @Override + public boolean isTransient() { + return def.isTransient(); + } + + @Override + public boolean isFinal() { + return def.isFinal(); + } + + public Object getOriginalValue() { + return originalValue; + } + + public Object getValue() { + return value; + } + + @Override + public void setDefaultValue(String defaultValue) { + def.setDefaultValue(defaultValue); + } + + @Override + public void setTransient(boolean isTransient) { + def.setTransient(isTransient); + } + + @Override + public void setFinal(boolean isFinal) { + def.setFinal(isFinal); + } + + public void setValue(Object value) { + this.value = value; + } + + public boolean isModified() { + boolean result; + if (isArrayType()) { + result = !ArrayUtils.isEquals(originalValue, value); + } else { + result = ObjectUtils.notEqual(originalValue, value); + } + return result; + } + + public boolean isValid() { + return valid; + } + + public void setValid(boolean valid) { + this.valid = valid; + } + + public boolean isSaved() { + return saved; + } + + public void setSaved(boolean saved) { + this.saved = saved; + } + + public void initValue(Object originalValue) { + this.originalValue = originalValue; + value = originalValue; + } + + public String getPropertyName() { + return propertyName; + } + + public TableCellEditor getEditor() { + return editor; + } + + protected void setEditor(TableCellEditor editor) { + this.editor = editor; + } + + public TableCellRenderer getRenderer() { + return renderer; + } + + public void setRenderer(TableCellRenderer renderer) { + this.renderer = renderer; + } + + protected void setPropertyName(String propertyName) { + this.propertyName = propertyName; + } + + /** + * Get a string value of the given {@code value} considered as a value of + * this option, means if option is array type, then we will decorate the + * value as a array. + * + * @param value value to decorate + * @return decorated value + * @since 2.5.14 + */ + public String toString( Object value) { + String result; + if (value == null) { + result = null; + } else { + if (isArrayType()) { + result = ArrayUtils.toString(value); + } else { + result = String.valueOf(value); + } + } + return result; + } +} diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/model/package.html b/jaxx-config/src/main/java/org/nuiton/jaxx/config/model/package.html similarity index 100% rename from jaxx-config/src/main/java/jaxx/runtime/swing/config/model/package.html rename to jaxx-config/src/main/java/org/nuiton/jaxx/config/model/package.html diff --git a/jaxx-config/src/main/java/jaxx/runtime/swing/config/package.html b/jaxx-config/src/main/java/org/nuiton/jaxx/config/package.html similarity index 100% rename from jaxx-config/src/main/java/jaxx/runtime/swing/config/package.html rename to jaxx-config/src/main/java/org/nuiton/jaxx/config/package.html diff --git a/jaxx-config/src/test/java/jaxx/runtime/swing/config/model/MyDelegateConfig.java b/jaxx-config/src/test/java/jaxx/runtime/swing/config/model/MyDelegateConfig.java deleted file mode 100644 index 75c9219..0000000 --- a/jaxx-config/src/test/java/jaxx/runtime/swing/config/model/MyDelegateConfig.java +++ /dev/null @@ -1,267 +0,0 @@ -package jaxx.runtime.swing.config.model; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Supplier; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.beans.AbstractBean; -import org.nuiton.config.ApplicationConfig; -import org.nuiton.config.ConfigOptionDef; - -import java.awt.Color; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.Date; -import java.util.Locale; - -import static org.nuiton.i18n.I18n.t; - -/** - * A config to test config ui api when using a delegation - * on {@link ApplicationConfig}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class MyDelegateConfig extends AbstractBean implements Supplier<ApplicationConfig> { - - /** Logger */ - private static final Log log = LogFactory.getLog(MyDelegateConfig.class); - - public static final String PROPERTY_FULLSCREEN = "fullscreen"; - - public static final String PROPERTY_LOCALE = "locale"; - - public static final String PROPERTY_FONT_SIZE = "fontSize"; - - public static final String PROPERTY_ADJUSTING = "adjusting"; - - public static final String PROPERTY_DEMO_COLOR = "demoColor"; - - public static final String PROPERTY_DEMO_CLASS = "demoClass"; - - protected final ApplicationConfig applicationConfig; - - public MyDelegateConfig() { - this.applicationConfig = new ApplicationConfig(); - - applicationConfig.setConfigFileName(Option.CONFIG_FILE.defaultValue); - - // chargement de la configuration interne - - for (Option o : Option.values()) { - applicationConfig.setDefaultOption(o.key, o.defaultValue); - } - - applicationConfig.setAdjusting(true); - try { - addPropertyChangeListener(PROPERTY_FULLSCREEN, saveAction); - addPropertyChangeListener(PROPERTY_FONT_SIZE, saveAction); - addPropertyChangeListener(PROPERTY_LOCALE, saveAction); - addPropertyChangeListener(PROPERTY_DEMO_COLOR, saveAction); - addPropertyChangeListener(PROPERTY_DEMO_CLASS, saveAction); - } finally { - applicationConfig.setAdjusting(false); - } - } - - protected final PropertyChangeListener saveAction = new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (isAdjusting()) { - if (log.isDebugEnabled()) { - log.debug("skip save while adjusting"); - } - } else { - if (log.isDebugEnabled()) { - log.debug("Saving configuration at " + new Date()); - } - saveForUser(); - } - } - }; - - public void saveForUser(String... excludeKeys) { - // never save anything :) - } - - public boolean isFullScreen() { - Boolean result = applicationConfig.getOptionAsBoolean(Option.FULL_SCREEN.key); - return result != null && result; - } - - public Locale getLocale() { - return applicationConfig.getOption(Locale.class, Option.LOCALE.key); - } - - public Float getFontSize() { - return applicationConfig.getOption(Float.class, Option.FONT_SIZE.key); - } - - public Color getDemoColor() { - return applicationConfig.getOptionAsColor(Option.DEMO_COLOR.key); - } - - public Class<?> getDemoClass() { - return applicationConfig.getOptionAsClass(Option.DEMO_CLASS.key); - } - - public void setFullscreen(boolean fullscreen) { - Object oldValue = null; - applicationConfig.setOption(Option.FULL_SCREEN.key, fullscreen + ""); - firePropertyChange(PROPERTY_FULLSCREEN, oldValue, fullscreen); - } - - public void setLocale(Locale newLocale) { - applicationConfig.setOption(Option.LOCALE.key, newLocale.toString()); - firePropertyChange(PROPERTY_LOCALE, null, newLocale); - } - - public void setFontSize(Float newFontSize) { - Float oldValue = getFontSize(); - if (log.isDebugEnabled()) { - log.debug("changing font-size to " + newFontSize); - } - applicationConfig.setOption(Option.FONT_SIZE.key, newFontSize.toString()); - firePropertyChange(PROPERTY_FONT_SIZE, oldValue, newFontSize); - } - - public void setDemoColor(Color color) { - Color oldValue = getDemoColor(); - if (log.isDebugEnabled()) { - log.debug("changing demo-color to " + color); - } - applicationConfig.setOption(Option.DEMO_COLOR.key, color.toString()); - firePropertyChange(PROPERTY_DEMO_COLOR, oldValue, color); - } - - public void setDemoClass(Class<?> newClass) { - Class<?> oldValue = getDemoClass(); - if (log.isDebugEnabled()) { - log.debug("changing demo-class to " + newClass); - } - applicationConfig.setOption(Option.DEMO_CLASS.key, newClass.getName()); - firePropertyChange(PROPERTY_DEMO_CLASS, oldValue, newClass); - } - - public boolean isAdjusting() { - return applicationConfig.isAdjusting(); - } - - public void setAdjusting(boolean adjusting) { - applicationConfig.setAdjusting(adjusting); - } - - @Override - public ApplicationConfig get() { - return applicationConfig; - } - - ////////////////////////////////////////////////// - // Toutes les options disponibles - ////////////////////////////////////////////////// - - public enum Option implements ConfigOptionDef { - - CONFIG_FILE(ApplicationConfig.CONFIG_FILE_NAME, t("jaxxdemo.config.configFileName.description"), "jaxxdemo", String.class, true, true), - FULL_SCREEN("ui.fullscreen", t("jaxxdemo.config.ui.fullscreen"), "false", Boolean.class, false, false), - LOCALE("ui." + PROPERTY_LOCALE, t("jaxxdemo.config.ui." + PROPERTY_LOCALE), Locale.FRANCE.toString(), Locale.class, false, false), - FONT_SIZE("ui." + PROPERTY_FONT_SIZE, t("jaxxdemo.config.ui." + PROPERTY_FONT_SIZE), "10f", Float.class, false, false), - DEMO_COLOR("ui." + PROPERTY_DEMO_COLOR, t("jaxxdemo.config.ui.demoColor"), "#ffffff", Color.class, false, false), - DEMO_CLASS("ui." + PROPERTY_DEMO_CLASS, t("jaxxdemo.config.ui.demoClass"), "java.io.File", Class.class, false, false); - - public final String key; - - public final String description; - - public String defaultValue; - - public final Class<?> type; - - public boolean _transient; - - public boolean _final; - - Option(String key, - String description, - String defaultValue, - Class<?> type, - boolean _transient, - boolean _final) { - this.key = key; - this.description = description; - this.defaultValue = defaultValue; - this.type = type; - this._final = _final; - this._transient = _transient; - } - - @Override - public boolean isFinal() { - return _final; - } - - @Override - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - } - - @Override - public void setTransient(boolean _transient) { - this._transient = _transient; - } - - @Override - public void setFinal(boolean _final) { - this._final = _final; - } - - @Override - public boolean isTransient() { - return _transient; - } - - @Override - public String getDefaultValue() { - return defaultValue; - } - - @Override - public String getDescription() { - return description; - } - - @Override - public String getKey() { - return key; - } - - @Override - public Class<?> getType() { - return type; - } - } -} - diff --git a/jaxx-config/src/test/java/jaxx/runtime/swing/config/model/MyDelegateConfigTest.java b/jaxx-config/src/test/java/jaxx/runtime/swing/config/model/MyDelegateConfigTest.java deleted file mode 100644 index 1bacaa6..0000000 --- a/jaxx-config/src/test/java/jaxx/runtime/swing/config/model/MyDelegateConfigTest.java +++ /dev/null @@ -1,337 +0,0 @@ -package jaxx.runtime.swing.config.model; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.SwingUtil; -import jaxx.runtime.swing.editor.MyDefaultCellEditor; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.nuiton.config.ApplicationConfig; - -import javax.swing.ImageIcon; -import javax.swing.table.TableCellEditor; -import java.awt.Color; -import java.io.File; -import java.util.Collection; - -/** - * To test ConfigUI api on {@link MyDelegateConfig}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class MyDelegateConfigTest { - - - public static final String CATEGORY = "cat0"; - - protected ConfigUIModelBuilder builder; - - protected MyDelegateConfig config; - - @Before - public void setup() { - config = new MyDelegateConfig(); - builder = new ConfigUIModelBuilder(); - } - - @Test(expected = NullPointerException.class) - public void testCreateModelLimitCase0() throws Exception { - builder.createModel((ApplicationConfig) null); - } - - @Test(expected = IllegalStateException.class) - public void testFlushModelLimitCase0() throws Exception { - builder.flushModel(); - } - - @Test - public void testCreateModel() throws Exception { - ConfigUIModel configModel = builder - .createModel(config) - .flushModel(); - Assert.assertNotNull(configModel); - Assert.assertNotNull(configModel.getApplicationConfig()); - } - - @Test(expected = IllegalStateException.class) - public void testRegisterCallbackLimitCase() throws Exception { - builder.registerCallBack(null, null, null, null); - } - - @Test(expected = NullPointerException.class) - public void testRegisterCallbackLimitCase0() throws Exception { - builder.createModel(config) - .registerCallBack(null, null, null, null); - } - - @Test(expected = NullPointerException.class) - public void testRegisterCallbackLimitCase1() throws Exception { - builder.createModel(config) - .registerCallBack("yo", null, null, null); - } - - @Test(expected = NullPointerException.class) - public void testRegisterCallbackLimitCase2() throws Exception { - builder.createModel(config) - .registerCallBack("yo", "yo description", null, null); - } - - @Test(expected = NullPointerException.class) - public void testRegisterCallbackLimitCase4() throws Exception { - Runnable callback = new Runnable() { - - @Override - public void run() { - } - }; - builder.createModel(config) - .registerCallBack("yo", "yo description", null, callback); - } - - @Test - public void testRegisterCallback() throws Exception { - Runnable callback = new Runnable() { - - @Override - public void run() { - } - }; - ImageIcon icon = SwingUtil.createActionIcon("add"); - ConfigUIModel configModel = builder.createModel(config) - .registerCallBack("yo", "yo description", icon, callback) - .flushModel(); - Assert.assertNotNull(configModel); - Assert.assertNotNull(configModel.getApplicationConfig()); - CallBackEntry callBackEntry = - configModel.getCallBacksManager().getCallBack("yo"); - Assert.assertNotNull(callBackEntry); - - Assert.assertEquals(callback, callBackEntry.getAction()); - } - - @Test(expected = IllegalStateException.class) - public void testAddCategoryLimitCase0() throws Exception { - builder.addCategory(null, null); - } - - @Test(expected = NullPointerException.class) - public void testAddCategoryLimitCase1() throws Exception { - builder.createModel(config) - .addCategory(null, null); - } - - @Test(expected = NullPointerException.class) - public void testAddCategoryLimitCase2() throws Exception { - builder.createModel(config) - .addCategory("", null); - } - - @Test - public void testAddCategory() throws Exception { - CategoryModel categoryModel = builder - .createModel(config) - .addCategory("cat0", "cat0 label") - .flushCategory(); - Assert.assertNotNull(categoryModel); - Assert.assertEquals("cat0", categoryModel.category); - Assert.assertEquals("cat0 label", categoryModel.categoryLabel); - Assert.assertEquals(0, categoryModel.entries.size()); - - } - - @Test(expected = IllegalStateException.class) - public void testAddOptionLimitCase0() throws Exception { - builder.addOption(null); - } - - @Test(expected = IllegalStateException.class) - public void testAddOptionLimitCase1() throws Exception { - builder.createModel(config) - .addOption(null); - } - - @Test(expected = NullPointerException.class) - public void testAddOptionLimitCase2() throws Exception { - builder.createModel(config) - .addCategory("cat0", "cat0 label") - .addOption(null); - } - - @Test - public void testAddOption() throws Exception { - OptionModel optionModel = builder - .createModel(config) - .addCategory("cat0", "cat0 label") - .addOption(MyDelegateConfig.Option.LOCALE) - .flushOption(); - Assert.assertNotNull(optionModel); - Assert.assertEquals(MyDelegateConfig.Option.LOCALE, optionModel.def); - - CategoryModel categoryModel = builder.flushCategory(); - Assert.assertNotNull(categoryModel); - Assert.assertEquals("cat0", categoryModel.category); - Assert.assertEquals("cat0 label", categoryModel.categoryLabel); - Assert.assertEquals(1, categoryModel.entries.size()); - } - - @Test(expected = IllegalStateException.class) - public void testSetOptionPropertyNameLimitCase0() throws Exception { - builder.setOptionPropertyName(null); - } - - @Test(expected = IllegalStateException.class) - public void testSetOptionPropertyNameLimitCase1() throws Exception { - builder.createModel(config) - .setOptionPropertyName(null); - } - - @Test(expected = IllegalStateException.class) - public void testSetOptionPropertyNameLimitCase2() throws Exception { - builder.createModel(config) - .addCategory("cat0", "cat0 label") - .setOptionPropertyName(null); - } - - @Test(expected = NullPointerException.class) - public void testSetOptionPropertyNameLimitCase3() throws Exception { - builder.createModel(config) - .addCategory("cat0", "cat0 label") - .addOption(MyDelegateConfig.Option.LOCALE) - .setOptionPropertyName(null); - } - - @Test - public void testSetOptionPropertyName() throws Exception { - OptionModel optionModel = builder - .createModel(config) - .addCategory("cat0", "cat0 label") - .addOption(MyDelegateConfig.Option.LOCALE) - .setOptionPropertyName(MyDelegateConfig.PROPERTY_LOCALE) - .flushOption(); - Assert.assertNotNull(optionModel); - Assert.assertEquals(MyDelegateConfig.Option.LOCALE, optionModel.def); - Assert.assertEquals(MyDelegateConfig.PROPERTY_LOCALE, optionModel.propertyName); - Assert.assertNull(optionModel.editor); - } - - @Test(expected = IllegalStateException.class) - public void testSetOptionEditorLimitCase0() throws Exception { - builder.setOptionEditor(null); - } - - @Test(expected = IllegalStateException.class) - public void testSetOptionEditorLimitCase1() throws Exception { - builder.createModel(config) - .setOptionEditor(null); - } - - @Test(expected = IllegalStateException.class) - public void testSetOptionEditorLimitCase2() throws Exception { - builder.createModel(config) - .addCategory("cat0", "cat0 label") - .setOptionEditor(null); - } - - - @Test(expected = NullPointerException.class) - public void testSetOptionEditorLimitCase3() throws Exception { - builder.createModel(config) - .addCategory("cat0", "cat0 label") - .addOption(MyDelegateConfig.Option.LOCALE) - .setOptionEditor(null); - } - - @Test - public void testSetOptionEditor() throws Exception { - TableCellEditor cellEditor = MyDefaultCellEditor.newBooleanEditor(); - OptionModel optionModel = builder.createModel(config) - .addCategory("cat0", "cat0 label") - .addOption(MyDelegateConfig.Option.LOCALE) - .setOptionEditor(cellEditor) - .flushOption(); - Assert.assertNotNull(optionModel); - Assert.assertEquals(MyDelegateConfig.Option.LOCALE, optionModel.def); - Assert.assertNull(optionModel.propertyName); - Assert.assertEquals(cellEditor, optionModel.editor); - } - - @Test - public void testFlushModel() throws Exception { - ConfigUIModel configModel = builder - .createModel(config) - .flushModel(); - Assert.assertNotNull(configModel); - Assert.assertNull(builder.model); - } - - @Test - public void testSaveClassOption() throws Exception { - ConfigUIModel configModel = builder - .createModel(config) - .addCategory(CATEGORY, "cat0 label") - .addOption(MyDelegateConfig.Option.DEMO_CLASS) - .setOptionPropertyName(MyDelegateConfig.PROPERTY_DEMO_CLASS) - .flushModel(); - configModel.setCategory(CATEGORY); - - CategoryModel categoryModel = configModel.getCategoryModel(); - Assert.assertNotNull(categoryModel); - - OptionModel optionModel = categoryModel.getOptionModel(MyDelegateConfig.Option.DEMO_CLASS.getKey()); - Assert.assertNotNull(optionModel); - - categoryModel.setValue(optionModel, Collection.class); - - Assert.assertEquals(File.class, config.getDemoClass()); - - configModel.saveModified(); - - Assert.assertEquals(Collection.class, config.getDemoClass()); - } - - @Test - public void testSaveColorOption() throws Exception { - ConfigUIModel configModel = builder - .createModel(config) - .addCategory(CATEGORY, "cat0 label") - .addOption(MyDelegateConfig.Option.DEMO_COLOR) - .flushModel(); - configModel.setCategory(CATEGORY); - - CategoryModel categoryModel = configModel.getCategoryModel(); - Assert.assertNotNull(categoryModel); - - OptionModel optionModel = categoryModel.getOptionModel(MyDelegateConfig.Option.DEMO_COLOR.getKey()); - Assert.assertNotNull(optionModel); - - Color newColor = new Color(0, 0, 0); - categoryModel.setValue(optionModel, newColor); - - Assert.assertFalse(newColor.equals(config.getDemoColor())); - - configModel.saveModified(); - Assert.assertEquals(newColor, config.getDemoColor()); - } -} diff --git a/jaxx-config/src/test/java/jaxx/runtime/swing/config/model/MyInheritedConfig.java b/jaxx-config/src/test/java/jaxx/runtime/swing/config/model/MyInheritedConfig.java deleted file mode 100644 index 2a10834..0000000 --- a/jaxx-config/src/test/java/jaxx/runtime/swing/config/model/MyInheritedConfig.java +++ /dev/null @@ -1,278 +0,0 @@ -package jaxx.runtime.swing.config.model; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.config.ApplicationConfig; -import org.nuiton.config.ConfigOptionDef; - -import java.awt.Color; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.Date; -import java.util.Locale; - -import static org.nuiton.i18n.I18n.t; - -/** - * A config to test config ui api when using a delegation - * on {@link ApplicationConfig}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class MyInheritedConfig extends ApplicationConfig { - - /** Logger */ - private static final Log log = LogFactory.getLog(MyInheritedConfig.class); - - public static final String PROPERTY_FULLSCREEN = "fullscreen"; - - public static final String PROPERTY_LOCALE = "locale"; - - public static final String PROPERTY_FONT_SIZE = "fontSize"; - - public static final String PROPERTY_ADJUSTING = "adjusting"; - - public static final String PROPERTY_DEMO_COLOR = "demoColor"; - - public static final String PROPERTY_DEMO_CLASS = "demoClass"; - -// /** -// * un drapeau pour bloquer la sauvegarde lors de la modification en masse des options -// * via les setter. -// */ -// protected boolean adjusting; - - protected final PropertyChangeListener saveAction = new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (isAdjusting()) { - if (log.isDebugEnabled()) { - log.debug("skip save while adjusting"); - } - return; - } - if (log.isDebugEnabled()) { - log.debug("Saving configuration at " + new Date()); - } - saveForUser(); - } - }; - - @Override - public void saveForUser(String... excludeKeys) { - // never save anything :) - } - - public MyInheritedConfig() { - - setConfigFileName(Option.CONFIG_FILE.defaultValue); - - // chargement de la configuration interne - - for (Option o : Option.values()) { - setDefaultOption(o.key, o.defaultValue); - } - - setAdjusting(true); - try { - addPropertyChangeListener(PROPERTY_FULLSCREEN, saveAction); - addPropertyChangeListener(PROPERTY_FONT_SIZE, saveAction); - addPropertyChangeListener(PROPERTY_LOCALE, saveAction); - addPropertyChangeListener(PROPERTY_DEMO_COLOR, saveAction); - addPropertyChangeListener(PROPERTY_DEMO_CLASS, saveAction); - } finally { - setAdjusting(false); - } - } - - @Override - public void setOption(String key, String value) { - if (key.equals(PROPERTY_ADJUSTING)) { - setAdjusting(Boolean.valueOf(value)); - return; - } - super.setOption(key, value); - } - - - public boolean isFullScreen() { - Boolean result = getOptionAsBoolean(Option.FULL_SCREEN.key); - return result != null && result; - } - - public Locale getLocale() { - return getOption(Locale.class, Option.LOCALE.key); - } - - public Float getFontSize() { - return getOption(Float.class, Option.FONT_SIZE.key); - } - - public Color getDemoColor() { - return getOptionAsColor(Option.DEMO_COLOR.key); - } - - public Class<?> getDemoClass() { - return getOptionAsClass(Option.DEMO_CLASS.key); - } - - public void setFullscreen(boolean fullscreen) { - Object oldValue = null; - setOption(Option.FULL_SCREEN.key, fullscreen + ""); - firePropertyChange(PROPERTY_FULLSCREEN, oldValue, fullscreen); - } - - public void setLocale(Locale newLocale) { - setOption(Option.LOCALE.key, newLocale.toString()); - firePropertyChange(PROPERTY_LOCALE, null, newLocale); - } - - public void setFontSize(Float newFontSize) { - Float oldValue = getFontSize(); - if (log.isDebugEnabled()) { - log.debug("changing font-size to " + newFontSize); - } - setOption(Option.FONT_SIZE.key, newFontSize.toString()); - firePropertyChange(PROPERTY_FONT_SIZE, oldValue, newFontSize); - } - - public void setDemoColor(Color color) { - Color oldValue = getDemoColor(); - if (log.isDebugEnabled()) { - log.debug("changing demo-color to " + color); - } - setOption(Option.DEMO_COLOR.key, color.toString()); - firePropertyChange(PROPERTY_DEMO_COLOR, oldValue, color); - } - - public void setDemoClass(Class<?> newClass) { - Class<?> oldValue = getDemoClass(); - if (log.isDebugEnabled()) { - log.debug("changing demo-class to " + newClass); - } - setOption(Option.DEMO_CLASS.key, newClass.getName()); - firePropertyChange(PROPERTY_DEMO_CLASS, oldValue, newClass); - } - -// public boolean isAdjusting() { -// return adjusting; -// } -// -// public void setAdjusting(boolean adjusting) { -// if (log.isDebugEnabled()) { -// log.debug("changing adjusting to " + adjusting); -// } -// boolean oldValue = this.adjusting; -// this.adjusting = adjusting; -// firePropertyChange(PROPERTY_ADJUSTING, oldValue, adjusting); -// } - - ////////////////////////////////////////////////// - // Toutes les options disponibles - ////////////////////////////////////////////////// - - public enum Option implements ConfigOptionDef { - - CONFIG_FILE(CONFIG_FILE_NAME, t("jaxxdemo.config.configFileName.description"), "jaxxdemo", String.class, true, true), - FULL_SCREEN("ui.fullscreen", t("jaxxdemo.config.ui.fullscreen"), "false", Boolean.class, false, false), - LOCALE("ui." + PROPERTY_LOCALE, t("jaxxdemo.config.ui." + PROPERTY_LOCALE), Locale.FRANCE.toString(), Locale.class, false, false), - FONT_SIZE("ui." + PROPERTY_FONT_SIZE, t("jaxxdemo.config.ui." + PROPERTY_FONT_SIZE), "10f", Float.class, false, false), - DEMO_COLOR("ui." + PROPERTY_DEMO_COLOR, t("jaxxdemo.config.ui.demoColor"), "#ffffff", Color.class, false, false), - DEMO_CLASS("ui." + PROPERTY_DEMO_CLASS, t("jaxxdemo.config.ui.demoClass"), "java.io.File", Class.class, false, false); - - public final String key; - - public final String description; - - public String defaultValue; - - public final Class<?> type; - - public boolean _transient; - - public boolean _final; - - Option(String key, - String description, - String defaultValue, - Class<?> type, - boolean _transient, - boolean _final) { - this.key = key; - this.description = description; - this.defaultValue = defaultValue; - this.type = type; - this._final = _final; - this._transient = _transient; - } - - @Override - public boolean isFinal() { - return _final; - } - - @Override - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - } - - @Override - public void setTransient(boolean _transient) { - this._transient = _transient; - } - - @Override - public void setFinal(boolean _final) { - this._final = _final; - } - - @Override - public boolean isTransient() { - return _transient; - } - - @Override - public String getDefaultValue() { - return defaultValue; - } - - @Override - public String getDescription() { - return description; - } - - @Override - public String getKey() { - return key; - } - - @Override - public Class<?> getType() { - return type; - } - } -} diff --git a/jaxx-config/src/test/java/jaxx/runtime/swing/config/model/MyInheritedConfigTest.java b/jaxx-config/src/test/java/jaxx/runtime/swing/config/model/MyInheritedConfigTest.java deleted file mode 100644 index 9442fcb..0000000 --- a/jaxx-config/src/test/java/jaxx/runtime/swing/config/model/MyInheritedConfigTest.java +++ /dev/null @@ -1,349 +0,0 @@ -package jaxx.runtime.swing.config.model; - -/* - * #%L - * JAXX :: Config - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.SwingUtil; -import jaxx.runtime.swing.editor.MyDefaultCellEditor; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.nuiton.config.ApplicationConfig; - -import javax.swing.ImageIcon; -import javax.swing.table.TableCellEditor; -import java.awt.Color; -import java.io.File; -import java.util.Collection; - -/** - * To test ConfigUI api on {@link MyInheritedConfig}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.11 - */ -public class MyInheritedConfigTest { - - public static final String CATEGORY = "cat0"; - - protected ConfigUIModelBuilder builder; - - protected MyInheritedConfig config; - - @Before - public void setup() { - config = new MyInheritedConfig(); - builder = new ConfigUIModelBuilder(); - } - - @Test(expected = NullPointerException.class) - public void testCreateModelLimitCase0() throws Exception { - builder.createModel((ApplicationConfig) null); - } - - @Test(expected = IllegalStateException.class) - public void testFlushModelLimitCase0() throws Exception { - builder.flushModel(); - } - - @Test - public void testCreateModel() throws Exception { - ConfigUIModel configModel = builder - .createModel(config) - .flushModel(); - Assert.assertNotNull(configModel); - Assert.assertNotNull(configModel.getApplicationConfig()); - } - - @Test(expected = IllegalStateException.class) - public void testRegisterCallbackLimitCase() throws Exception { - builder.registerCallBack(null, null, null, null); - } - - @Test(expected = NullPointerException.class) - public void testRegisterCallbackLimitCase0() throws Exception { - builder.createModel(config) - .registerCallBack(null, null, null, null); - } - - @Test(expected = NullPointerException.class) - public void testRegisterCallbackLimitCase1() throws Exception { - builder.createModel(config) - .registerCallBack("yo", null, null, null); - } - - @Test(expected = NullPointerException.class) - public void testRegisterCallbackLimitCase2() throws Exception { - builder.createModel(config) - .registerCallBack("yo", "yo description", null, null); - } - - @Test(expected = NullPointerException.class) - public void testRegisterCallbackLimitCase4() throws Exception { - Runnable callback = new Runnable() { - - @Override - public void run() { - } - }; - builder.createModel(config) - .registerCallBack("yo", "yo description", null, callback); - } - - @Test - public void testRegisterCallback() throws Exception { - - Runnable callback = new Runnable() { - - @Override - public void run() { - } - }; - ImageIcon icon = SwingUtil.createActionIcon("add"); - ConfigUIModel configModel = builder - .createModel(config) - .registerCallBack("yo", "yo description", icon, callback) - .flushModel(); - Assert.assertNotNull(configModel); - Assert.assertNotNull(configModel.getApplicationConfig()); - CallBackEntry callBackEntry = - configModel.getCallBacksManager().getCallBack("yo"); - Assert.assertNotNull(callBackEntry); - - Assert.assertEquals(callback, callBackEntry.getAction()); - } - - @Test(expected = IllegalStateException.class) - public void testAddCategoryLimitCase0() throws Exception { - builder.addCategory(null, null); - } - - @Test(expected = NullPointerException.class) - public void testAddCategoryLimitCase1() throws Exception { - builder.createModel(config) - .addCategory(null, null); - } - - @Test(expected = NullPointerException.class) - public void testAddCategoryLimitCase2() throws Exception { - builder.createModel(config) - .addCategory("", null); - } - - @Test - public void testAddCategory() throws Exception { - CategoryModel categoryModel = builder - .createModel(config) - .addCategory("cat0", "cat0 label") - .flushCategory(); - Assert.assertNotNull(categoryModel); - Assert.assertEquals("cat0", categoryModel.category); - Assert.assertEquals("cat0 label", categoryModel.categoryLabel); - Assert.assertEquals(0, categoryModel.entries.size()); - - } - - @Test(expected = IllegalStateException.class) - public void testAddOptionLimitCase0() throws Exception { - builder.addOption(null); - } - - @Test(expected = IllegalStateException.class) - public void testAddOptionLimitCase1() throws Exception { - builder.createModel(config) - .addOption(null); - } - - @Test(expected = NullPointerException.class) - public void testAddOptionLimitCase2() throws Exception { - builder.createModel(config) - .addCategory("cat0", "cat0 label") - .addOption(null); - } - - @Test - public void testAddOption() throws Exception { - OptionModel optionModel = builder - .createModel(config) - .addCategory("cat0", "cat0 label") - .addOption(MyInheritedConfig.Option.LOCALE) - .flushOption(); - Assert.assertNotNull(optionModel); - Assert.assertEquals(MyInheritedConfig.Option.LOCALE, optionModel.def); - - CategoryModel categoryModel = builder.flushCategory(); - Assert.assertNotNull(categoryModel); - Assert.assertEquals("cat0", categoryModel.category); - Assert.assertEquals("cat0 label", categoryModel.categoryLabel); - Assert.assertEquals(1, categoryModel.entries.size()); - } - - @Test(expected = IllegalStateException.class) - public void testSetOptionPropertyNameLimitCase0() throws Exception { - builder.setOptionPropertyName(null); - } - - @Test(expected = IllegalStateException.class) - public void testSetOptionPropertyNameLimitCase1() throws Exception { - builder.createModel(config); - builder.setOptionPropertyName(null); - } - - @Test(expected = IllegalStateException.class) - public void testSetOptionPropertyNameLimitCase2() throws Exception { - builder.createModel(config) - .addCategory("cat0", "cat0 label") - .setOptionPropertyName(null); - } - - @Test(expected = NullPointerException.class) - public void testSetOptionPropertyNameLimitCase3() throws Exception { - builder.createModel(config) - .addCategory("cat0", "cat0 label") - .addOption(MyInheritedConfig.Option.LOCALE) - .setOptionPropertyName(null); - } - - @Test - public void testSetOptionPropertyName() throws Exception { - OptionModel optionModel = builder - .createModel(config) - .addCategory("cat0", "cat0 label") - .addOption(MyInheritedConfig.Option.LOCALE) - .setOptionPropertyName(MyInheritedConfig.PROPERTY_LOCALE) - .flushOption(); - Assert.assertNotNull(optionModel); - Assert.assertEquals(MyInheritedConfig.Option.LOCALE, optionModel.def); - Assert.assertEquals(MyInheritedConfig.PROPERTY_LOCALE, optionModel.propertyName); - Assert.assertNull(optionModel.editor); - } - - @Test(expected = IllegalStateException.class) - public void testSetOptionEditorLimitCase0() throws Exception { - builder.setOptionEditor(null); - } - - @Test(expected = IllegalStateException.class) - public void testSetOptionEditorLimitCase1() throws Exception { - builder.createModel(config); - builder.setOptionEditor(null); - } - - @Test(expected = IllegalStateException.class) - public void testSetOptionEditorLimitCase2() throws Exception { - builder.createModel(config) - .addCategory("cat0", "cat0 label") - .setOptionEditor(null); - } - - - @Test(expected = NullPointerException.class) - public void testSetOptionEditorLimitCase3() throws Exception { - builder.createModel(config) - .addCategory("cat0", "cat0 label") - .addOption(MyInheritedConfig.Option.LOCALE) - .setOptionEditor(null); - } - - @Test - public void testSetOptionEditor() throws Exception { - TableCellEditor cellEditor = MyDefaultCellEditor.newBooleanEditor(); - OptionModel optionModel = builder.createModel(config) - .addCategory("cat0", "cat0 label") - .addOption(MyInheritedConfig.Option.LOCALE) - .setOptionEditor(cellEditor) - .flushOption(); - Assert.assertNotNull(optionModel); - Assert.assertEquals(MyInheritedConfig.Option.LOCALE, optionModel.def); - Assert.assertNull(optionModel.propertyName); - Assert.assertEquals(cellEditor, optionModel.editor); - } - - @Test - public void testFlushModel() throws Exception { - ConfigUIModel configModel = builder - .createModel(config) - .flushModel(); - Assert.assertNotNull(configModel); - Assert.assertNull(builder.model); - } - - @Test - public void testSetModel() throws Exception { - - } - - @Test - public void testSetCategory() throws Exception { - } - - @Test - public void testSetOption() throws Exception { - } - - @Test - public void testSaveClassOption() throws Exception { - ConfigUIModel configModel = builder - .createModel(config) - .addCategory(CATEGORY, "cat0 label") - .addOption(MyDelegateConfig.Option.DEMO_CLASS) - .setOptionPropertyName(MyDelegateConfig.PROPERTY_DEMO_CLASS) - .flushModel(); - configModel.setCategory(CATEGORY); - CategoryModel categoryModel = configModel.getCategoryModel(); - Assert.assertNotNull(categoryModel); - - OptionModel optionModel = categoryModel.getOptionModel(MyDelegateConfig.Option.DEMO_CLASS.getKey()); - Assert.assertNotNull(optionModel); - - categoryModel.setValue(optionModel, Collection.class); - - Assert.assertEquals(File.class, config.getDemoClass()); - - configModel.saveModified(); - Assert.assertEquals(Collection.class, config.getDemoClass()); - } - - @Test - public void testSaveColorOption() throws Exception { - ConfigUIModel configModel = builder - .createModel(config) - .addCategory(CATEGORY, "cat0 label") - .addOption(MyDelegateConfig.Option.DEMO_COLOR) - .flushModel(); - configModel.setCategory(CATEGORY); - - CategoryModel categoryModel = configModel.getCategoryModel(); - Assert.assertNotNull(categoryModel); - - OptionModel optionModel = categoryModel.getOptionModel(MyDelegateConfig.Option.DEMO_COLOR.getKey()); - Assert.assertNotNull(optionModel); - - Color newColor = new Color(0, 0, 0); - categoryModel.setValue(optionModel, newColor); - - Assert.assertFalse(newColor.equals(config.getDemoColor())); - - configModel.saveModified(); - Assert.assertEquals(newColor, config.getDemoColor()); - } -} diff --git a/jaxx-config/src/test/java/org/nuiton/jaxx/config/model/MyDelegateConfig.java b/jaxx-config/src/test/java/org/nuiton/jaxx/config/model/MyDelegateConfig.java new file mode 100644 index 0000000..6850089 --- /dev/null +++ b/jaxx-config/src/test/java/org/nuiton/jaxx/config/model/MyDelegateConfig.java @@ -0,0 +1,267 @@ +package org.nuiton.jaxx.config.model; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Supplier; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.beans.AbstractBean; +import org.nuiton.config.ApplicationConfig; +import org.nuiton.config.ConfigOptionDef; + +import java.awt.Color; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Date; +import java.util.Locale; + +import static org.nuiton.i18n.I18n.t; + +/** + * A config to test config ui api when using a delegation + * on {@link ApplicationConfig}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class MyDelegateConfig extends AbstractBean implements Supplier<ApplicationConfig> { + + /** Logger */ + private static final Log log = LogFactory.getLog(MyDelegateConfig.class); + + public static final String PROPERTY_FULLSCREEN = "fullscreen"; + + public static final String PROPERTY_LOCALE = "locale"; + + public static final String PROPERTY_FONT_SIZE = "fontSize"; + + public static final String PROPERTY_ADJUSTING = "adjusting"; + + public static final String PROPERTY_DEMO_COLOR = "demoColor"; + + public static final String PROPERTY_DEMO_CLASS = "demoClass"; + + protected final ApplicationConfig applicationConfig; + + public MyDelegateConfig() { + this.applicationConfig = new ApplicationConfig(); + + applicationConfig.setConfigFileName(Option.CONFIG_FILE.defaultValue); + + // chargement de la configuration interne + + for (Option o : Option.values()) { + applicationConfig.setDefaultOption(o.key, o.defaultValue); + } + + applicationConfig.setAdjusting(true); + try { + addPropertyChangeListener(PROPERTY_FULLSCREEN, saveAction); + addPropertyChangeListener(PROPERTY_FONT_SIZE, saveAction); + addPropertyChangeListener(PROPERTY_LOCALE, saveAction); + addPropertyChangeListener(PROPERTY_DEMO_COLOR, saveAction); + addPropertyChangeListener(PROPERTY_DEMO_CLASS, saveAction); + } finally { + applicationConfig.setAdjusting(false); + } + } + + protected final PropertyChangeListener saveAction = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (isAdjusting()) { + if (log.isDebugEnabled()) { + log.debug("skip save while adjusting"); + } + } else { + if (log.isDebugEnabled()) { + log.debug("Saving configuration at " + new Date()); + } + saveForUser(); + } + } + }; + + public void saveForUser(String... excludeKeys) { + // never save anything :) + } + + public boolean isFullScreen() { + Boolean result = applicationConfig.getOptionAsBoolean(Option.FULL_SCREEN.key); + return result != null && result; + } + + public Locale getLocale() { + return applicationConfig.getOption(Locale.class, Option.LOCALE.key); + } + + public Float getFontSize() { + return applicationConfig.getOption(Float.class, Option.FONT_SIZE.key); + } + + public Color getDemoColor() { + return applicationConfig.getOptionAsColor(Option.DEMO_COLOR.key); + } + + public Class<?> getDemoClass() { + return applicationConfig.getOptionAsClass(Option.DEMO_CLASS.key); + } + + public void setFullscreen(boolean fullscreen) { + Object oldValue = null; + applicationConfig.setOption(Option.FULL_SCREEN.key, fullscreen + ""); + firePropertyChange(PROPERTY_FULLSCREEN, oldValue, fullscreen); + } + + public void setLocale(Locale newLocale) { + applicationConfig.setOption(Option.LOCALE.key, newLocale.toString()); + firePropertyChange(PROPERTY_LOCALE, null, newLocale); + } + + public void setFontSize(Float newFontSize) { + Float oldValue = getFontSize(); + if (log.isDebugEnabled()) { + log.debug("changing font-size to " + newFontSize); + } + applicationConfig.setOption(Option.FONT_SIZE.key, newFontSize.toString()); + firePropertyChange(PROPERTY_FONT_SIZE, oldValue, newFontSize); + } + + public void setDemoColor(Color color) { + Color oldValue = getDemoColor(); + if (log.isDebugEnabled()) { + log.debug("changing demo-color to " + color); + } + applicationConfig.setOption(Option.DEMO_COLOR.key, color.toString()); + firePropertyChange(PROPERTY_DEMO_COLOR, oldValue, color); + } + + public void setDemoClass(Class<?> newClass) { + Class<?> oldValue = getDemoClass(); + if (log.isDebugEnabled()) { + log.debug("changing demo-class to " + newClass); + } + applicationConfig.setOption(Option.DEMO_CLASS.key, newClass.getName()); + firePropertyChange(PROPERTY_DEMO_CLASS, oldValue, newClass); + } + + public boolean isAdjusting() { + return applicationConfig.isAdjusting(); + } + + public void setAdjusting(boolean adjusting) { + applicationConfig.setAdjusting(adjusting); + } + + @Override + public ApplicationConfig get() { + return applicationConfig; + } + + ////////////////////////////////////////////////// + // Toutes les options disponibles + ////////////////////////////////////////////////// + + public enum Option implements ConfigOptionDef { + + CONFIG_FILE(ApplicationConfig.CONFIG_FILE_NAME, t("jaxxdemo.config.configFileName.description"), "jaxxdemo", String.class, true, true), + FULL_SCREEN("ui.fullscreen", t("jaxxdemo.config.ui.fullscreen"), "false", Boolean.class, false, false), + LOCALE("ui." + PROPERTY_LOCALE, t("jaxxdemo.config.ui." + PROPERTY_LOCALE), Locale.FRANCE.toString(), Locale.class, false, false), + FONT_SIZE("ui." + PROPERTY_FONT_SIZE, t("jaxxdemo.config.ui." + PROPERTY_FONT_SIZE), "10f", Float.class, false, false), + DEMO_COLOR("ui." + PROPERTY_DEMO_COLOR, t("jaxxdemo.config.ui.demoColor"), "#ffffff", Color.class, false, false), + DEMO_CLASS("ui." + PROPERTY_DEMO_CLASS, t("jaxxdemo.config.ui.demoClass"), "java.io.File", Class.class, false, false); + + public final String key; + + public final String description; + + public String defaultValue; + + public final Class<?> type; + + public boolean _transient; + + public boolean _final; + + Option(String key, + String description, + String defaultValue, + Class<?> type, + boolean _transient, + boolean _final) { + this.key = key; + this.description = description; + this.defaultValue = defaultValue; + this.type = type; + this._final = _final; + this._transient = _transient; + } + + @Override + public boolean isFinal() { + return _final; + } + + @Override + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + @Override + public void setTransient(boolean _transient) { + this._transient = _transient; + } + + @Override + public void setFinal(boolean _final) { + this._final = _final; + } + + @Override + public boolean isTransient() { + return _transient; + } + + @Override + public String getDefaultValue() { + return defaultValue; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getKey() { + return key; + } + + @Override + public Class<?> getType() { + return type; + } + } +} + diff --git a/jaxx-config/src/test/java/org/nuiton/jaxx/config/model/MyDelegateConfigTest.java b/jaxx-config/src/test/java/org/nuiton/jaxx/config/model/MyDelegateConfigTest.java new file mode 100644 index 0000000..1b75e72 --- /dev/null +++ b/jaxx-config/src/test/java/org/nuiton/jaxx/config/model/MyDelegateConfigTest.java @@ -0,0 +1,337 @@ +package org.nuiton.jaxx.config.model; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.swing.editor.MyDefaultCellEditor; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.nuiton.config.ApplicationConfig; + +import javax.swing.ImageIcon; +import javax.swing.table.TableCellEditor; +import java.awt.Color; +import java.io.File; +import java.util.Collection; + +/** + * To test ConfigUI api on {@link MyDelegateConfig}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class MyDelegateConfigTest { + + + public static final String CATEGORY = "cat0"; + + protected ConfigUIModelBuilder builder; + + protected MyDelegateConfig config; + + @Before + public void setup() { + config = new MyDelegateConfig(); + builder = new ConfigUIModelBuilder(); + } + + @Test(expected = NullPointerException.class) + public void testCreateModelLimitCase0() throws Exception { + builder.createModel((ApplicationConfig) null); + } + + @Test(expected = IllegalStateException.class) + public void testFlushModelLimitCase0() throws Exception { + builder.flushModel(); + } + + @Test + public void testCreateModel() throws Exception { + ConfigUIModel configModel = builder + .createModel(config) + .flushModel(); + Assert.assertNotNull(configModel); + Assert.assertNotNull(configModel.getApplicationConfig()); + } + + @Test(expected = IllegalStateException.class) + public void testRegisterCallbackLimitCase() throws Exception { + builder.registerCallBack(null, null, null, null); + } + + @Test(expected = NullPointerException.class) + public void testRegisterCallbackLimitCase0() throws Exception { + builder.createModel(config) + .registerCallBack(null, null, null, null); + } + + @Test(expected = NullPointerException.class) + public void testRegisterCallbackLimitCase1() throws Exception { + builder.createModel(config) + .registerCallBack("yo", null, null, null); + } + + @Test(expected = NullPointerException.class) + public void testRegisterCallbackLimitCase2() throws Exception { + builder.createModel(config) + .registerCallBack("yo", "yo description", null, null); + } + + @Test(expected = NullPointerException.class) + public void testRegisterCallbackLimitCase4() throws Exception { + Runnable callback = new Runnable() { + + @Override + public void run() { + } + }; + builder.createModel(config) + .registerCallBack("yo", "yo description", null, callback); + } + + @Test + public void testRegisterCallback() throws Exception { + Runnable callback = new Runnable() { + + @Override + public void run() { + } + }; + ImageIcon icon = SwingUtil.createActionIcon("add"); + ConfigUIModel configModel = builder.createModel(config) + .registerCallBack("yo", "yo description", icon, callback) + .flushModel(); + Assert.assertNotNull(configModel); + Assert.assertNotNull(configModel.getApplicationConfig()); + CallBackEntry callBackEntry = + configModel.getCallBacksManager().getCallBack("yo"); + Assert.assertNotNull(callBackEntry); + + Assert.assertEquals(callback, callBackEntry.getAction()); + } + + @Test(expected = IllegalStateException.class) + public void testAddCategoryLimitCase0() throws Exception { + builder.addCategory(null, null); + } + + @Test(expected = NullPointerException.class) + public void testAddCategoryLimitCase1() throws Exception { + builder.createModel(config) + .addCategory(null, null); + } + + @Test(expected = NullPointerException.class) + public void testAddCategoryLimitCase2() throws Exception { + builder.createModel(config) + .addCategory("", null); + } + + @Test + public void testAddCategory() throws Exception { + CategoryModel categoryModel = builder + .createModel(config) + .addCategory("cat0", "cat0 label") + .flushCategory(); + Assert.assertNotNull(categoryModel); + Assert.assertEquals("cat0", categoryModel.category); + Assert.assertEquals("cat0 label", categoryModel.categoryLabel); + Assert.assertEquals(0, categoryModel.entries.size()); + + } + + @Test(expected = IllegalStateException.class) + public void testAddOptionLimitCase0() throws Exception { + builder.addOption(null); + } + + @Test(expected = IllegalStateException.class) + public void testAddOptionLimitCase1() throws Exception { + builder.createModel(config) + .addOption(null); + } + + @Test(expected = NullPointerException.class) + public void testAddOptionLimitCase2() throws Exception { + builder.createModel(config) + .addCategory("cat0", "cat0 label") + .addOption(null); + } + + @Test + public void testAddOption() throws Exception { + OptionModel optionModel = builder + .createModel(config) + .addCategory("cat0", "cat0 label") + .addOption(MyDelegateConfig.Option.LOCALE) + .flushOption(); + Assert.assertNotNull(optionModel); + Assert.assertEquals(MyDelegateConfig.Option.LOCALE, optionModel.def); + + CategoryModel categoryModel = builder.flushCategory(); + Assert.assertNotNull(categoryModel); + Assert.assertEquals("cat0", categoryModel.category); + Assert.assertEquals("cat0 label", categoryModel.categoryLabel); + Assert.assertEquals(1, categoryModel.entries.size()); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionPropertyNameLimitCase0() throws Exception { + builder.setOptionPropertyName(null); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionPropertyNameLimitCase1() throws Exception { + builder.createModel(config) + .setOptionPropertyName(null); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionPropertyNameLimitCase2() throws Exception { + builder.createModel(config) + .addCategory("cat0", "cat0 label") + .setOptionPropertyName(null); + } + + @Test(expected = NullPointerException.class) + public void testSetOptionPropertyNameLimitCase3() throws Exception { + builder.createModel(config) + .addCategory("cat0", "cat0 label") + .addOption(MyDelegateConfig.Option.LOCALE) + .setOptionPropertyName(null); + } + + @Test + public void testSetOptionPropertyName() throws Exception { + OptionModel optionModel = builder + .createModel(config) + .addCategory("cat0", "cat0 label") + .addOption(MyDelegateConfig.Option.LOCALE) + .setOptionPropertyName(MyDelegateConfig.PROPERTY_LOCALE) + .flushOption(); + Assert.assertNotNull(optionModel); + Assert.assertEquals(MyDelegateConfig.Option.LOCALE, optionModel.def); + Assert.assertEquals(MyDelegateConfig.PROPERTY_LOCALE, optionModel.propertyName); + Assert.assertNull(optionModel.editor); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionEditorLimitCase0() throws Exception { + builder.setOptionEditor(null); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionEditorLimitCase1() throws Exception { + builder.createModel(config) + .setOptionEditor(null); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionEditorLimitCase2() throws Exception { + builder.createModel(config) + .addCategory("cat0", "cat0 label") + .setOptionEditor(null); + } + + + @Test(expected = NullPointerException.class) + public void testSetOptionEditorLimitCase3() throws Exception { + builder.createModel(config) + .addCategory("cat0", "cat0 label") + .addOption(MyDelegateConfig.Option.LOCALE) + .setOptionEditor(null); + } + + @Test + public void testSetOptionEditor() throws Exception { + TableCellEditor cellEditor = MyDefaultCellEditor.newBooleanEditor(); + OptionModel optionModel = builder.createModel(config) + .addCategory("cat0", "cat0 label") + .addOption(MyDelegateConfig.Option.LOCALE) + .setOptionEditor(cellEditor) + .flushOption(); + Assert.assertNotNull(optionModel); + Assert.assertEquals(MyDelegateConfig.Option.LOCALE, optionModel.def); + Assert.assertNull(optionModel.propertyName); + Assert.assertEquals(cellEditor, optionModel.editor); + } + + @Test + public void testFlushModel() throws Exception { + ConfigUIModel configModel = builder + .createModel(config) + .flushModel(); + Assert.assertNotNull(configModel); + Assert.assertNull(builder.model); + } + + @Test + public void testSaveClassOption() throws Exception { + ConfigUIModel configModel = builder + .createModel(config) + .addCategory(CATEGORY, "cat0 label") + .addOption(MyDelegateConfig.Option.DEMO_CLASS) + .setOptionPropertyName(MyDelegateConfig.PROPERTY_DEMO_CLASS) + .flushModel(); + configModel.setCategory(CATEGORY); + + CategoryModel categoryModel = configModel.getCategoryModel(); + Assert.assertNotNull(categoryModel); + + OptionModel optionModel = categoryModel.getOptionModel(MyDelegateConfig.Option.DEMO_CLASS.getKey()); + Assert.assertNotNull(optionModel); + + categoryModel.setValue(optionModel, Collection.class); + + Assert.assertEquals(File.class, config.getDemoClass()); + + configModel.saveModified(); + + Assert.assertEquals(Collection.class, config.getDemoClass()); + } + + @Test + public void testSaveColorOption() throws Exception { + ConfigUIModel configModel = builder + .createModel(config) + .addCategory(CATEGORY, "cat0 label") + .addOption(MyDelegateConfig.Option.DEMO_COLOR) + .flushModel(); + configModel.setCategory(CATEGORY); + + CategoryModel categoryModel = configModel.getCategoryModel(); + Assert.assertNotNull(categoryModel); + + OptionModel optionModel = categoryModel.getOptionModel(MyDelegateConfig.Option.DEMO_COLOR.getKey()); + Assert.assertNotNull(optionModel); + + Color newColor = new Color(0, 0, 0); + categoryModel.setValue(optionModel, newColor); + + Assert.assertFalse(newColor.equals(config.getDemoColor())); + + configModel.saveModified(); + Assert.assertEquals(newColor, config.getDemoColor()); + } +} diff --git a/jaxx-config/src/test/java/org/nuiton/jaxx/config/model/MyInheritedConfig.java b/jaxx-config/src/test/java/org/nuiton/jaxx/config/model/MyInheritedConfig.java new file mode 100644 index 0000000..2af222a --- /dev/null +++ b/jaxx-config/src/test/java/org/nuiton/jaxx/config/model/MyInheritedConfig.java @@ -0,0 +1,278 @@ +package org.nuiton.jaxx.config.model; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.config.ApplicationConfig; +import org.nuiton.config.ConfigOptionDef; + +import java.awt.Color; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Date; +import java.util.Locale; + +import static org.nuiton.i18n.I18n.t; + +/** + * A config to test config ui api when using a delegation + * on {@link ApplicationConfig}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class MyInheritedConfig extends ApplicationConfig { + + /** Logger */ + private static final Log log = LogFactory.getLog(MyInheritedConfig.class); + + public static final String PROPERTY_FULLSCREEN = "fullscreen"; + + public static final String PROPERTY_LOCALE = "locale"; + + public static final String PROPERTY_FONT_SIZE = "fontSize"; + + public static final String PROPERTY_ADJUSTING = "adjusting"; + + public static final String PROPERTY_DEMO_COLOR = "demoColor"; + + public static final String PROPERTY_DEMO_CLASS = "demoClass"; + +// /** +// * un drapeau pour bloquer la sauvegarde lors de la modification en masse des options +// * via les setter. +// */ +// protected boolean adjusting; + + protected final PropertyChangeListener saveAction = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (isAdjusting()) { + if (log.isDebugEnabled()) { + log.debug("skip save while adjusting"); + } + return; + } + if (log.isDebugEnabled()) { + log.debug("Saving configuration at " + new Date()); + } + saveForUser(); + } + }; + + @Override + public void saveForUser(String... excludeKeys) { + // never save anything :) + } + + public MyInheritedConfig() { + + setConfigFileName(Option.CONFIG_FILE.defaultValue); + + // chargement de la configuration interne + + for (Option o : Option.values()) { + setDefaultOption(o.key, o.defaultValue); + } + + setAdjusting(true); + try { + addPropertyChangeListener(PROPERTY_FULLSCREEN, saveAction); + addPropertyChangeListener(PROPERTY_FONT_SIZE, saveAction); + addPropertyChangeListener(PROPERTY_LOCALE, saveAction); + addPropertyChangeListener(PROPERTY_DEMO_COLOR, saveAction); + addPropertyChangeListener(PROPERTY_DEMO_CLASS, saveAction); + } finally { + setAdjusting(false); + } + } + + @Override + public void setOption(String key, String value) { + if (key.equals(PROPERTY_ADJUSTING)) { + setAdjusting(Boolean.valueOf(value)); + return; + } + super.setOption(key, value); + } + + + public boolean isFullScreen() { + Boolean result = getOptionAsBoolean(Option.FULL_SCREEN.key); + return result != null && result; + } + + public Locale getLocale() { + return getOption(Locale.class, Option.LOCALE.key); + } + + public Float getFontSize() { + return getOption(Float.class, Option.FONT_SIZE.key); + } + + public Color getDemoColor() { + return getOptionAsColor(Option.DEMO_COLOR.key); + } + + public Class<?> getDemoClass() { + return getOptionAsClass(Option.DEMO_CLASS.key); + } + + public void setFullscreen(boolean fullscreen) { + Object oldValue = null; + setOption(Option.FULL_SCREEN.key, fullscreen + ""); + firePropertyChange(PROPERTY_FULLSCREEN, oldValue, fullscreen); + } + + public void setLocale(Locale newLocale) { + setOption(Option.LOCALE.key, newLocale.toString()); + firePropertyChange(PROPERTY_LOCALE, null, newLocale); + } + + public void setFontSize(Float newFontSize) { + Float oldValue = getFontSize(); + if (log.isDebugEnabled()) { + log.debug("changing font-size to " + newFontSize); + } + setOption(Option.FONT_SIZE.key, newFontSize.toString()); + firePropertyChange(PROPERTY_FONT_SIZE, oldValue, newFontSize); + } + + public void setDemoColor(Color color) { + Color oldValue = getDemoColor(); + if (log.isDebugEnabled()) { + log.debug("changing demo-color to " + color); + } + setOption(Option.DEMO_COLOR.key, color.toString()); + firePropertyChange(PROPERTY_DEMO_COLOR, oldValue, color); + } + + public void setDemoClass(Class<?> newClass) { + Class<?> oldValue = getDemoClass(); + if (log.isDebugEnabled()) { + log.debug("changing demo-class to " + newClass); + } + setOption(Option.DEMO_CLASS.key, newClass.getName()); + firePropertyChange(PROPERTY_DEMO_CLASS, oldValue, newClass); + } + +// public boolean isAdjusting() { +// return adjusting; +// } +// +// public void setAdjusting(boolean adjusting) { +// if (log.isDebugEnabled()) { +// log.debug("changing adjusting to " + adjusting); +// } +// boolean oldValue = this.adjusting; +// this.adjusting = adjusting; +// firePropertyChange(PROPERTY_ADJUSTING, oldValue, adjusting); +// } + + ////////////////////////////////////////////////// + // Toutes les options disponibles + ////////////////////////////////////////////////// + + public enum Option implements ConfigOptionDef { + + CONFIG_FILE(CONFIG_FILE_NAME, t("jaxxdemo.config.configFileName.description"), "jaxxdemo", String.class, true, true), + FULL_SCREEN("ui.fullscreen", t("jaxxdemo.config.ui.fullscreen"), "false", Boolean.class, false, false), + LOCALE("ui." + PROPERTY_LOCALE, t("jaxxdemo.config.ui." + PROPERTY_LOCALE), Locale.FRANCE.toString(), Locale.class, false, false), + FONT_SIZE("ui." + PROPERTY_FONT_SIZE, t("jaxxdemo.config.ui." + PROPERTY_FONT_SIZE), "10f", Float.class, false, false), + DEMO_COLOR("ui." + PROPERTY_DEMO_COLOR, t("jaxxdemo.config.ui.demoColor"), "#ffffff", Color.class, false, false), + DEMO_CLASS("ui." + PROPERTY_DEMO_CLASS, t("jaxxdemo.config.ui.demoClass"), "java.io.File", Class.class, false, false); + + public final String key; + + public final String description; + + public String defaultValue; + + public final Class<?> type; + + public boolean _transient; + + public boolean _final; + + Option(String key, + String description, + String defaultValue, + Class<?> type, + boolean _transient, + boolean _final) { + this.key = key; + this.description = description; + this.defaultValue = defaultValue; + this.type = type; + this._final = _final; + this._transient = _transient; + } + + @Override + public boolean isFinal() { + return _final; + } + + @Override + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + @Override + public void setTransient(boolean _transient) { + this._transient = _transient; + } + + @Override + public void setFinal(boolean _final) { + this._final = _final; + } + + @Override + public boolean isTransient() { + return _transient; + } + + @Override + public String getDefaultValue() { + return defaultValue; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getKey() { + return key; + } + + @Override + public Class<?> getType() { + return type; + } + } +} diff --git a/jaxx-config/src/test/java/org/nuiton/jaxx/config/model/MyInheritedConfigTest.java b/jaxx-config/src/test/java/org/nuiton/jaxx/config/model/MyInheritedConfigTest.java new file mode 100644 index 0000000..f67efe3 --- /dev/null +++ b/jaxx-config/src/test/java/org/nuiton/jaxx/config/model/MyInheritedConfigTest.java @@ -0,0 +1,349 @@ +package org.nuiton.jaxx.config.model; + +/* + * #%L + * JAXX :: Config + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.swing.editor.MyDefaultCellEditor; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.nuiton.config.ApplicationConfig; + +import javax.swing.ImageIcon; +import javax.swing.table.TableCellEditor; +import java.awt.Color; +import java.io.File; +import java.util.Collection; + +/** + * To test ConfigUI api on {@link MyInheritedConfig}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.11 + */ +public class MyInheritedConfigTest { + + public static final String CATEGORY = "cat0"; + + protected ConfigUIModelBuilder builder; + + protected MyInheritedConfig config; + + @Before + public void setup() { + config = new MyInheritedConfig(); + builder = new ConfigUIModelBuilder(); + } + + @Test(expected = NullPointerException.class) + public void testCreateModelLimitCase0() throws Exception { + builder.createModel((ApplicationConfig) null); + } + + @Test(expected = IllegalStateException.class) + public void testFlushModelLimitCase0() throws Exception { + builder.flushModel(); + } + + @Test + public void testCreateModel() throws Exception { + ConfigUIModel configModel = builder + .createModel(config) + .flushModel(); + Assert.assertNotNull(configModel); + Assert.assertNotNull(configModel.getApplicationConfig()); + } + + @Test(expected = IllegalStateException.class) + public void testRegisterCallbackLimitCase() throws Exception { + builder.registerCallBack(null, null, null, null); + } + + @Test(expected = NullPointerException.class) + public void testRegisterCallbackLimitCase0() throws Exception { + builder.createModel(config) + .registerCallBack(null, null, null, null); + } + + @Test(expected = NullPointerException.class) + public void testRegisterCallbackLimitCase1() throws Exception { + builder.createModel(config) + .registerCallBack("yo", null, null, null); + } + + @Test(expected = NullPointerException.class) + public void testRegisterCallbackLimitCase2() throws Exception { + builder.createModel(config) + .registerCallBack("yo", "yo description", null, null); + } + + @Test(expected = NullPointerException.class) + public void testRegisterCallbackLimitCase4() throws Exception { + Runnable callback = new Runnable() { + + @Override + public void run() { + } + }; + builder.createModel(config) + .registerCallBack("yo", "yo description", null, callback); + } + + @Test + public void testRegisterCallback() throws Exception { + + Runnable callback = new Runnable() { + + @Override + public void run() { + } + }; + ImageIcon icon = SwingUtil.createActionIcon("add"); + ConfigUIModel configModel = builder + .createModel(config) + .registerCallBack("yo", "yo description", icon, callback) + .flushModel(); + Assert.assertNotNull(configModel); + Assert.assertNotNull(configModel.getApplicationConfig()); + CallBackEntry callBackEntry = + configModel.getCallBacksManager().getCallBack("yo"); + Assert.assertNotNull(callBackEntry); + + Assert.assertEquals(callback, callBackEntry.getAction()); + } + + @Test(expected = IllegalStateException.class) + public void testAddCategoryLimitCase0() throws Exception { + builder.addCategory(null, null); + } + + @Test(expected = NullPointerException.class) + public void testAddCategoryLimitCase1() throws Exception { + builder.createModel(config) + .addCategory(null, null); + } + + @Test(expected = NullPointerException.class) + public void testAddCategoryLimitCase2() throws Exception { + builder.createModel(config) + .addCategory("", null); + } + + @Test + public void testAddCategory() throws Exception { + CategoryModel categoryModel = builder + .createModel(config) + .addCategory("cat0", "cat0 label") + .flushCategory(); + Assert.assertNotNull(categoryModel); + Assert.assertEquals("cat0", categoryModel.category); + Assert.assertEquals("cat0 label", categoryModel.categoryLabel); + Assert.assertEquals(0, categoryModel.entries.size()); + + } + + @Test(expected = IllegalStateException.class) + public void testAddOptionLimitCase0() throws Exception { + builder.addOption(null); + } + + @Test(expected = IllegalStateException.class) + public void testAddOptionLimitCase1() throws Exception { + builder.createModel(config) + .addOption(null); + } + + @Test(expected = NullPointerException.class) + public void testAddOptionLimitCase2() throws Exception { + builder.createModel(config) + .addCategory("cat0", "cat0 label") + .addOption(null); + } + + @Test + public void testAddOption() throws Exception { + OptionModel optionModel = builder + .createModel(config) + .addCategory("cat0", "cat0 label") + .addOption(MyInheritedConfig.Option.LOCALE) + .flushOption(); + Assert.assertNotNull(optionModel); + Assert.assertEquals(MyInheritedConfig.Option.LOCALE, optionModel.def); + + CategoryModel categoryModel = builder.flushCategory(); + Assert.assertNotNull(categoryModel); + Assert.assertEquals("cat0", categoryModel.category); + Assert.assertEquals("cat0 label", categoryModel.categoryLabel); + Assert.assertEquals(1, categoryModel.entries.size()); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionPropertyNameLimitCase0() throws Exception { + builder.setOptionPropertyName(null); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionPropertyNameLimitCase1() throws Exception { + builder.createModel(config); + builder.setOptionPropertyName(null); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionPropertyNameLimitCase2() throws Exception { + builder.createModel(config) + .addCategory("cat0", "cat0 label") + .setOptionPropertyName(null); + } + + @Test(expected = NullPointerException.class) + public void testSetOptionPropertyNameLimitCase3() throws Exception { + builder.createModel(config) + .addCategory("cat0", "cat0 label") + .addOption(MyInheritedConfig.Option.LOCALE) + .setOptionPropertyName(null); + } + + @Test + public void testSetOptionPropertyName() throws Exception { + OptionModel optionModel = builder + .createModel(config) + .addCategory("cat0", "cat0 label") + .addOption(MyInheritedConfig.Option.LOCALE) + .setOptionPropertyName(MyInheritedConfig.PROPERTY_LOCALE) + .flushOption(); + Assert.assertNotNull(optionModel); + Assert.assertEquals(MyInheritedConfig.Option.LOCALE, optionModel.def); + Assert.assertEquals(MyInheritedConfig.PROPERTY_LOCALE, optionModel.propertyName); + Assert.assertNull(optionModel.editor); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionEditorLimitCase0() throws Exception { + builder.setOptionEditor(null); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionEditorLimitCase1() throws Exception { + builder.createModel(config); + builder.setOptionEditor(null); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionEditorLimitCase2() throws Exception { + builder.createModel(config) + .addCategory("cat0", "cat0 label") + .setOptionEditor(null); + } + + + @Test(expected = NullPointerException.class) + public void testSetOptionEditorLimitCase3() throws Exception { + builder.createModel(config) + .addCategory("cat0", "cat0 label") + .addOption(MyInheritedConfig.Option.LOCALE) + .setOptionEditor(null); + } + + @Test + public void testSetOptionEditor() throws Exception { + TableCellEditor cellEditor = MyDefaultCellEditor.newBooleanEditor(); + OptionModel optionModel = builder.createModel(config) + .addCategory("cat0", "cat0 label") + .addOption(MyInheritedConfig.Option.LOCALE) + .setOptionEditor(cellEditor) + .flushOption(); + Assert.assertNotNull(optionModel); + Assert.assertEquals(MyInheritedConfig.Option.LOCALE, optionModel.def); + Assert.assertNull(optionModel.propertyName); + Assert.assertEquals(cellEditor, optionModel.editor); + } + + @Test + public void testFlushModel() throws Exception { + ConfigUIModel configModel = builder + .createModel(config) + .flushModel(); + Assert.assertNotNull(configModel); + Assert.assertNull(builder.model); + } + + @Test + public void testSetModel() throws Exception { + + } + + @Test + public void testSetCategory() throws Exception { + } + + @Test + public void testSetOption() throws Exception { + } + + @Test + public void testSaveClassOption() throws Exception { + ConfigUIModel configModel = builder + .createModel(config) + .addCategory(CATEGORY, "cat0 label") + .addOption(MyDelegateConfig.Option.DEMO_CLASS) + .setOptionPropertyName(MyDelegateConfig.PROPERTY_DEMO_CLASS) + .flushModel(); + configModel.setCategory(CATEGORY); + CategoryModel categoryModel = configModel.getCategoryModel(); + Assert.assertNotNull(categoryModel); + + OptionModel optionModel = categoryModel.getOptionModel(MyDelegateConfig.Option.DEMO_CLASS.getKey()); + Assert.assertNotNull(optionModel); + + categoryModel.setValue(optionModel, Collection.class); + + Assert.assertEquals(File.class, config.getDemoClass()); + + configModel.saveModified(); + Assert.assertEquals(Collection.class, config.getDemoClass()); + } + + @Test + public void testSaveColorOption() throws Exception { + ConfigUIModel configModel = builder + .createModel(config) + .addCategory(CATEGORY, "cat0 label") + .addOption(MyDelegateConfig.Option.DEMO_COLOR) + .flushModel(); + configModel.setCategory(CATEGORY); + + CategoryModel categoryModel = configModel.getCategoryModel(); + Assert.assertNotNull(categoryModel); + + OptionModel optionModel = categoryModel.getOptionModel(MyDelegateConfig.Option.DEMO_COLOR.getKey()); + Assert.assertNotNull(optionModel); + + Color newColor = new Color(0, 0, 0); + categoryModel.setValue(optionModel, newColor); + + Assert.assertFalse(newColor.equals(config.getDemoColor())); + + configModel.saveModified(); + Assert.assertEquals(newColor, config.getDemoColor()); + } +} diff --git a/jaxx-demo/pom.xml b/jaxx-demo/pom.xml index 9d1b70f..654183a 100644 --- a/jaxx-demo/pom.xml +++ b/jaxx-demo/pom.xml @@ -41,7 +41,7 @@ <properties> - <maven.jar.main.class>jaxx.demo.RunDemo</maven.jar.main.class> + <maven.jar.main.class>org.nuiton.jaxx.demo.RunDemo</maven.jar.main.class> <jaxx.addProjectClassPath>true</jaxx.addProjectClassPath> <jaxx.addSourcesToClassPath>true</jaxx.addSourcesToClassPath> @@ -56,7 +56,7 @@ <jaxx.mergeIdsToInput>true</jaxx.mergeIdsToInput> <jaxx.inputHelpDirectory>src/main/resources</jaxx.inputHelpDirectory> <jaxx.inputHelpFilenamePrefix>jaxxdemo-help</jaxx.inputHelpFilenamePrefix> - <jaxx.helpBrokerFQN>jaxx.demo.DemoHelpBroker</jaxx.helpBrokerFQN> + <jaxx.helpBrokerFQN>org.nuiton.jaxx.demo.DemoHelpBroker</jaxx.helpBrokerFQN> <!-- generate license bundled files --> <license.generateBundle>true</license.generateBundle> diff --git a/jaxx-demo/src/main/java/jaxx/demo/DemoApplicationContext.java b/jaxx-demo/src/main/java/jaxx/demo/DemoApplicationContext.java deleted file mode 100644 index 4826d6c..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/DemoApplicationContext.java +++ /dev/null @@ -1,175 +0,0 @@ -package jaxx.demo; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.context.DefaultApplicationContext; -import jaxx.runtime.context.JAXXContextEntryDef; -import jaxx.runtime.swing.help.JAXXHelpBroker; -import jaxx.runtime.swing.help.JAXXHelpUIHandler; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.InputStream; -import java.net.URI; -import java.util.Properties; - -import static org.nuiton.i18n.I18n.t; - -/** - * Created on 1/9/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since XXX - */ -public class DemoApplicationContext extends DefaultApplicationContext implements JAXXHelpUIHandler { - - static final JAXXContextEntryDef<DemoUI> MAIN_UI = - JAXXUtil.newContextEntryDef("MainUI", DemoUI.class); - - /** The singleton instance of the main context */ - private static volatile DemoApplicationContext context; - - /** Logger. */ - private static final Log log = LogFactory.getLog(DemoApplicationContext.class); - - /** - * @return <code>true</code> si le context a été initialisé via la méthode - * {@link #init(DemoConfig)}, <code>false</code> autrement. - */ - protected static boolean isInit() { - return context != null; - } - - /** - * Permet l'initialisation du contexte applicatif et positionne - * l'context partagée. - * - * Note : Cette méthode ne peut être appelée qu'une seule fois. - * - * @param config application config - * @return le context partagée - * @throws IllegalStateException si un contexte applicatif a déja été positionné. - */ - protected static DemoApplicationContext init(DemoConfig config) throws IllegalStateException { - if (isInit()) { - throw new IllegalStateException("there is an already application context registred."); - } - context = new DemoApplicationContext(config); - return context; - } - - /** - * Récupération du contexte applicatif. - * - * @return l'context partagé du contexte. - * @throws IllegalStateException si le contexte n'a pas été initialisé via - * la méthode {@link #init(DemoConfig)} - */ - public static DemoApplicationContext get() throws IllegalStateException { - if (!isInit()) { - throw new IllegalStateException("no application context registred."); - } - return context; - } - - public DemoApplicationContext(DemoConfig config) { - - // share config - setContextValue(config); - - //--------------------------------------------------------------------// - // init help - //--------------------------------------------------------------------// - - // load help mapping - String mappingProperties = "/jaxxdemo-help-fr.properties"; - try { - - InputStream resourceAsStream = - getClass().getResourceAsStream(mappingProperties); - helpMapping = new Properties(); - helpMapping.load(resourceAsStream); - - } catch (Exception eee) { - log.error("Failed to load help mapping file at '" + - mappingProperties + "'", eee); - } - } - - public DemoConfig getConfig() { - return getContextValue(DemoConfig.class); - } - - private Properties helpMapping; - - @Override - public void showHelp(JAXXContext context, JAXXHelpBroker broker, String helpId) { - - if (helpId == null) { - helpId = broker.getDefaultID(); - } - - if (log.isInfoEnabled()) { - log.info("help-id: " + helpId); - } - - String value = (String) helpMapping.get(helpId); - - if (value == null) { - throw new RuntimeException(t("jaxxdemo.context.helpPage.notFound", helpId)); - } - - String helpDirectory = getConfig().getHelpResourceWithLocale(value); - boolean withFragment = helpDirectory.contains("#"); - - String fragment = null; - if (withFragment) { - fragment = StringUtils.substringAfter(helpDirectory, "#"); - helpDirectory = StringUtils.substringBefore(helpDirectory, "#"); - } - - URI resolvedUri = URI.create(helpDirectory); -// try { - - if (withFragment) { - resolvedUri = URI.create(resolvedUri.toString() + "#" + fragment); - } - if (log.isInfoEnabled()) { - log.info("help-uri: " + resolvedUri); - } - getMainUI().getP().setStatus(t("jaxxdemo.openHelp", helpId)); -// SwingUtil.openLink(resolvedUri); -// } catch (URISyntaxException e) { -// throw new RuntimeException(t("jaxxdemo.context.helpPage.notFound", resolvedUri)); -// } - } - - public DemoUI getMainUI() { - - return MAIN_UI.getContextValue(this); - } - -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/DemoConfig.java b/jaxx-demo/src/main/java/jaxx/demo/DemoConfig.java deleted file mode 100644 index be27f34..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/DemoConfig.java +++ /dev/null @@ -1,512 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo; - -import com.google.common.base.Supplier; -import jaxx.demo.component.swing.JButtonDemo; -import jaxx.runtime.JAXXUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.beans.AbstractBean; -import org.nuiton.config.ApplicationConfig; -import org.nuiton.config.ArgumentsParserException; -import org.nuiton.config.ConfigOptionDef; -import org.nuiton.version.Version; -import org.nuiton.version.Versions; - -import javax.swing.KeyStroke; -import java.awt.Color; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Date; -import java.util.Locale; -import java.util.Properties; - -import static org.nuiton.i18n.I18n.t; - -/** - * La configuration de l'application. - * - * Il s'agit de l'objet partagé par toutes les démos. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.7.2 - */ -public class DemoConfig extends AbstractBean implements Supplier<ApplicationConfig> { - - /** Logger */ - private static final Log log = LogFactory.getLog(DemoConfig.class); - - /** - * le fichier de configuration de l'application avec les informations sur - * le projet (version, license,...) et la configuration des ui (icons, ...) - */ - public static final String APPLICATION_PROPERTIES = "/jaxx-demo.properties"; - - public static final String PROPERTY_FULLSCREEN = "fullscreen"; - - public static final String PROPERTY_LOCALE = "locale"; - - public static final String PROPERTY_FONT_SIZE = "fontSize"; - - public static final String PROPERTY_DEMO_COLOR = "demoColor"; - - public static final String PROPERTY_DEMO_CLASS = "demoClass"; - - public static final String PROPERTY_LOG_LEVEL = "logLevel"; - - public static final String PROPERTY_LOG_PATTERN_LAYOUT = "logPatternLayout"; - - public static final String PROPERTY_KEY_OPEN_CONFIG = "keyOpenConfig"; - - private final ApplicationConfig applicationConfig; - - @Override - public ApplicationConfig get() { - return applicationConfig; - } - - public DemoConfig(String... args) { - - applicationConfig = new ApplicationConfig(); - applicationConfig.setConfigFileName(Option.CONFIG_FILE.defaultValue); - - // chargement de la configuration interne - - InputStream stream = - getClass().getResourceAsStream(APPLICATION_PROPERTIES); - - Properties p = new Properties(); - try { - p.load(stream); - for (Object k : p.keySet()) { - String key = k + ""; - Object value = p.get(k); - if (log.isDebugEnabled()) { - log.debug("install properties " + k + " : " + value); - } - applicationConfig.setDefaultOption(key, "" + value); - } - } catch (IOException ex) { - throw new RuntimeException(ex); - } - - applicationConfig.loadDefaultOptions(Option.values()); - - String sVersion = applicationConfig.getOption("application.version"); - Version version = Versions.valueOf(sVersion); - if (version.isSnapshot()) { - // on supprime le stamp de snapshot s'il existe - version = Versions.removeSnapshot(version); - } - applicationConfig.setDefaultOption("version", version.getVersion()); - - installSaveUserAction(PROPERTY_FULLSCREEN, - PROPERTY_FONT_SIZE, - PROPERTY_LOCALE, - PROPERTY_DEMO_CLASS, - PROPERTY_DEMO_COLOR); - - try { - applicationConfig.parse(args); - } catch (ArgumentsParserException e) { - throw new IllegalStateException("Could not parse configuration", e); - } - } - - /** - * TODO Remove this when the method in ApplicationConfig will be public - * - * Action to save user configuration. - * - * Add it as a listener of the configuration for a given property. - * - * <b>Note:</b> Will not save if {@link ApplicationConfig#isAdjusting()} is {@code true}. - * - * @since 2.5.4 - */ - private final PropertyChangeListener saveUserAction = - new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (applicationConfig.isAdjusting()) { - if (log.isDebugEnabled()) { - log.debug("Skip save while adjusting"); - } - } else { - if (log.isDebugEnabled()) { - log.debug("Saving configuration fired by property [" + - evt.getPropertyName() + "] at " + - new Date()); - } - saveForUser(); - } - } - }; - - /** - * TODO Remove this when the method in ApplicationConfig will be public - * - * Install the {@link #saveUserAction} on givne {@code properties}. - * - * @param properties properties on which insalls the saveUserAction - */ - protected void installSaveUserAction(String... properties) { - - // pass in adjusting state - applicationConfig.setAdjusting(true); - - try { - // ajout de tous les listeners pour sauver la configuration - // lors de la modification des options de la configuration - for (String propertyKey : properties) { - // add a listener - if (log.isDebugEnabled()) { - log.debug("register saveUserAction on property [" + - propertyKey + ']'); - } - addPropertyChangeListener(propertyKey, saveUserAction); - } - } finally { - - // ok back to normal adjusting state - applicationConfig.setAdjusting(false); - } - } - - public String getCopyrightText() { - return "Version " + getVersion() + " Codelutin @ 2008-2009"; - } - - /** @return la version de l'application. */ - public Version getVersion() { - Version option = applicationConfig.getOption(Version.class, "version"); - return option; - } - - public boolean isFullScreen() { - boolean result = applicationConfig.getOptionAsBoolean(Option.FULL_SCREEN.key); - return result; - } - - public Locale getLocale() { - Locale result = applicationConfig.getOption(Locale.class, Option.LOCALE.key); - return result; - } - - public String getDemoPath() { - String result = applicationConfig.getOption(Option.DEMO_PATH.key); - return result; - } - - public Float getFontSize() { - Float result = applicationConfig.getOption(Float.class, Option.FONT_SIZE.key); - return result; - } - - public Color getDemoColor() { - Color result = applicationConfig.getOptionAsColor(Option.DEMO_COLOR.key); - return result; - } - - public Class<?> getDemoClass() { - Class<?> result = applicationConfig.getOptionAsClass(Option.DEMO_CLASS.key); - return result; - } - - public String getLogLevel() { - String level = applicationConfig.getOption(Option.LOG_LEVEL.key); - return level; - } - - public String getLogPatternLayout() { - String result = applicationConfig.getOption(Option.LOG_PATTERN_LAYOUT.key); - return result; - } - - public KeyStroke getKeyOpenConfig() { - return applicationConfig.getOptionAsKeyStroke(Option.KEY_OPEN_CONFIG.key); - } - - public void setFullscreen(boolean fullscreen) { - applicationConfig.setOption(Option.FULL_SCREEN.key, fullscreen + ""); - firePropertyChange(PROPERTY_FULLSCREEN, null, fullscreen); - } - - public void setLocale(Locale newLocale) { - applicationConfig.setOption(Option.LOCALE.key, newLocale.toString()); - firePropertyChange(PROPERTY_LOCALE, null, newLocale); - } - - public void setFontSize(Float newFontSize) { - Float oldValue = getFontSize(); - if (log.isDebugEnabled()) { - log.debug("changing font-size to " + newFontSize); - } - applicationConfig.setOption(Option.FONT_SIZE.key, newFontSize.toString()); - firePropertyChange(PROPERTY_FONT_SIZE, oldValue, newFontSize); - } - - public void setDemoColor(Color color) { - Color oldValue = getDemoColor(); - if (log.isDebugEnabled()) { - log.debug("changing demo-color to " + color); - } - applicationConfig.setOption(Option.DEMO_COLOR.key, color.toString()); - firePropertyChange(PROPERTY_DEMO_COLOR, oldValue, color); - } - - public void setDemoClass(Class<?> newClass) { - Class<?> oldValue = getDemoClass(); - if (log.isDebugEnabled()) { - log.debug("changing demo-class to " + newClass); - } - applicationConfig.setOption(Option.DEMO_CLASS.key, newClass.getName()); - firePropertyChange(PROPERTY_DEMO_CLASS, oldValue, newClass); - } - - public void setLogLevel(String logLevel) { - String oldValue = getLogLevel(); - applicationConfig.setOption(Option.LOG_LEVEL.key, logLevel); - firePropertyChange(PROPERTY_LOG_LEVEL, oldValue, logLevel); - } - - public void setLogPatternLayout(String logPatternLayout) { - String oldValue = getLogPatternLayout(); - applicationConfig.setOption(Option.LOG_PATTERN_LAYOUT.key, logPatternLayout); - firePropertyChange(PROPERTY_LOG_PATTERN_LAYOUT, oldValue, logPatternLayout); - } - - public void setKeyOpenConfig(KeyStroke keyStroke) { - KeyStroke oldValue = getKeyOpenConfig(); - applicationConfig.setOption(Option.KEY_OPEN_CONFIG.key, keyStroke.toString()); - firePropertyChange(PROPERTY_KEY_OPEN_CONFIG, oldValue, keyStroke); - } - - - public void saveForUser() { - // shoudl we never save any conf ? - applicationConfig.saveForUser(); - } - - public static final String[] DEFAULT_JAXX_PCS = { - PROPERTY_FULLSCREEN, - PROPERTY_LOCALE, - PROPERTY_FONT_SIZE, - ApplicationConfig.ADJUSTING_PROPERTY - }; - - public void removeJaxxPropertyChangeListener() { - PropertyChangeListener[] toRemove; - toRemove = JAXXUtil.findJaxxPropertyChangeListener( - DEFAULT_JAXX_PCS, - applicationConfig.getPropertyChangeListeners()); - if (toRemove == null || toRemove.length == 0) { - return; - } - if (log.isDebugEnabled()) { - log.debug("before remove : " + applicationConfig.getPropertyChangeListeners().length); - log.debug("toRemove : " + toRemove.length); - } - for (PropertyChangeListener listener : toRemove) { - removePropertyChangeListener(listener); - } - if (log.isDebugEnabled()) { - log.debug("after remove : " + getPropertyChangeListeners().length); - } - } - - public URL getApplicationSiteUrl() { - return applicationConfig.getOptionAsURL("application.site.url"); - } - - public String getIconPath() { - return applicationConfig.getOption("application.icon.path"); - } - - public String getHelpLocation() { - return applicationConfig.getOption("application.help.path"); - } - - public String getHelpResourceWithLocale(String value) { - String result = getHelpLocation() + "/" + - getLocale().getLanguage() + "/" + - value; - return result; - } - - ////////////////////////////////////////////////// - // Toutes les options disponibles - ////////////////////////////////////////////////// - - public enum Option implements ConfigOptionDef { - - CONFIG_FILE( - ApplicationConfig.CONFIG_FILE_NAME, - t("jaxxdemo.config.configFileName.description"), - "jaxxdemo", - String.class, - true, - true), - FULL_SCREEN( - "ui.fullscreen", - t("jaxxdemo.config.ui.fullscreen"), - "false", - Boolean.class, - false, - false), - LOCALE( - "ui." + PROPERTY_LOCALE, - t("jaxxdemo.config.ui.locale"), - Locale.FRANCE.toString(), - Locale.class, - false, - false), - FONT_SIZE( - "ui." + PROPERTY_FONT_SIZE, - t("jaxxdemo.config.ui.fontSize"), - "10f", - Float.class, - false, - false), - DEMO_COLOR( - "ui." + PROPERTY_DEMO_COLOR, - t("jaxxdemo.config.ui.demoColor"), - "#ffffff", - Color.class, - false, - false), - DEMO_CLASS( - "ui." + PROPERTY_DEMO_CLASS, - t("jaxxdemo.config.ui.demoClass"), - "java.io.File", - Class.class, - false, - false), - - LOG_LEVEL( - "ui." + PROPERTY_LOG_LEVEL, - t("jaxxdemo.config.ui.logLevel"), - "INFO", - String.class, - false, - false), - LOG_PATTERN_LAYOUT( - "ui." + PROPERTY_LOG_PATTERN_LAYOUT, - t("jaxxdemo.config.ui.logPatternLayout"), - "%5p [%t] (%F:%L) %M - %m%n", - String.class, - false, - false), - KEY_OPEN_CONFIG( - "ui." + PROPERTY_KEY_OPEN_CONFIG, - t("jaxxdemo.config.ui.keyOpenConfig"), - "ctrl alt pressed S", - KeyStroke.class, - false, - false), - DEMO_PATH( - "ui.demo.path", - t("jaxxdemo.config.ui.demo.path"), - "jaxxdemo.tree/jaxxdemo.component.swing/jaxxdemo.component.swing.buttons/" + JButtonDemo.class.getSimpleName(), - String.class, - false, - true); - - public final String key; - - public final String description; - - public String defaultValue; - - public final Class<?> type; - - public boolean _transient; - - public boolean _final; - - Option(String key, - String description, - String defaultValue, - Class<?> type, - boolean _transient, - boolean _final) { - this.key = key; - this.description = description; - this.defaultValue = defaultValue; - this.type = type; - this._final = _final; - this._transient = _transient; - } - - @Override - public boolean isFinal() { - return _final; - } - - @Override - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - } - - @Override - public void setTransient(boolean _transient) { - this._transient = _transient; - } - - @Override - public void setFinal(boolean _final) { - this._final = _final; - } - - @Override - public boolean isTransient() { - return _transient; - } - - @Override - public String getDefaultValue() { - return defaultValue; - } - - @Override - public String getDescription() { - return description; - } - - @Override - public String getKey() { - return key; - } - - @Override - public Class<?> getType() { - return type; - } - - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/DemoHelpBroker.java b/jaxx-demo/src/main/java/jaxx/demo/DemoHelpBroker.java deleted file mode 100644 index 4b595be..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/DemoHelpBroker.java +++ /dev/null @@ -1,148 +0,0 @@ -package jaxx.demo; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Preconditions; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.awt.visitor.BuildTreeVisitor; -import jaxx.runtime.awt.visitor.ComponentTreeNode; -import jaxx.runtime.awt.visitor.DebugComponentTreeNodeVisitor; -import jaxx.runtime.awt.visitor.GetCompopentAtPointVisitor; -import jaxx.runtime.swing.help.JAXXHelpBroker; -import jaxx.runtime.swing.help.JAXXHelpUI; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.AbstractButton; -import java.awt.Component; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; - -/** - * Help broker. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.1 - */ -public class DemoHelpBroker extends JAXXHelpBroker { - - /** Logger */ - private static final Log log = LogFactory.getLog(DemoHelpBroker.class); - - public DemoHelpBroker(String defaultID) { - super("tutti", "help", - defaultID, - DemoApplicationContext.get()); - } - - @Override - public void prepareUI(JAXXObject c) { - - Preconditions.checkNotNull(c, "parameter c can not be null!"); - - // l'ui doit avoir un boutton showHelp - AbstractButton help = getShowHelpButton(c); - - if (help != null) { - - // attach context to button - if (log.isDebugEnabled()) { - log.debug("attach context to showhelp button " + c); - } - help.putClientProperty(JAXX_CONTEXT_ENTRY, c); - - // add tracking action - ActionListener listener = getShowHelpAction(); - if (log.isDebugEnabled()) { - log.debug("adding tracking action " + listener); - } - help.addActionListener(listener); - - if (log.isDebugEnabled()) { - log.debug("done for " + c); - } - } - } - - @Override - public String findHelpId(Component comp) { - - if (comp == null) { - comp = DemoApplicationContext.get().getMainUI(); - } - JAXXHelpUI parentContainer = SwingUtil.getParent(comp, JAXXHelpUI.class); - - String result; - if (parentContainer != null && this != parentContainer.getBroker()) { - - JAXXHelpBroker broker = parentContainer.getBroker(); - result = broker.findHelpId(comp); - } else { - result = super.findHelpId(comp); - } - - if (result == null) { - result = "ui.main.menu"; - } - - return result; - } - - @Override - public Component getDeppestComponent(Component mouseComponent, MouseEvent event) { - ComponentTreeNode tree = BuildTreeVisitor.buildTree(mouseComponent); - - DebugComponentTreeNodeVisitor debugTree = new DebugComponentTreeNodeVisitor() { - @Override - public String getMessage(ComponentTreeNode componentTree) { - String message = super.getMessage(componentTree); - Component userObject = componentTree.getUserObject(); - if (userObject.isShowing() && userObject.isVisible()) { - Rectangle rectangle = new Rectangle(userObject.getLocationOnScreen(), userObject.getSize()); - message += " visible - " + rectangle; - } else { - message += " invisible"; - } - return message; - } - }; - - debugTree.setDebug(log.isDebugEnabled()); - - debugTree.parse(tree); - -// Point point = event.getPoint(); - Point point = event.getLocationOnScreen(); - - Component component = GetCompopentAtPointVisitor.get(tree, point); - if (log.isDebugEnabled()) { - log.debug("Component at (" + point + "): " + component); - } - return component; - } - - -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/DemoPanel.jaxx b/jaxx-demo/src/main/java/jaxx/demo/DemoPanel.jaxx deleted file mode 100644 index 1d5b923..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/DemoPanel.jaxx +++ /dev/null @@ -1,63 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<JPanel id='top' abstract='true'> - - <import> - jaxx.demo.DemoHelpBroker - org.nuiton.util.StringUtil - </import> - - <script><![CDATA[ - -//protected String getHelpDefaultId() { return "ui.main.menu"; } - -protected String[] getSources() { - if (DemoPanel.class.equals(getClass())) { - return StringUtil.EMPTY_STRING_ARRAY; - } - return addDefaultSources(); -} - -protected String[] addDefaultSources(String... sources) { - return DemoSourcesHandler.addDefaultSources(this, sources); -} - -public String getLabel() { - String name = getClass().getSimpleName(); - if (name.endsWith("Demo")) { - name = name.substring(0, name.length() - "Demo".length()); - } - return name; -} - -public String getDemoTabTitle() { - return getLabel() + " Demo"; -} - ]]> - </script> - - <String id='helpDefaultId' javaBean='"ui.main.menu"'/> - - <DemoHelpBroker id='broker' constructorParams='getHelpDefaultId()'/> - -</JPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/DemoSources.jaxx b/jaxx-demo/src/main/java/jaxx/demo/DemoSources.jaxx deleted file mode 100644 index 207fe2f..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/DemoSources.jaxx +++ /dev/null @@ -1,90 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<JPanel layout='{new BorderLayout()}' decorator='help'> - - <import> - jaxx.demo.DemoHelpBroker - jaxx.runtime.SwingUtil - jaxx.runtime.swing.FontSizor - - java.awt.RenderingHints - javax.swing.DefaultComboBoxModel - - org.fife.ui.rsyntaxtextarea.RSyntaxTextArea - </import> - - <script><![CDATA[ - -public void init() { - handler.init(this); -} - -public DemoConfig getConfig() { - return getContextValue(DemoConfig.class); -} - - - ]]> - </script> - - <DemoHelpBroker id='broker' constructorParams='"ui.main.sources"'/> - - <Class id='incomingClass' javaBean='null' genericType='?'/> - - <String id='currentSource' javaBean='null'/> - - <java.util.List id='sources' genericType='String' javaBean='null'/> - - <JToolBar id='editorPaneHeader' - floatable='false' - borderPainted='false' - opaque='false' - constraints='BorderLayout.SOUTH'> - - <JComboBox id='sourceTabs' - model='{new DefaultComboBoxModel()}' - onItemStateChanged='if(event.getStateChange() == ItemEvent.SELECTED) { handler.updateSource(event); }'/> - <javax.swing.Box.Filler - constructorParams='SwingUtil.newMinDimension(), SwingUtil.newMinDimension(), SwingUtil.newMaxXDimension()'/> - <FontSizor id='fontSizor' opaque='false' showFontSize='true' - fontSize='{getConfig().getFontSize()}'/> - </JToolBar> - - <JScrollPane id='editorPane' columnHeaderView='{editorPaneHeader}' - constraints='BorderLayout.CENTER'> - <RSyntaxTextArea id='editor' - font-size='{getConfig().getFontSize()}' - minimumSize="{SwingUtil.newMinDimension()}" - antiAliasingEnabled='true' - editable="false" - wrapStyleWord="false" - columns="80" - lineWrap="true"/> - <!--font-size='{updateSize(getFontSizor().getFontSize())}'--> - <!-- TC-20091221 : can not use binding since we want to do something after assigment... --> - <!--text='{handler.getSourceContent(DemoSources.this, getCurrentSource())}'--> - <!--syntaxEditingStyle='{handler.getSourceEditingStyle(DemoSources.this, getCurrentSource())}'--> - </JScrollPane> - - -</JPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/DemoSourcesHandler.java b/jaxx-demo/src/main/java/jaxx/demo/DemoSourcesHandler.java deleted file mode 100644 index cded567..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/DemoSourcesHandler.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.demo; - -import com.google.common.collect.Lists; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.spi.UIHandler; -import jaxx.runtime.swing.FontSizor; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; - -import java.awt.event.ItemEvent; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -/** - * Created: 21 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - * - * Mise a jour: $Date$ par : - * $Author$ - */ -public class DemoSourcesHandler implements UIHandler<DemoSources> { - - /** Logger */ - private static final Log log = LogFactory.getLog(DemoSourcesHandler.class); - - protected static Map<String, String> sourcesCache; - - public static String[] addDefaultSources(JAXXObject ui, String... extraSources) { - List<String> sources = Lists.newArrayList(); - String packageName = ui.getClass().getPackage().getName(); - String simpleName = ui.getClass().getSimpleName(); - addIfExist(ui, sources, packageName, simpleName + ".jaxx"); - addIfExist(ui, sources, packageName, simpleName + ".css"); - addIfExist(ui, sources, packageName, simpleName + "Handler.java"); - addIfExist(ui, sources, packageName, simpleName + "Model.java"); - Collections.addAll(sources, extraSources); - return sources.toArray(new String[sources.size()]); - } - - private static void addIfExist(JAXXObject ui, - List<String> sources, - String packageName, - String resourcePath) { - String path = "/" + packageName.replaceAll("\\.", "/"); - path += "/" + resourcePath; - InputStream resource = ui.getClass().getResourceAsStream(path); - try { - if (resource != null) { - sources.add(resourcePath); - } - } finally { - IOUtils.closeQuietly(resource); - } - - } - - public static Map<String, String> getSourcesCache() { - if (sourcesCache == null) { - sourcesCache = new TreeMap<String, String>(); - } - return sourcesCache; - } - - public String getSourceContent(String name) { - if (name == null) { - return ""; - } - String result = getSourcesCache().get(name); - if (result == null) { - try { - if (log.isDebugEnabled()) { - log.debug(name + " from " + ui.getIncomingClass()); - } - int lastDotIndex = name.lastIndexOf("."); - String path = "/" + name.substring(0, lastDotIndex).replaceAll("\\.", "/"); - path += name.substring(lastDotIndex); - result = IOUtils.toString(ui.getIncomingClass().getResourceAsStream(path)); - if (log.isDebugEnabled()) { - log.debug("source [" + name + "], loaded content =\n" + result); - } - } catch (Exception e) { - log.error("could not load file " + name, e); - result = "could not load file " + name; - } - getSourcesCache().put(name, result); - } - return result; - } - - public String getSourceEditingStyle(String source) { - - if (source == null) { - return ""; - } - ui.getEditor().setFractionalFontMetricsEnabled(true); - String s = null; - if (source.matches(".*\\.jaxx") || source.matches(".*\\.xml")) { - s = RSyntaxTextArea.SYNTAX_STYLE_XML; - } else if (source.matches(".*\\.java")) { - s = RSyntaxTextArea.SYNTAX_STYLE_JAVA; - } else if (source.matches(".*\\.css")) { - s = RSyntaxTextArea.SYNTAX_STYLE_CSS; - } - if (log.isDebugEnabled()) { - log.debug("source [" + source + "] style = " + s); - } - return s; - } - - DemoSources ui; - - @Override - public void beforeInit(DemoSources ui) { - this.ui = ui; - } - - @Override - public void afterInit(final DemoSources ui) { - - //fontSizor.setDefaultFontSize(getConfig().getFontSize()); - final FontSizor fontSizor = ui.getFontSizor(); - fontSizor.init(); - fontSizor.setCallBack(new Runnable() { - - @Override - public void run() { - log.info("update font size : " + fontSizor.getFontSize()); - ui.getConfig().setFontSize(fontSizor.getFontSize()); - } - }); - } - - public void updateSource(ItemEvent event) { - ui.setCurrentSource((String) ui.sourceTabs.getSelectedItem()); - ui.editor.setText(getSourceContent(ui.getCurrentSource())); - ui.editor.setSyntaxEditingStyle(getSourceEditingStyle(ui.getCurrentSource())); - ui.editor.setCaretPosition(0); - } - - public void init(final DemoSources ui) { - List<String> sources = ui.getSources(); - if (sources == null) { - return; - } - - List<String> toFill = new ArrayList<String>(); - String prefix = ui.getIncomingClass() == null ? "" : - ui.getIncomingClass().getPackage().getName() + "."; - for (String source : sources) { - String path; - if (source.startsWith("/")) { - path = source.substring(1); - } else { - path = prefix + source; - } - if (log.isDebugEnabled()) { - log.debug("adding resource " + path); - } - toFill.add(path); - } - SwingUtil.fillComboBox(ui.getSourceTabs(), toFill, null); - if (!toFill.isEmpty()) { - ui.getSourceTabs().setSelectedIndex(0); - } - toFill.clear(); - ui.getEditor().discardAllEdits(); - } - -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/DemoUI.jaxx b/jaxx-demo/src/main/java/jaxx/demo/DemoUI.jaxx deleted file mode 100644 index 1faf8c3..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/DemoUI.jaxx +++ /dev/null @@ -1,110 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<JFrame id='mainFrame' width='1024' height='800' - decorator='help' onWindowClosing='handler.close(mainFrame)'> - - <import> - jaxx.demo.tree.DemoTreeHelper - jaxx.demo.tree.DemoCellRenderer - - jaxx.runtime.SwingUtil - jaxx.runtime.swing.CardLayout2 - jaxx.runtime.swing.StatusMessagePanel - - java.awt.Dimension - java.util.Locale - </import> - - <CardLayout2 id='contentLayout'/> - - <DemoConfig id='config' initializer='getContextValue(DemoConfig.class)'/> - - <DemoTreeHelper id='treeHelper' - initializer='getContextValue(DemoTreeHelper.class)'/> - - <DemoHelpBroker id='broker' constructorParams='"ui.main.menu"'/> - - <script><![CDATA[ - -public boolean acceptLocale(Locale l, String expected) { - return l !=null && l.toString().equals(expected); -} -]]> - </script> - - <JMenuBar id='menu'> - - <JMenu id='menuFile'> - <JMenuItem id='menuFileConfiguration' - onActionPerformed="handler.showConfig(this)"/> - <JMenu id='menuFileLanguage'> - <JMenuItem id='menuFileLanguageFR' - onActionPerformed="handler.changeLanguage(this, Locale.FRANCE)"/> - <JMenuItem id='menuFileLanguageUK' - onActionPerformed="handler.changeLanguage(this, Locale.UK)"/> - </JMenu> - <JSeparator/> - <JMenuItem id='menuFileFullscreen' - onActionPerformed="handler.changeScreen(this, true)"/> - <JMenuItem id='menuFileNormalscreen' - onActionPerformed="handler.changeScreen(this, false)"/> - <JSeparator/> - <JMenuItem id='menuFileExit' - onActionPerformed="handler.close(this)"/> - </JMenu> - - <JMenu id='menuHelp'> - <JMenuItem id='menuHelpLogs' - onActionPerformed="handler.showLogs(this)"/> - <JMenuItem id='menuHelpHelp' - onActionPerformed="handler.showHelp(this, null)"/> - <JMenuItem id='menuHelpSite' - onActionPerformed="handler.gotoSite(this)"/> - <JMenuItem id='menuHelpAbout' - onActionPerformed="handler.showAbout(this)"/> - </JMenu> - - <JToolBar layout='{new BorderLayout()}'> - - <!-- pour afficher l'aide contextuelle --> - <JButton id='showHelp' constraints='BorderLayout.EAST'/> - </JToolBar> - - - </JMenuBar> - - <JPanel id='mainPane' layout='{new BorderLayout()}'> - - <JSplitPane id='splitPane' constraints='BorderLayout.CENTER'> - <JScrollPane id='navigationPane'> - <JTree id='navigation'/> - </JScrollPane> - - <JPanel id='content'/> - - </JSplitPane> - - <StatusMessagePanel id='p' constraints='BorderLayout.SOUTH'/> - - </JPanel> -</JFrame> diff --git a/jaxx-demo/src/main/java/jaxx/demo/DemoUIHandler.java b/jaxx-demo/src/main/java/jaxx/demo/DemoUIHandler.java deleted file mode 100644 index 78b26ab..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/DemoUIHandler.java +++ /dev/null @@ -1,581 +0,0 @@ -package jaxx.demo; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.demo.tree.DemoNode; -import jaxx.demo.tree.DemoTreeHelper; -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.context.DefaultApplicationContext; -import jaxx.runtime.context.JAXXContextEntryDef; -import jaxx.runtime.context.JAXXInitialContext; -import jaxx.runtime.spi.UIHandler; -import jaxx.runtime.swing.ErrorDialogUI; -import jaxx.runtime.swing.config.ConfigUIHelper; -import jaxx.runtime.swing.log.JAXXLog4jUI; -import jaxx.runtime.swing.renderer.DecoratorProviderListCellRenderer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.decorator.DecoratorProvider; -import org.nuiton.i18n.I18n; -import org.nuiton.jaxx.widgets.about.AboutUI; -import org.nuiton.jaxx.widgets.about.AboutUIBuilder; - -import javax.swing.AbstractAction; -import javax.swing.InputMap; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.JTree; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.TreePath; -import java.awt.Component; -import java.awt.Desktop; -import java.awt.event.ActionEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.lang.reflect.Constructor; -import java.net.URL; -import java.util.Arrays; -import java.util.Locale; - -import static org.nuiton.i18n.I18n.n; -import static org.nuiton.i18n.I18n.t; - -/** - * Le handler de l'ui principale. - * - * @author Tony Chemit - chemit@codelutin.com - * @see DemoUI - */ -public class DemoUIHandler implements UIHandler<DemoUI> { - - /** Logger */ - static private Log log = LogFactory.getLog(DemoUIHandler.class); - - static final JAXXContextEntryDef<DemoUI> MAIN_UI_ENTRY_DEF = - JAXXUtil.newContextEntryDef("mainui", DemoUI.class); - - public static final String OPEN_CONFIG_ACTION = "openConfig"; - - /** - * Methode pour initialiser l'ui principale sans l'afficher. - * - * @param rootContext le context applicatif - * @param config la configuration a utiliser - * @return l'ui instancie et initialisee mais non visible encore - */ - public DemoUI initUI(DefaultApplicationContext rootContext, DemoConfig config) { - - if (log.isDebugEnabled()) { - log.debug("fullscreen ? " + config.isFullScreen()); - } - DecoratorProvider decoratorProvider = - rootContext.getContextValue(DecoratorProvider.class); - - if (!config.getLocale().equals(I18n.getDefaultLocale())) { - if (log.isInfoEnabled()) { - log.info("re-init I18n with locale " + config.getLocale()); - } - // change i18n language - I18n.setDefaultLocale(config.getLocale()); - // reload decorators - decoratorProvider.reload(); - } - - // create restrict context for ui - JAXXInitialContext context = new JAXXInitialContext(); - - // share handler - context.add(this); - - // share tree helper - context.add(rootContext.getContextValue(DemoTreeHelper.class)); - - // share config - context.add(rootContext.getContextValue(DemoConfig.class)); - - // share a unique DecoratorProvider - context.add(decoratorProvider); - - // share a unique DecoratorProviderListCellRenderer - context.add(new DecoratorProviderListCellRenderer(decoratorProvider)); - - // instanciate ui - DemoUI ui = new DemoUI(context); - - // add key strokes - addKeyStrokes(ui, config); - - // keep it in root context - MAIN_UI_ENTRY_DEF.setContextValue(rootContext, ui); - - // synch to error dialog - ErrorDialogUI.init(ui); - - // set fullscreen propery on main ui - ui.getGraphicsConfiguration().getDevice().setFullScreenWindow(config.isFullScreen() ? ui : null); - - return ui; - } - - protected void addKeyStrokes(final DemoUI ui, DemoConfig config) { - - // Use WHEN_IN_FOCUSED_WINDOW to don't have focus check for binding keys - JPanel mainPane = ui.getMainPane(); - mainPane.getActionMap().put(OPEN_CONFIG_ACTION, new AbstractAction() { - - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent e) { - showConfig(ui); - } - }); - final InputMap inputMap = mainPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); - config.addPropertyChangeListener(DemoConfig.PROPERTY_KEY_OPEN_CONFIG, new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - KeyStroke oldValue = (KeyStroke) evt.getOldValue(); - inputMap.remove(oldValue); - setShowConfigInputMap(inputMap, (KeyStroke) evt.getNewValue()); - } - }); - setShowConfigInputMap(inputMap, config.getKeyOpenConfig()); - } - - protected void setShowConfigInputMap(InputMap inputMap, KeyStroke keyStroke) { - inputMap.put(keyStroke, OPEN_CONFIG_ACTION); - } - - @Override - public void beforeInit(DemoUI ui) { - - } - - @Override - public void afterInit(final DemoUI ui) { - - // Creation of selection listener to open ui when tree selection change - TreeSelectionListener listener = new TreeSelectionListener() { - @Override - public void valueChanged(TreeSelectionEvent event) { - TreePath path = event.getPath(); - DemoNode node = (DemoNode) path.getLastPathComponent(); - - if (log.isDebugEnabled()) { - log.debug("Select node " + node); - } - - if (node == null || node.isStringNode()) { - - // noeud de présentation, rien a faire - return; - } - showUI(ui, node.getInternalClass()); - } - }; - - JTree tree = ui.getNavigation(); - - ui.getTreeHelper().setUI(tree, true, listener); - - // auto-expand node when selected - SwingUtil.addExpandOnClickListener(tree); - - } - - protected void showUI(DemoUI ui, Class<?> type) { - - JPanel content = ui.getContent(); - - String constraints = type.getName(); - - log.info("Show for " + constraints); - - // Verify if instance is existing - DemoTab demoContent = getContentIfExist(ui, constraints); - - if (demoContent == null) { - - log.info("Will instanciate a new " + constraints); - try { - // Get constructor - Constructor<?> constructor = - type.getConstructor(JAXXContext.class); - - JAXXInitialContext tx = - new JAXXInitialContext().add(ui.getDelegateContext()); - - DemoPanel panel = (DemoPanel) constructor.newInstance(tx); - - log.info("Demo panel to use : " + panel); - - demoContent = new DemoTab(tx.add("content", panel)); - - } catch (Exception eee) { - log.error(eee, eee); - ErrorDialogUI.showError(eee); - } - - // Add to content panel - content.add(demoContent, constraints); - } - - // show ui - ui.getContentLayout().show(content, constraints); - } - -// Get content if exist in content, else return null - - protected <E extends Component> E getContentIfExist(DemoUI ui, String constraints) { - if (log.isDebugEnabled()) { - log.debug("Get content if exist " + constraints); - } - if (!ui.getContentLayout().contains(constraints)) { - return null; - } - return (E) ui.getContentLayout().getComponent(ui.getContent(), constraints); - } - - public void displayUI(final DemoUI ui, final String[] nodePath) { - - // expend all nodes of the demo tree - SwingUtil.expandTree(ui.getNavigation()); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - String[] path; - if (nodePath == null) { - // take first node - path = new String[]{"jaxxdemo.tree"}; - } else { - // take selected node - path = nodePath; - - } - log.info("node to re select " + Arrays.toString(path)); - // select node - ui.getTreeHelper().selectNode(path); - - // use best dimensions - ui.getSplitPane().resetToPreferredSizes(); - } - }); - - // show ui after all (in another invocation, tu avoid layout adjustement - // to be seen). - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - - // show ui - ui.setVisible(true); - } - }); - } - - /** - * Permet de recharger l'ui principale et de changer de le mode d'affichage. - * - * @param rootContext le contexte applicatif - * @param config la configuration a utiliser - */ - public void reloadUI(DefaultApplicationContext rootContext, DemoConfig config) { - - // scan main ui - DemoUI ui = getUI(rootContext); - - String[] node = null; - if (ui != null) { - - ui.getConfig().removeJaxxPropertyChangeListener(); - - node = ui.getTreeHelper().getSelectedIds(); - - if (node != null) { - if (log.isDebugEnabled()) { - log.debug("selected node " + Arrays.toString(node)); - } - } - - ErrorDialogUI.init(null); - - ui.dispose(); - - ui.setVisible(false); - - MAIN_UI_ENTRY_DEF.removeContextValue(rootContext); - } - - ui = initUI(rootContext, config); - - displayUI(ui, node); - } - - /** - * Méthode pour changer de mode d'affichage. - * - * Si <code>fullscreen</code> est à <code>true</code> alors on passe en - * mode console (c'est à dire en mode plein écran exclusif), sinon on - * passe en mode fenetré normal. - * - * @param context l'ui principale de l'application - * @param fullscreen le nouvel état requis. - */ - public void changeScreen(JAXXContext context, boolean fullscreen) { - - DemoUI ui = getUI(context); - - // sauvegarde de l'état dans la configuration - DemoConfig config = ui.getConfig(); - config.setFullscreen(fullscreen); - - // rechargement de l'ui - reloadUI(DemoApplicationContext.get(), config); - } - - public void changeLanguage(JAXXContext context, Locale newLocale) { - - DemoUI ui = getUI(context); - - DemoConfig config = ui.getConfig(); - - // sauvegarde de la nouvelle locale - config.setLocale(newLocale); - - // rechargement de l'ui - reloadUI(DemoApplicationContext.get(), config); - } - - /** - * Ferme l'application. - * - * @param context l'ui principale de l'application - */ - public void close(JAXXContext context) { - log.info("JAXX Demo quitting..."); - try { - - DemoUI ui = getUI(context); - ui.dispose(); - } finally { - System.exit(0); - } - } - - final Runnable reloadUICallback = new Runnable() { - - @Override - public void run() { - if (log.isInfoEnabled()) { - log.info("will reload ui"); - } - DefaultApplicationContext context = DemoApplicationContext.get(); - DemoUI ui = getUI(context); - DemoConfig config = ui.getConfig(); - reloadUI(context, config); - } - }; - - final Runnable reloadApplicationCallback = new Runnable() { - - @Override - public void run() { - if (log.isInfoEnabled()) { - log.info("will reload appplication"); - } - close(DemoApplicationContext.get()); - } - }; - - final Runnable reloadLogAppenderCallback = new Runnable() { - - @Override - public void run() { - if (log.isInfoEnabled()) { - log.info("will reload log appender"); - } - DefaultApplicationContext context = DemoApplicationContext.get(); - DemoUI ui = getUI(context); - DemoConfig config = ui.getConfig(); - - // init jaxx logger - JAXXLog4jUI.init(config.getLogLevel(), config.getLogPatternLayout()); - } - }; - - public void showConfig(JAXXContext context) { - DemoUI ui = getUI(context); - DemoConfig config = ui.getConfig(); - - ConfigUIHelper helper = new ConfigUIHelper(config); - - helper.registerCallBack("ui", - n("demo.action.reload.ui"), - SwingUtil.createActionIcon("reload-ui"), - reloadUICallback); - - helper.registerCallBack("application", - n("demo.action.reload.application"), - SwingUtil.createActionIcon("reload-application"), - reloadApplicationCallback); - - helper.registerCallBack("log", - n("demo.action.reload.logAppender"), - SwingUtil.createActionIcon("reload-log"), - reloadLogAppenderCallback); - - // categorie repertoires - - helper.addCategory(n("jaxxdemo.config.category.directories"), - n("jaxxdemo.config.category.directories.description")); - - helper.addOption(DemoConfig.Option.CONFIG_FILE); - - // others - helper.addCategory(n("jaxxdemo.config.category.other"), - n("jaxxdemo.config.category.other.description")); - - helper.addOption(DemoConfig.Option.FULL_SCREEN). - setOptionPropertyName(DemoConfig.PROPERTY_FULLSCREEN). - setOptionCallBack("ui"); - - helper.addOption(DemoConfig.Option.FONT_SIZE). - setOptionPropertyName(DemoConfig.PROPERTY_FONT_SIZE). - setOptionCallBack("ui"); - - helper.addOption(DemoConfig.Option.LOCALE). - setOptionPropertyName(DemoConfig.PROPERTY_LOCALE). - setOptionCallBack("ui"); - - helper.addOption(DemoConfig.Option.DEMO_COLOR). - setOptionPropertyName(DemoConfig.PROPERTY_DEMO_COLOR). - setOptionCallBack("ui"); - - helper.addOption(DemoConfig.Option.DEMO_CLASS). - setOptionPropertyName(DemoConfig.PROPERTY_DEMO_CLASS). - setOptionCallBack("ui"); - - helper.addOption(DemoConfig.Option.KEY_OPEN_CONFIG). - setOptionPropertyName(DemoConfig.PROPERTY_KEY_OPEN_CONFIG). - setOptionCallBack("ui"); - - helper.addOption(DemoConfig.Option.LOG_LEVEL). - setOptionPropertyName(DemoConfig.PROPERTY_LOG_LEVEL). - setOptionCallBack("log"); - - helper.addOption(DemoConfig.Option.LOG_PATTERN_LAYOUT). - setOptionPropertyName(DemoConfig.PROPERTY_LOG_PATTERN_LAYOUT). - setOptionCallBack("log"); - - helper.buildUI(context, "jaxxdemo.config.category.other"); - - helper.displayUI(ui, false); - } - - public void showHelp(DemoUI ui) { - - DemoApplicationContext.get().showHelp(ui, ui.getBroker(), null); - } - - public void showHelp(JAXXContext context, String helpId) { - log.info(context + " :: " + helpId); -// DemoUI mainUI = getUI(context); -// ObserveHelpBroker helpBroker = context.getContextValue(ObserveHelpBroker.class); -// -// if (helpId == null) { -// helpId = helpBroker.getDefaultID(); -// } -// log.debug("show help " + helpId); -// mainUI.getHelp().setCurrentID(helpId); - } - - public void showLogs(DemoUI ui) { - - JAXXLog4jUI log4jUI = new JAXXLog4jUI(); - String title = t("jaxxdemo.title.showLog"); - log4jUI.setTitle(title); - log4jUI.showInDialog(ui, false); - } - - public void gotoSite(JAXXContext context) { - - DemoUI ui = getUI(context); - DemoConfig config = ui.getConfig(); - - URL siteURL = config.getApplicationSiteUrl(); - - log.info(t("jaxxdemo.message.goto.site", siteURL)); - - if (log.isDebugEnabled()) { - log.debug("goto " + siteURL); - } - if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { - try { - Desktop.getDesktop().browse(siteURL.toURI()); - } catch (Exception ex) { - log.error(ex.getMessage(), ex); - ErrorDialogUI.showError(ex); - } - } - } - - public void showAbout(DemoUI ui) { - - DemoConfig config = ui.getConfig(); - - String iconPath = config.getIconPath(); - - String name = "jaxx-demo"; - AboutUI about = AboutUIBuilder.builder(ui) - .setIconPath(config.getIconPath()) - .setTitle(t("jaxxdemo.title.about")) - .setBottomText(ui.getConfig().getCopyrightText()) - .addAboutTab(t("jaxxdemo.about.message"), true) - .addDefaultLicenseTab(name, false) - .addDefaultThirdPartyTab(name, false) - .addDefaultChangelogTab(name, false) - .build(); - - about.display(); - - } - - DemoUI getUI(JAXXContext context) { - if (context instanceof DemoUI) { - return (DemoUI) context; - } - DemoUI ui = MAIN_UI_ENTRY_DEF.getContextValue(context); - return ui; - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/RunDemo.java b/jaxx-demo/src/main/java/jaxx/demo/RunDemo.java deleted file mode 100644 index ddfe7de..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/RunDemo.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo; - -import jaxx.demo.entities.DemoDecoratorProvider; -import jaxx.demo.tree.DemoDataProvider; -import jaxx.demo.tree.DemoTreeHelper; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.swing.ErrorDialogUI; -import jaxx.runtime.swing.log.JAXXLog4jUI; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.decorator.DecoratorProvider; -import org.nuiton.i18n.I18n; -import org.nuiton.i18n.init.DefaultI18nInitializer; -import org.nuiton.util.StringUtil; - -import java.util.Arrays; -import java.util.Date; - -import static org.nuiton.i18n.I18n.t; - -/** @author Tony Chemit - chemit@codelutin.com */ -public class RunDemo { - - /** Logger */ - private static Log log = LogFactory.getLog(RunDemo.class); - - public static void main(String... args) { - - long startingTime = System.nanoTime(); - log.info("JAXX Demo start at " + new Date() + " args: " + Arrays.toString(args)); - - try { - - // init root context - // to enable javassist on webstart, must remove any securityManager, - // see if this can be dangerous (should not be since jnlp is signed ?) - // moreover it speeds up the loading :) - System.setSecurityManager(null); - - long t0 = System.nanoTime(); - - I18n.init(new DefaultI18nInitializer("jaxx-demo-i18n"), null); - - Runtime.getRuntime().addShutdownHook(new ShutdownHook()); - - // init config - DemoConfig config = new DemoConfig(args); - - // init root context - DemoApplicationContext rootContext = DemoApplicationContext.init(config); - - // share a tree helper - rootContext.setContextValue(new DemoTreeHelper(new DemoDataProvider())); - - // share the config - rootContext.setContextValue(config); - - // init decorator provider - DecoratorProvider p = new DemoDecoratorProvider(); - - // share the decorator provider - rootContext.setContextValue(p); - - long t00 = System.nanoTime(); - - // init i18n - I18n.setDefaultLocale(config.getLocale()); - - log.info("language : " + config.getLocale()); - - if (log.isDebugEnabled()) { - log.debug("i18n loading time : " + StringUtil.convertTime(t00, System.nanoTime())); - } - - log.info(t("jaxxdemo.message.config.loaded", config.getVersion())); - - // init jaxx logger - JAXXLog4jUI.init(config.getLogLevel(), config.getLogPatternLayout()); - - // prepare ui look&feel and load ui properties - try { - SwingUtil.initNimbusLoookAndFeel(); - } catch (Exception e) { - // could not find nimbus look-and-feel - log.warn(t("jaxxdemo.warning.nimbus.landf")); - } catch (Throwable e) { - log.warn(t("jaxxdemo.warning.no.ui")); - - } - - if (log.isDebugEnabled()) { - log.debug("init done in " + StringUtil.convertTime(t0, System.nanoTime())); - } - - log.info(t("jaxxdemo.init.context.done", StringUtil.convertTime(startingTime, System.nanoTime()))); - - // on affiche l'ui principale - DemoUIHandler handler = new DemoUIHandler(); - - DemoUI ui = handler.initUI(rootContext, config); - - log.info(t("jaxxdemo.init.ui.done")); - - DemoApplicationContext.MAIN_UI.setContextValue(rootContext, ui); - - handler.displayUI(ui, config.getDemoPath().split("/")); - - } catch (Exception e) { - log.error(e.getMessage(), e); - ErrorDialogUI.showError(e); - System.exit(1); - } - } - - protected static class ShutdownHook extends Thread { - - public ShutdownHook() { - super("shutdown JAXXDemo"); - } - - @Override - public void run() { - try { - super.run(); - - // force to kill main thread - - log.info(t("jaxxdemo.init.closed", new Date())); - Runtime.getRuntime().halt(0); - } catch (Exception ex) { - log.error("error while closing " + ex.getMessage(), ex); - Runtime.getRuntime().halt(1); - } - } - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/BoxedDecoratorDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/BoxedDecoratorDemo.jaxx deleted file mode 100644 index 61582a5..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/BoxedDecoratorDemo.jaxx +++ /dev/null @@ -1,122 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - - -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - jaxx.runtime.SwingUtil - jaxx.runtime.swing.BlockingLayerUI - jaxx.runtime.swing.BlockingLayerUI2 - - java.awt.Color - java.awt.event.ActionEvent - - javax.swing.AbstractAction - javax.swing.DefaultListModel - javax.swing.JComponent - </import> - <BlockingLayerUI id='layerUI' - acceptAction='{new AbstractAction() { - private static final long serialVersionUID = 1L; - @Override - public void actionPerformed(ActionEvent e) { - accept(e, "from icon of layer"); - } - }}'/> - <BlockingLayerUI2 id='layerUI2' - acceptAction='{new AbstractAction() { - private static final long serialVersionUID = 1L; - @Override - public void actionPerformed(ActionEvent e) { - accept(e, "from icon of layer"); - } - }}'/> - <script><![CDATA[ - -void $afterCompleteSetup() { - for (JComponent boxed : SwingUtil.getLayeredComponents(this)) { - if (boxed == buttonD) { - SwingUtil.setLayerUI(boxed, layerUI2); - continue; - } - - BlockingLayerUI ui = layerUI.clone(); - if (boxed == buttonC) { - ui.setBlock(true); - } - SwingUtil.setLayerUI(boxed, ui); - } -} - -public void setLayer(boolean active) { - for (JComponent boxed : SwingUtil.getLayeredComponents(this)) { - if (boxed == buttonD) { - continue; - } - BlockingLayerUI ui = (BlockingLayerUI) SwingUtil.getLayer(boxed).getUI(); - if (boxed == buttonC) { - ui.setBlock(active); - } - ui.setUseIcon(active); - } -} - -protected void accept(ActionEvent e, String suffix) { - JButton source = (JButton) e.getSource(); - String clickedMessage = (String) source.getClientProperty("clickedText"); - String msg = "'" + source.getText() + "' clicked - " + suffix + " : " + clickedMessage; - ((DefaultListModel)messages.getModel()).addElement(msg); -}]]> - </script> - <Table fill='both' weightx='1' constraints='BorderLayout.CENTER'> - <row> - <cell> - <JCheckBox id='toggle' selected='true' - text='{toggle.isSelected() ? "Active layer" : "No layer"}' - onActionPerformed='setLayer(toggle.isSelected());'/> - </cell> - </row> - <row> - <cell weighty='0.5'> - <JPanel id='buttonPane'> - <JButton id='buttonA' decorator='boxed' - _clickedText='"button A was clicked"' - onActionPerformed='accept(event, "from button (no layer)")'/> - <JButton id='buttonB' decorator='boxed' - onActionPerformed='accept(event, "from button (no layer)")'/> - <JButton id='buttonC' decorator='boxed' - onActionPerformed='accept(event, "from button (no layer)");'/> - <JButton id='buttonD' decorator='boxed' - onActionPerformed='accept(event, "from button (no layer)");'/> - </JPanel> - </cell> - </row> - <row> - <cell weighty='0.5'> - <JScrollPane> - <JList id='messages'/> - </JScrollPane> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/StatusMessagePanelDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/StatusMessagePanelDemo.jaxx deleted file mode 100644 index 24bd58f..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/StatusMessagePanelDemo.jaxx +++ /dev/null @@ -1,32 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - <JPanel layout='{new GridLayout(0,1)}' constraints='BorderLayout.CENTER'> - <JButton text='Fool me once' - onActionPerformed='p.setStatus(((JButton)event.getSource()).getText() + " ? shame on you!")'/> - <JButton text='Fool me twice' - onActionPerformed='p.setStatus(((JButton)event.getSource()).getText() + " ? shame on ...")'/> - </JPanel> - <jaxx.runtime.swing.StatusMessagePanel id='p' - constraints='BorderLayout.SOUTH'/> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanComboBoxDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanComboBoxDemo.jaxx deleted file mode 100644 index 056e7a8..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanComboBoxDemo.jaxx +++ /dev/null @@ -1,53 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - jaxx.demo.entities.People - jaxx.runtime.swing.editor.bean.BeanComboBox - </import> - - <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> - <row> - <cell> - <JPanel id='configurationPanel' layout='{new GridLayout(0,1)}'> - <JCheckBox id='autoCompleteButton'/> - <JCheckBox id='showResetButton'/> - <JCheckBox id='showDecoratorButton'/> - </JPanel> - </cell> - </row> - <row> - <cell> - <BeanComboBox id='comboBox' genericType='People'/> - </cell> - </row> - <row> - <cell> - <JPanel id='resultPanel' layout='{new BorderLayout()}'> - <JLabel id='selectedResult' constraints='BorderLayout.CENTER'/> - </JPanel> - </cell> - </row> - </Table> - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanComboBoxDemoHandler.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanComboBoxDemoHandler.java deleted file mode 100644 index b426a8c..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanComboBoxDemoHandler.java +++ /dev/null @@ -1,76 +0,0 @@ -package jaxx.demo.component.jaxx.editor; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.demo.entities.DemoDataProvider; -import jaxx.demo.entities.DemoDecoratorProvider; -import jaxx.demo.entities.People; -import jaxx.runtime.spi.UIHandler; -import org.nuiton.decorator.JXPathDecorator; - -import java.util.List; - -import static org.nuiton.i18n.I18n.t; -import static org.nuiton.i18n.I18n.n; - -/** - * Handlerof {@link BeanComboBoxDemo}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.9 - */ -public class BeanComboBoxDemoHandler implements UIHandler<BeanComboBoxDemo> { - - private JXPathDecorator<People> decorator; - - @Override - public void beforeInit(BeanComboBoxDemo ui) { - this.decorator = (JXPathDecorator<People>) - new DemoDecoratorProvider().getDecoratorByType(People.class); - } - - @Override - public void afterInit(BeanComboBoxDemo ui) { - List<People> data = new DemoDataProvider().getPeoples(); - - ui.getComboBox().init(decorator, data); - } - - public String getSelectedResult(People people) { - String result; - - if (people == null) { - result = t("jaxxdemo.beancomboboxdemo.no.people.selected"); - } else { - result = t("jaxxdemo.beancomboboxdemo.selected.people", decorator.toString(people)); - } - return result; - } - - static { - n("jaxxdemo.common.people"); - n("jaxxdemo.common.firstName"); - n("jaxxdemo.common.lastName"); - n("jaxxdemo.common.age"); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanDoubleListDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanDoubleListDemo.jaxx deleted file mode 100644 index 35f424a..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanDoubleListDemo.jaxx +++ /dev/null @@ -1,48 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - jaxx.demo.entities.People - jaxx.runtime.swing.editor.bean.BeanDoubleList - </import> - - <Table fill='both'> - <row> - <cell> - <JPanel id='configurationPanel' layout='{new GridLayout(0,1)}'> - <JCheckBox id='filterableButton'/> - <JCheckBox id='highlightFilterTextButton'/> - <JCheckBox id='showResetButton'/> - <JCheckBox id='showDecoratorButton'/> - <JCheckBox id='filterOnNachoButton'/> - </JPanel> - </cell> - </row> - <row> - <cell weighty='1' weightx='1'> - <BeanDoubleList id='doubleList' genericType='People'/> - </cell> - </row> - </Table> - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanDoubleListDemoHandler.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanDoubleListDemoHandler.java deleted file mode 100644 index df9bb67..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanDoubleListDemoHandler.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package jaxx.demo.component.jaxx.editor; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Predicate; -import jaxx.demo.entities.DemoDataProvider; -import jaxx.demo.entities.DemoDecoratorProvider; -import jaxx.demo.entities.Movie; -import jaxx.demo.entities.People; -import jaxx.runtime.spi.UIHandler; -import org.nuiton.decorator.JXPathDecorator; - -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.util.List; - -/** @author kmorin */ -public class BeanDoubleListDemoHandler implements UIHandler<BeanDoubleListDemo> { - - private BeanDoubleListDemo ui; - - @Override - public void beforeInit(BeanDoubleListDemo ui) { - this.ui = ui; - } - - @Override - public void afterInit(BeanDoubleListDemo ui) { - DemoDataProvider demoDataProvider = new DemoDataProvider(); - List<People> data = demoDataProvider.getPeoples(); - JXPathDecorator<People> decorator = (JXPathDecorator<People>) new DemoDecoratorProvider().getDecoratorByType(People.class); - ui.getDoubleList().init(decorator, data, data.subList(0, 1)); - - final Movie nacho = demoDataProvider.getMovie("0"); - final Predicate<People> filter = new Predicate<People>() { - - public boolean apply(People input) { - return nacho.getActors().contains(input); - } - }; - ui.getFilterOnNachoButton().addChangeListener(new ChangeListener() { - - public void stateChanged(ChangeEvent e) { - if (BeanDoubleListDemoHandler.this.ui.getFilterOnNachoButton().isSelected()) { - BeanDoubleListDemoHandler.this.ui.getDoubleList().getHandler().addFilter(filter); - - } else { - BeanDoubleListDemoHandler.this.ui.getDoubleList().getHandler().clearFilters(); - } - } - }); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemo.jaxx deleted file mode 100644 index 4c40b27..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemo.jaxx +++ /dev/null @@ -1,54 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - jaxx.demo.entities.People - jaxx.runtime.swing.editor.bean.BeanFilterableComboBox - </import> - - <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> - <row> - <cell> - <JPanel id='configurationPanel' layout='{new GridLayout(0,1)}'> - <JCheckBox id='filterableButton'/> - <JCheckBox id='showResetButton'/> - <JCheckBox id='showDecoratorButton'/> - <JCheckBox id='colorizeInvalidComboEditorTextButton'/> - </JPanel> - </cell> - </row> - <row> - <cell> - <BeanFilterableComboBox id='comboBox' genericType='People'/> - </cell> - </row> - <row> - <cell> - <JPanel id='resultPanel' layout='{new BorderLayout()}'> - <JLabel id='selectedResult' constraints='BorderLayout.CENTER'/> - </JPanel> - </cell> - </row> - </Table> - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemoHandler.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemoHandler.java deleted file mode 100644 index bd623a3..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemoHandler.java +++ /dev/null @@ -1,78 +0,0 @@ -package jaxx.demo.component.jaxx.editor; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.demo.entities.DemoDataProvider; -import jaxx.demo.entities.DemoDecoratorProvider; -import jaxx.demo.entities.People; -import jaxx.runtime.spi.UIHandler; -import org.nuiton.decorator.JXPathDecorator; - -import java.util.List; - -import static org.nuiton.i18n.I18n.t; -import static org.nuiton.i18n.I18n.n; - -/** - * Handlerof {@link BeanComboBoxDemo}. - * - * @author Kevin Morin - morin@codelutin.com - * @since 2.5.12 - */ -public class BeanFilterableComboBoxDemoHandler implements UIHandler<BeanFilterableComboBoxDemo> { - - private JXPathDecorator<People> decorator; - - - @Override - public void beforeInit(BeanFilterableComboBoxDemo ui) { - this.decorator = (JXPathDecorator<People>) - new DemoDecoratorProvider().getDecoratorByType(People.class); - } - - @Override - public void afterInit(BeanFilterableComboBoxDemo ui) { - - List<People> data = new DemoDataProvider().getPeoples(); - - ui.getComboBox().init(decorator, data); - } - - public String getSelectedResult(Object people) { - String result; - - if (people == null || !People.class.isInstance(people)) { - result = t("jaxxdemo.beanfilterablecomboboxdemo.no.people.selected"); - } else { - result = t("jaxxdemo.beanfilterablecomboboxdemo.selected.people", decorator.toString(people)); - } - return result; - } - - static { - n("jaxxdemo.common.people"); - n("jaxxdemo.common.firstName"); - n("jaxxdemo.common.lastName"); - n("jaxxdemo.common.age"); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/ComboEditorDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/ComboEditorDemo.jaxx deleted file mode 100644 index ee63828..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/ComboEditorDemo.jaxx +++ /dev/null @@ -1,66 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - - -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - org.nuiton.i18n.LanguageEnum - org.nuiton.i18n.CountryEnum - </import> - - <Table fill='both' constraints='BorderLayout.CENTER'> - <row> - <cell> - <JLabel text='Locale editor:' labelFor='{localeEditor}'/> - </cell> - - <cell> - <LocaleEditor id='localeEditor'/> - </cell> - </row> - <row> - <cell> - <JLabel text='EnumEditor (language) :' labelFor='{languageEditor}'/> - </cell> - <cell> - <EnumEditor id='languageEditor' genericType='LanguageEnum' - constructorParams='LanguageEnum.class'/> - </cell> - </row> - <row> - <cell> - <JLabel text='EnumEditor (country) :' labelFor='{countryEditor}'/> - </cell> - <cell> - <EnumEditor id='countryEditor' genericType='CountryEnum' - constructorParams='CountryEnum.class'/> - </cell> - </row> - <row> - <cell columns="2"> - <JTextArea - text='{"locale : "+ localeEditor.getSelectedItem() + "\nlanguage : "+ languageEditor.getSelectedItem() + "\ncountry : " + countryEditor.getSelectedItem()}'/> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/DatePickerDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/DatePickerDemo.jaxx deleted file mode 100644 index 41e2db7..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/DatePickerDemo.jaxx +++ /dev/null @@ -1,96 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - java.beans.PropertyChangeEvent - java.beans.PropertyChangeListener - java.text.SimpleDateFormat - java.util.Date - </import> - - <String id='patternLayout' javaBean='"dd/MM/yyyy HH:mm:ss"'/> - - <SimpleDateFormat id='dateFormat' constructorParams='patternLayout'/> - - <Date id='date' javaBean='new Date()'/> - - <script><![CDATA[ - protected void $afterCompleteSetup() { - - addPropertyChangeListener(PROPERTY_PATTERN_LAYOUT, new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - dateFormat = new SimpleDateFormat(patternLayout); - datePicker.setPatternLayout(patternLayout); - resultView.setText(dateFormat.format(date)); - } - }); - - addPropertyChangeListener(PROPERTY_DATE, new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - resultView.setText(dateFormat.format(date)); - } - }); - } - ]]></script> - - <Table fill='both' constraints='BorderLayout.CENTER'> - <row> - <cell columns='2' fill='horizontal' weightx='1'> - <JCheckBox id='showPopupButton' - text='jaxxdemo.datePickerEditor.showPopupButton' - selected='false'/> - </cell> - </row> - <row> - <cell> - <JLabel text='jaxxdemo.datePickerEditor.patternLayout'/> - </cell> - <cell fill='horizontal' weightx='1'> - <JTextField id='patternLayoutField' - text='{patternLayout}' - onFocusLost='setPatternLayout(patternLayoutField.getText())'/> - </cell> - </row> - <row> - <cell fill='horizontal' weightx='1' columns='2'> - <JAXXDatePicker id='datePicker' - date='{date}' - patternLayout='{patternLayout}' - showPopupButton='{showPopupButton.isSelected()}' - onActionPerformed='setDate(datePicker.getDate())'/> - </cell> - </row> - <row> - <cell> - <JLabel text='jaxxdemo.datePickerEditor.dateResult'/> - </cell> - <cell fill='horizontal' weightx='1'> - <JLabel id='resultView' text='{dateFormat.format(date)}'/> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FileEditorDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FileEditorDemo.jaxx deleted file mode 100644 index e0e642c..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FileEditorDemo.jaxx +++ /dev/null @@ -1,121 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - <import> - jaxx.runtime.swing.editor.FileEditor - </import> - - <String id='title' javaBean='"Open file"'/> - <String id='exts' javaBean='"txt, png"'/> - <String id='extsDescription' javaBean='"Text (*.txt), Image (*.png)"'/> - <Boolean id='acceptAllFileFilterUsed' javaBean='Boolean.TRUE'/> - <Boolean id='directoryEnabled' javaBean='Boolean.TRUE'/> - <Boolean id='fileEnabled' javaBean='Boolean.FALSE'/> - <Boolean id='showReset' javaBean='Boolean.TRUE'/> - - <Table fill='both' constraints='BorderLayout.CENTER'> - <row> - <cell fill='horizontal' weightx='1'> - <JLabel text='jaxxdemo.fileEditor.titleLbl'/> - </cell> - <cell fill='horizontal' weightx='1'> - <JTextField id='titleField' - text='{getTitle()}' - onKeyReleased='setTitle(titleField.getText())'/> - </cell> - </row> - <row> - <cell fill='horizontal' weightx='1'> - <JLabel text='jaxxdemo.fileEditor.directoryEnabled'/> - </cell> - <cell fill='horizontal' weightx='1'> - <JCheckBox id='directoryEnabledField' - selected='{isDirectoryEnabled()}' - onActionPerformed='setDirectoryEnabled(directoryEnabledField.isSelected())'/> - </cell> - </row> - <row> - <cell fill='horizontal' weightx='1'> - <JLabel text='jaxxdemo.fileEditor.fileEnabled'/> - </cell> - <cell fill='horizontal' weightx='1'> - <JCheckBox id='fileEnabledField' - selected='{isFileEnabled()}' - onActionPerformed='setFileEnabled(fileEnabledField.isSelected())'/> - </cell> - </row> - <row> - <cell fill='horizontal' weightx='1'> - <JLabel text='jaxxdemo.fileEditor.extsLbl'/> - </cell> - <cell fill='horizontal' weightx='1'> - <JTextField id='extsField' - enabled='{isFileEnabled()}' - text='{getExts()}' - onKeyReleased='setExts(extsField.getText())'/> - </cell> - </row> - <row> - <cell fill='horizontal' weightx='1'> - <JLabel text='jaxxdemo.fileEditor.extsDescLbl'/> - </cell> - <cell fill='horizontal' weightx='1'> - <JTextField id='extsDescriptionField' - enabled='{isFileEnabled()}' - text='{getExtsDescription()}' - onKeyReleased='setExtsDescription(extsDescriptionField.getText())'/> - </cell> - </row> - <row> - <cell fill='horizontal' weightx='1'> - <JLabel text='jaxxdemo.fileEditor.acceptAllFileFilterUsed'/> - </cell> - <cell fill='horizontal' weightx='1'> - <JCheckBox id='acceptAllFileFilterUsedField' - selected='{isAcceptAllFileFilterUsed()}' - onActionPerformed='setAcceptAllFileFilterUsed(acceptAllFileFilterUsedField.isSelected())'/> - </cell> - </row> - <row> - <cell fill='horizontal' weightx='1'> - <JLabel text='jaxxdemo.fileEditor.showResetLabel'/> - </cell> - <cell fill='horizontal' weightx='1'> - <JCheckBox id='showResetCheckBox' - selected='{isShowReset()}' - onActionPerformed='setShowReset(showResetCheckBox.isSelected())'/> - </cell> - </row> - <row> - <cell fill='horizontal' weightx='1' columns='2'> - <FileEditor id='fileChooser' - title='{getTitle()}' - exts='{getExts()}' - directoryEnabled='{isDirectoryEnabled()}' - showReset='{isShowReset()}' - fileEnabled='{isFileEnabled()}' - acceptAllFileFilterUsed='{isAcceptAllFileFilterUsed()}' - extsDescription='{getExtsDescription()}'/> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/I18nEditorDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/I18nEditorDemo.jaxx deleted file mode 100644 index 24a1c45..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/I18nEditorDemo.jaxx +++ /dev/null @@ -1,92 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - - -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - <import> - javax.swing.border.Border - jaxx.runtime.swing.editor.I18nEditor - org.nuiton.i18n.I18n - java.util.Arrays - </import> - <script><![CDATA[ -protected Border getPopupBorder(String text) { - if (text==null || text.trim().isEmpty()) { - return null; - } - return new TitledBorder(t(text)); -} -]]> - </script> - <Table fill='both' constraints='BorderLayout.CENTER'> - <row> - <cell> - <JPanel - border='{new TitledBorder(t("jaxxdemo.i18neditor.configuration"))}' - layout='{new GridLayout(0,1)}'> - - <JCheckBox id='showText' - text='jaxxdemo.i18neditor.showText' - selected='true'/> - - <JCheckBox id='showIcon' - text='jaxxdemo.i18neditor.showIcon' - selected='true'/> - - <JCheckBox id='showPopupText' - text='jaxxdemo.i18neditor.showPopupText' - selected='true'/> - - <JCheckBox id='showPopupIcon' - text='jaxxdemo.i18neditor.showPopupIcon' - selected='true'/> - - <JPanel> - <JLabel text='jaxxdemo.i18neditor.popupBorderText' - labelFor='{popupBorderText}'/> - <JTextField id='popupBorderText' - text='{t("jaxxdemo.i18neditor.popup.title")}'/> - </JPanel> - - </JPanel> - </cell> - </row> - <row> - <cell> - <I18nEditor id='editor' - showText='{showText.isSelected()}' - showIcon='{showIcon.isSelected()}' - showPopupText='{showPopupText.isSelected()}' - showPopupIcon='{showPopupIcon.isSelected()}' - popupBorder='{getPopupBorder(popupBorderText.getText())}' - locales='{Arrays.asList(I18n.getStore().getLocales())}'/> - </cell> - </row> - <row> - <cell> - <JLabel - border='{new TitledBorder(t("jaxxdemo.i18neditor.selected.locale"))}' - text='{editor.getSelectedLocale().toString()}'/> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/ListSelectorDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/ListSelectorDemo.jaxx deleted file mode 100644 index ac81728..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/ListSelectorDemo.jaxx +++ /dev/null @@ -1,101 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - <import> - jaxx.runtime.swing.ListSelector - com.google.common.collect.Lists - java.util.List - jaxx.demo.entities.People - jaxx.demo.entities.Movie - jaxx.demo.entities.DemoDataProvider - jaxx.demo.entities.DemoDecoratorProvider - jaxx.runtime.swing.renderer.DecoratorProviderListCellRenderer - java.util.Collection - jaxx.runtime.swing.model.GenericListModel - </import> - - <ListCellRenderer id='listCellRenderer' initializer='new DecoratorProviderListCellRenderer(new DemoDecoratorProvider())'/> - <DemoDataProvider id='dataProvider'/> - - <String id='addToolTip' javaBean='"Add"'/> - <String id='removeToolTip' javaBean='"Remove"'/> - - <script><![CDATA[ -public List<People> getActors(Collection<Movie> movies) { - List<People> actors = Lists.newArrayList(); - for (Movie m : movies) { - List<People> actorsToAdd = m.getActors(); - actors.removeAll(actorsToAdd); - actors.addAll(actorsToAdd); - } - return actors; -} -]]></script> - - <Table fill='both' constraints='BorderLayout.CENTER'> - <row> - <cell fill='horizontal' weightx='1'> - <JLabel text='jaxxdemo.listSelector.addToolTipLbl'/> - </cell> - <cell fill='horizontal' weightx='1'> - <JTextField id='addToolTipField' - text='{getAddToolTip()}' - onKeyReleased='setAddToolTip(addToolTipField.getText())'/> - </cell> - </row> - <row> - <cell fill='horizontal' weightx='1'> - <JLabel text='jaxxdemo.listSelector.removeToolTipLbl'/> - </cell> - <cell fill='horizontal' weightx='1'> - <JTextField id='removeToolTipField' - text='{getRemoveToolTip()}' - onKeyReleased='setRemoveToolTip(removeToolTipField.getText())'/> - </cell> - </row> - <row> - <cell fill='both' weightx='1' weighty='0.5' columns='2'> - <JScrollPane> - <ComboToListSelector id='comboToListSelector' - genericType='Movie' - addToolTip='{getAddToolTip()}' - removeToolTip='{getRemoveToolTip()}' - values='{dataProvider.getMovies()}' - renderer='{listCellRenderer}' - onValuesAdded='listToListSelector.setValues(getActors(comboToListSelector.getSelectedValues()))' - onValuesRemoved='listToListSelector.setValues(getActors(comboToListSelector.getSelectedValues()))'/> - </JScrollPane> - </cell> - </row> - <row> - <cell fill='both' weightx='1' weighty='0.5' columns='2'> - <JScrollPane> - <ListToListSelector id='listToListSelector' - genericType='People' - addToolTip='{getAddToolTip()}' - removeToolTip='{getRemoveToolTip()}' - renderer='{listCellRenderer}'/> - </JScrollPane> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/NumberEditorDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/NumberEditorDemo.jaxx deleted file mode 100644 index af20e9f..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/NumberEditorDemo.jaxx +++ /dev/null @@ -1,113 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - jaxx.runtime.swing.editor.NumberEditor - static org.nuiton.i18n.I18n.t - </import> - - <!-- model --> - <NumberEditorDemoModel id='demoModel'/> - - <script><![CDATA[ - -public void changeNumberPattern() { - editor.setNumberPattern(numberPattern.getText()); -} - -void $afterCompleteSetup() { - editor.init(); - changeNumberPattern(); -} - -]]> - </script> - - <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> - <row> - <cell> - <JPanel - border='{new TitledBorder(t("jaxxdemo.numbereditor.configuration"))}' - layout='{new GridLayout(0,1)}'> - - <JCheckBox id='useFloat' - text='jaxxdemo.numbereditor.useFloat' - selected='true'/> - - <JCheckBox id='useSign' - text='jaxxdemo.numbereditor.useSign' - selected='true'/> - - <JCheckBox id='showPopupButton' - text='jaxxdemo.numbereditor.showPopupButton' - selected='true'/> - - <JCheckBox id='showResetButton' - text='jaxxdemo.numbereditor.showReset' - selected='true'/> - - <JCheckBox id='autoPopup' - text='jaxxdemo.numbereditor.autoPopup' - selected='false'/> - <JPanel - border='{new TitledBorder(t("jaxxdemo.numbereditor.numberPattern.configuration"))}' - layout='{new GridLayout(1,0)}'> - <JTextField id='numberPattern' text='{"\\d{0,3}"}'/> - <JButton id='applyNumberPattern' - text='jaxxdemo.numbereditor.applyNumberPattern' - onActionPerformed='changeNumberPattern();'/> - </JPanel> - </JPanel> - </cell> - </row> - <row> - <cell> - <jaxx.runtime.swing.editor.NumberEditor id='editor' - constructorParams='this' - bean='{demoModel}' - property='{useFloat.isSelected() ? "floatProperty" : "integerProperty"}' - useFloat='{useFloat.isSelected()}' - useSign='{useSign.isSelected()}' - autoPopup='{autoPopup.isSelected()}' - showPopupButton='{showPopupButton.isSelected()}' - showReset='{showResetButton.isSelected()}'/> - </cell> - </row> - <row> - <cell> - <JPanel border='{new TitledBorder(t("jaxxdemo.numbereditor.model"))}' - layout='{new GridLayout(0,1)}'> - <JLabel - text='{t("jaxxdemo.numbereditor.model.numberPattern", editor.getNumberPattern())}'/> - <JLabel - text='{t("jaxxdemo.numbereditor.model.int", demoModel.getIntegerProperty())}'/> - <JLabel - text='{t("jaxxdemo.numbereditor.model.float", demoModel.getFloatProperty())}'/> - - </JPanel> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> - diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/NumberEditorDemoModel.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/NumberEditorDemoModel.java deleted file mode 100644 index 4f5a45e..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/NumberEditorDemoModel.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.component.jaxx.editor; - -import org.jdesktop.beans.AbstractSerializableBean; - -/** - * @author Tony Chemit - chemit@codelutin.com - * @since 1.5 - */ -public class NumberEditorDemoModel extends AbstractSerializableBean { - - public static final String INTEGER_PROPERTY = "integerProperty"; - - public static final String FLOAT_PROPERTY = "floatProperty"; - - private static final long serialVersionUID = 1L; - - protected int integerProperty; - - protected float floatProperty; - - public float getFloatProperty() { - return floatProperty; - } - - public int getIntegerProperty() { - return integerProperty; - } - - public void setFloatProperty(float floatProperty) { - float old = this.floatProperty; - this.floatProperty = floatProperty; - firePropertyChange(FLOAT_PROPERTY, old, floatProperty); - } - - public void setIntegerProperty(int integerProperty) { - int old = this.integerProperty; - this.integerProperty = integerProperty; - firePropertyChange(INTEGER_PROPERTY, old, integerProperty); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemo.jaxx deleted file mode 100644 index 3d94c0d..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemo.jaxx +++ /dev/null @@ -1,81 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - jaxx.runtime.swing.editor.SimpleTimeEditor - - static org.nuiton.i18n.I18n.t - </import> - - <!-- model --> - <SimpleTimeEditorDemoModel id='demoModel'/> - - <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> - <row> - <cell> - <JPanel id="configPanel"> - - <!--JCheckBox id='useFloat' - text='jaxxdemo.numbereditor.useFloat' - selected='true'/> - - <JCheckBox id='useSign' - text='jaxxdemo.numbereditor.useSign' - selected='true'/> - - <JCheckBox id='showPopupButton' - text='jaxxdemo.numbereditor.showPopupButton' - selected='true'/> - - <JCheckBox id='showResetButton' - text='jaxxdemo.numbereditor.showReset' - selected='true'/> - - <JCheckBox id='autoPopup' - text='jaxxdemo.numbereditor.autoPopup' - selected='false'/--> - - </JPanel> - </cell> - </row> - <row> - <cell> - <SimpleTimeEditor id='editor' constructorParams='this' - border='{new TitledBorder(t("jaxxdemo.timeeditor.editor"))}'/> - </cell> - </row> - <row> - <cell> - - <JPanel id='resultPane'> - - <JLabel constraints='BorderLayout.CENTER' - text='{t("jaxxdemo.timeeditor.value", demoModel.getTime())}'/> - </JPanel> - - </cell> - </row> - </Table> - - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemoHandler.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemoHandler.java deleted file mode 100644 index 4fd6699..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemoHandler.java +++ /dev/null @@ -1,47 +0,0 @@ -package jaxx.demo.component.jaxx.editor; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.spi.UIHandler; - -/** - * Created on 11/22/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class SimpleTimeEditorDemoHandler implements UIHandler<SimpleTimeEditorDemo> { - @Override - public void beforeInit(SimpleTimeEditorDemo ui) { - - } - - @Override - public void afterInit(SimpleTimeEditorDemo ui) { - // init time editor - ui.editor.init(); - - // set current time in model - ui.demoModel.setTime(new java.util.Date()); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemoModel.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemoModel.java deleted file mode 100644 index 8e5789a..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemoModel.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.demo.component.jaxx.editor; - -import jaxx.runtime.swing.editor.SimpleTimeEditor; -import org.jdesktop.beans.AbstractSerializableBean; - -import java.util.Date; - -/** - * Model of a bean using the {@link SimpleTimeEditor}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class SimpleTimeEditorDemoModel extends AbstractSerializableBean { - - public static final String TIME_PROPERTY = "time"; - - private static final long serialVersionUID = 1L; - - protected Date time; - - public Date getTime() { - return time; - } - - public void setTime(Date time) { - Date old = this.time; - this.time = time; - firePropertyChange(TIME_PROPERTY, old, time); - } - - -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemo.jaxx deleted file mode 100644 index ba8fd3c..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemo.jaxx +++ /dev/null @@ -1,84 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - jaxx.runtime.swing.editor.TimeEditor - static org.nuiton.i18n.I18n.t - </import> - - <!-- model --> - <jaxx.demo.component.jaxx.editor.TimeEditorDemoModel id='demoModel'/> - - <script><![CDATA[ - -void $afterCompleteSetup() { - - // init time editor - editor.init(); - - // set current time in model - demoModel.setTime(new java.util.Date()); -} -]]> - </script> - - - <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> - <row> - <cell> - <JPanel id="configPanel"> - - <JPanel layout='{new BorderLayout()}'> - - <JLabel id='labelConfigLabel' constraints='BorderLayout.WEST'/> - - <JTextField id='labelConfig' constraints='BorderLayout.CENTER'/> - </JPanel> - - </JPanel> - </cell> - </row> - <row> - <cell> - <jaxx.runtime.swing.editor.TimeEditor id='editor' constructorParams='this' property='time' - border='{new TitledBorder(t("jaxxdemo.timeeditor.editor"))}' - bean='{demoModel}' - date="{demoModel.getTime()}" - label="{labelConfig.getText()}"/> - </cell> - </row> - <row> - <cell> - - <JPanel id='resultPane'> - - <JLabel constraints='BorderLayout.CENTER' - text='{t("jaxxdemo.timeeditor.value", demoModel.getTime())}'/> - </JPanel> - - </cell> - </row> - </Table> - - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemoModel.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemoModel.java deleted file mode 100644 index ac58cac..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemoModel.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.demo.component.jaxx.editor; - -import jaxx.runtime.swing.editor.TimeEditor; -import org.jdesktop.beans.AbstractSerializableBean; - -import java.util.Date; - -/** - * Model of a bean using the {@link TimeEditor}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.2 - */ -public class TimeEditorDemoModel extends AbstractSerializableBean { - - public static final String TIME_PROPERTY = "time"; - - private static final long serialVersionUID = 1L; - - protected Date time; - - public Date getTime() { - return time; - } - - public void setTime(Date time) { - Date old = this.time; - this.time = time; - firePropertyChange(TIME_PROPERTY, old, time); - } - -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/gis/CoordinateDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/gis/CoordinateDemo.jaxx deleted file mode 100644 index 84ec02a..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/gis/CoordinateDemo.jaxx +++ /dev/null @@ -1,97 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - jaxx.runtime.swing.editor.NumberEditor - jaxx.runtime.swing.editor.gis.DmsCoordinate - jaxx.runtime.swing.editor.gis.DmsCoordinateEditor - jaxx.runtime.swing.editor.gis.DmdCoordinate - jaxx.runtime.swing.editor.gis.DmdCoordinateEditor - </import> - - <!-- model --> - <CoordinateDemoModel id='model'/> - - <!-- internal editor models --> - <DmsCoordinate id='latitudeDms'/> - <DmdCoordinate id='latitudeDmd'/> - <Float id='latitudeDd' javaBean='null'/> - <DmsCoordinate id='longitudeDms'/> - <DmdCoordinate id='longitudeDmd'/> - <Float id='longitudeDd' javaBean='null'/> - - <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> - <row> - <cell> - <JPanel id='config' layout='{new GridLayout(1,0)}'> - - <JPanel id='configLatitude' layout='{new GridLayout(0,1)}'> - <JCheckBox id='latitudeShowReset'/> - <JRadioButton id='latitudeUseDms' - onActionPerformed='handler.useLatitudeDmsEditor()'/> - <JRadioButton id='latitudeUseDmd' - onActionPerformed='handler.useLatitudeDmdEditor()'/> - <JRadioButton id='latitudeUseDd' - onActionPerformed='handler.useLatitudeDdEditor()'/> - </JPanel> - <JPanel id='configLongitude' layout='{new GridLayout(0,1)}'> - <JCheckBox id='longitudeShowReset'/> - <JRadioButton id='longitudeUseDms' - onActionPerformed='handler.useLongitudeDmsEditor()'/> - <JRadioButton id='longitudeUseDmd' - onActionPerformed='handler.useLongitudeDmdEditor()'/> - <JRadioButton id='longitudeUseDd' - onActionPerformed='handler.useLongitudeDdEditor()'/> - </JPanel> - </JPanel> - </cell> - </row> - <row> - <cell> - <JPanel layout='{new GridLayout(1,0)}'> - <JPanel id='latitudePane' layout='{new GridLayout(0,1)}'> - <DmsCoordinateEditor id='latitudeDmsEditor' constructorParams='this'/> - <DmdCoordinateEditor id='latitudeDmdEditor' constructorParams='this'/> - <NumberEditor id='latitudeDdEditor' constructorParams='this'/> - </JPanel> - <JPanel id='longitudePane' layout='{new GridLayout(0,1)}'> - <DmsCoordinateEditor id='longitudeDmsEditor' - constructorParams='this'/> - <DmdCoordinateEditor id='longitudeDmdEditor' - constructorParams='this'/> - <NumberEditor id='longitudeDdEditor' constructorParams='this'/> - </JPanel> - </JPanel> - </cell> - </row> - <row> - <cell> - <JPanel id='result' layout='{new GridLayout(0,1)}'> - <JLabel id='resultLatitude'/> - <JLabel id='resultLongitude'/> - - </JPanel> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/gis/CoordinateDemoHandler.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/gis/CoordinateDemoHandler.java deleted file mode 100644 index 34c4b51..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/gis/CoordinateDemoHandler.java +++ /dev/null @@ -1,175 +0,0 @@ -package jaxx.demo.component.jaxx.editor.gis; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.spi.UIHandler; -import jaxx.runtime.swing.editor.gis.DmdCoordinate; -import jaxx.runtime.swing.editor.gis.DmsCoordinate; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -import static org.nuiton.i18n.I18n.t; - -/** - * Created on 11/26/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class CoordinateDemoHandler implements UIHandler<CoordinateDemo> { - - /** Logger. */ - private static final Log log = - LogFactory.getLog(CoordinateDemoHandler.class); - - private CoordinateDemo ui; - - @Override - public void beforeInit(CoordinateDemo ui) { - if (log.isInfoEnabled()) { - log.info("BeforeInit " + ui.getName()); - } - this.ui = ui; - } - - @Override - public void afterInit(CoordinateDemo ui) { - - if (log.isInfoEnabled()) { - log.info("AfterInit " + ui.getName()); - } - - ui.getLatitudeDmsEditor().init(false); - ui.getLatitudeDmdEditor().init(false); - ui.getLatitudeDdEditor().init(); - ui.getLongitudeDmsEditor().init(true); - ui.getLongitudeDmdEditor().init(true); - ui.getLongitudeDdEditor().init(); - - ui.getLatitudeDms().addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - DmsCoordinate source = (DmsCoordinate) evt.getSource(); - getModel().setLatitude(source.toDecimal()); - } - }); - ui.getLatitudeDmd().addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - DmdCoordinate source = (DmdCoordinate) evt.getSource(); - getModel().setLatitude(source.toDecimal()); - } - }); - - ui.addPropertyChangeListener("latitudeDd", new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - Float source = (Float) evt.getNewValue(); - getModel().setLatitude(source); - } - }); - - ui.getLongitudeDms().addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - DmsCoordinate source = (DmsCoordinate) evt.getSource(); - getModel().setLongitude(source.toDecimal()); - } - }); - ui.getLongitudeDmd().addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - DmdCoordinate source = (DmdCoordinate) evt.getSource(); - getModel().setLongitude(source.toDecimal()); - } - }); - - ui.addPropertyChangeListener("longitudeDd", new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - Float source = (Float) evt.getNewValue(); - getModel().setLongitude(source); - } - }); - - useLatitudeDmsEditor(); - useLongitudeDmsEditor(); - } - - public void useLatitudeDmsEditor() { - ui.getLatitudeDmsEditor().setValue(DmsCoordinate.valueOf(getModel().getLatitude())); - ui.getLatitudeDmsEditor().setEnabled(true); - ui.getLatitudeDmdEditor().setEnabled(false); - ui.getLatitudeDdEditor().setEnabled(false); - } - - public void useLatitudeDmdEditor() { - ui.getLatitudeDmdEditor().setValue(DmdCoordinate.valueOf(getModel().getLatitude())); - ui.getLatitudeDmsEditor().setEnabled(false); - ui.getLatitudeDmdEditor().setEnabled(true); - ui.getLatitudeDdEditor().setEnabled(false); - } - - public void useLatitudeDdEditor() { - ui.getLatitudeDdEditor().setModel(getModel().getLatitude()); - ui.getLatitudeDmsEditor().setEnabled(false); - ui.getLatitudeDmdEditor().setEnabled(false); - ui.getLatitudeDdEditor().setEnabled(true); - } - - public void useLongitudeDmsEditor() { - ui.getLongitudeDmsEditor().setValue(DmsCoordinate.valueOf(getModel().getLongitude())); - ui.getLongitudeDmsEditor().setEnabled(true); - ui.getLongitudeDmdEditor().setEnabled(false); - ui.getLongitudeDdEditor().setEnabled(false); - } - - public void useLongitudeDmdEditor() { - ui.getLongitudeDmdEditor().setValue(DmdCoordinate.valueOf(getModel().getLongitude())); - ui.getLongitudeDmsEditor().setEnabled(false); - ui.getLongitudeDmdEditor().setEnabled(true); - ui.getLongitudeDdEditor().setEnabled(false); - } - - public void useLongitudeDdEditor() { - ui.getLongitudeDdEditor().setModel(getModel().getLongitude()); - ui.getLongitudeDmsEditor().setEnabled(false); - ui.getLongitudeDmdEditor().setEnabled(false); - ui.getLongitudeDdEditor().setEnabled(true); - } - - public String getLatitudeText(Float latitude) { - return t("jaxxdemo.coordinate.result.latitude", latitude); - } - - public String getLongitudeText(Float longitude) { - return t("jaxxdemo.coordinate.result.longitude", longitude); - } - - protected CoordinateDemoModel getModel() { - return ui.getModel(); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/gis/CoordinateDemoModel.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/gis/CoordinateDemoModel.java deleted file mode 100644 index 5d56865..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/gis/CoordinateDemoModel.java +++ /dev/null @@ -1,64 +0,0 @@ -package jaxx.demo.component.jaxx.editor.gis; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.jdesktop.beans.AbstractSerializableBean; - -/** - * Created on 11/26/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class CoordinateDemoModel extends AbstractSerializableBean { - - public static final String PROPERTY_LONGITUDE = "longitude"; - - public static final String PROPERTY_LATITUDE = "latitude"; - - private static final long serialVersionUID = 1L; - - protected Float latitude; - - protected Float longitude; - - public Float getLongitude() { - return longitude; - } - - public void setLongitude(Float longitude) { - Object oldValue = getLongitude(); - this.longitude = longitude; - firePropertyChange(PROPERTY_LONGITUDE, oldValue, longitude); - } - - public Float getLatitude() { - return latitude; - } - - public void setLatitude(Float latitude) { - Object oldValue = getLatitude(); - this.latitude = latitude; - firePropertyChange(PROPERTY_LATITUDE, oldValue, latitude); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemo.jaxx deleted file mode 100644 index 4bb8a86..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemo.jaxx +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - org.nuiton.jaxx.widgets.datetime.DateTimeEditor - </import> - - <DateTimeEditorDemoModel id='model' initializer='getContextValue(DateTimeEditorDemoModel.class)'/> - - <JPanel layout='{new BorderLayout()}' constraints='BorderLayout.NORTH'> - <Table id="configPanel" constraints='BorderLayout.NORTH'> - <row> - <cell anchor='west'> - <JLabel id='labelConfigLabel'/> - </cell> - <cell fill='both' weightx='1'> - <JTextField id='labelConfig'/> - </cell> - </row> - <row> - <cell> - <JLabel id='formatConfigLabel'/> - </cell> - <cell fill='both' weightx='1'> - <JTextField id='formatConfig'/> - </cell> - </row> - <row> - <cell anchor='west' columns="2"> - <JCheckBox id='dateEditableButton'/> - </cell> - </row> - <row> - <cell anchor='west' columns="2"> - <JCheckBox id='timeEditableButton'/> - </cell> - </row> - <row> - <cell anchor='west' columns="2"> - <JCheckBox id='enableButton'/> - </cell> - </row> - </Table> - <DateTimeEditor id='editor' constructorParams='this' constraints='BorderLayout.CENTER'/> - </JPanel> - - <JPanel id='result' layout='{new GridLayout(0,2)}' constraints='BorderLayout.CENTER'> - <JLabel id='resultDateLabel'/> - <JTextField id='resultDate'/> - <JLabel id='resultDayDateLabel'/> - <JTextField id='resultDayDate'/> - <JLabel id='resultTimeDateLabel'/> - <JTextField id='resultTimeDate'/> - </JPanel> - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemoHandler.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemoHandler.java deleted file mode 100644 index 8ff7746..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemoHandler.java +++ /dev/null @@ -1,80 +0,0 @@ -package jaxx.demo.component.jaxx.widgets.datetime; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.spi.UIHandler; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; - -/** - * Created on 9/9/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.12 - */ -public class DateTimeEditorDemoHandler implements UIHandler<DateTimeEditorDemo> { - - protected final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); - - protected final DateFormat dayDateFormat = new SimpleDateFormat("yyyy-MM-dd"); - - protected final DateFormat timeDateFormat = new SimpleDateFormat("HH:mm"); - - @Override - public void beforeInit(DateTimeEditorDemo ui) { - - DateTimeEditorDemoModel model = new DateTimeEditorDemoModel(); - - Date now = new Date(); - - model.setDate(now); - model.setDayDate(now); - model.setTimeDate(now); - - ui.setContextValue(model); - - } - - @Override - public void afterInit(final DateTimeEditorDemo ui) { - - // init editor - ui.getEditor().init(); - - } - - public String getDate(Date date) { - return dateFormat.format(date); - } - - public String getDayDate(Date date) { - return dayDateFormat.format(date); - } - - public String getTimeDate(Date date) { - return timeDateFormat.format(date); - } - -} \ No newline at end of file diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemoModel.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemoModel.java deleted file mode 100644 index da62607..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemoModel.java +++ /dev/null @@ -1,74 +0,0 @@ -package jaxx.demo.component.jaxx.widgets.datetime; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.jdesktop.beans.AbstractSerializableBean; - -import java.util.Date; - -/** - * Created on 9/10/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.12 - */ -public class DateTimeEditorDemoModel extends AbstractSerializableBean { - - private static final long serialVersionUID = 1L; - - protected Date date; - - protected Date dayDate; - - protected Date timeDate; - - public Date getDate() { - return date; - } - - public void setDate(Date date) { - Date oldValue = getDate(); - this.date = date; - firePropertyChange("date", oldValue, date); - } - - public Date getDayDate() { - return dayDate; - } - - public void setDayDate(Date dayDate) { - Date oldValue = getDayDate(); - this.dayDate = dayDate; - firePropertyChange("dayDate", oldValue, dayDate); - } - - public Date getTimeDate() { - return timeDate; - } - - public void setTimeDate(Date timeDate) { - Date oldValue = getTimeDate(); - this.timeDate = timeDate; - firePropertyChange("timeDate", oldValue, timeDate); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemo.jaxx deleted file mode 100644 index da5f3b0..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemo.jaxx +++ /dev/null @@ -1,54 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - org.nuiton.jaxx.widgets.datetime.TimeEditor - </import> - - <jaxx.demo.component.jaxx.widgets.datetime.TimeEditorDemoModel id='model' initializer='getContextValue(TimeEditorDemoModel.class)'/> - - <JPanel layout='{new BorderLayout()}' constraints='BorderLayout.NORTH'> - <Table id="configPanel" constraints='BorderLayout.NORTH'> - <row> - <cell anchor='west'> - <JLabel id='labelConfigLabel'/> - </cell> - <cell fill='both' weightx='1'> - <JTextField id='labelConfig'/> - </cell> - </row> - <row> - <cell anchor='west' columns="2"> - <JCheckBox id='enableButton'/> - </cell> - </row> - </Table> - <org.nuiton.jaxx.widgets.datetime.TimeEditor id='editor' constructorParams='this' constraints='BorderLayout.CENTER'/> - </JPanel> - - <JPanel id='result' layout='{new GridLayout(0,2)}' constraints='BorderLayout.CENTER'> - <JLabel id='resultTimeLabel'/> - <JTextField id='resultTime'/> - </JPanel> - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemoHandler.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemoHandler.java deleted file mode 100644 index a0ad6de..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemoHandler.java +++ /dev/null @@ -1,66 +0,0 @@ -package jaxx.demo.component.jaxx.widgets.datetime; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.spi.UIHandler; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; - -/** - * Created on 11/30/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.18 - */ -public class TimeEditorDemoHandler implements UIHandler<TimeEditorDemo> { - - protected final DateFormat timeFormat = new SimpleDateFormat("HH:mm"); - - @Override - public void beforeInit(TimeEditorDemo ui) { - - TimeEditorDemoModel model = new TimeEditorDemoModel(); - - Date now = new Date(); - - model.setTime(now); - - ui.setContextValue(model); - - } - - @Override - public void afterInit(final TimeEditorDemo ui) { - - // init editor - ui.getEditor().init(); - - } - - public String getTime(Date date) { - return timeFormat.format(date); - } - -} \ No newline at end of file diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemoModel.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemoModel.java deleted file mode 100644 index b6834bf..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemoModel.java +++ /dev/null @@ -1,50 +0,0 @@ -package jaxx.demo.component.jaxx.widgets.datetime; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.jdesktop.beans.AbstractSerializableBean; - -import java.util.Date; - -/** - * Created on 11/30/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.18 - */ -public class TimeEditorDemoModel extends AbstractSerializableBean { - - private static final long serialVersionUID = 1L; - - protected Date time; - - public Date getTime() { - return time; - } - - public void setTime(Date time) { - Date oldValue = getTime(); - this.time = time; - firePropertyChange("time", oldValue, time); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemo.jaxx deleted file mode 100644 index 5fa3d0d..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemo.jaxx +++ /dev/null @@ -1,55 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - org.nuiton.jaxx.widgets.gis.absolute.CoordinatesEditor - </import> - - <CoordinatesEditorDemoModel id='model' initializer='getContextValue(CoordinatesEditorDemoModel.class)'/> - - <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> - <row> - <cell> - <JPanel id='config' layout='{new GridLayout(0,1)}'> - <JCheckBox id='showReset'/> - <JCheckBox id='enableButton'/> - <JCheckBox id='displayZeroWhenNull'/> - </JPanel> - </cell> - </row> - <row> - <cell> - <CoordinatesEditor id='editor'/> - </cell> - </row> - <row> - <cell> - <JPanel id='result' layout='{new GridLayout(0,1)}'> - <JLabel id='resultQuadrant'/> - <JLabel id='resultLatitude'/> - <JLabel id='resultLongitude'/> - </JPanel> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemoHandler.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemoHandler.java deleted file mode 100644 index 3bbb968..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemoHandler.java +++ /dev/null @@ -1,68 +0,0 @@ -package jaxx.demo.component.jaxx.widgets.gis; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.spi.UIHandler; - -import static org.nuiton.i18n.I18n.t; - -/** - * Created on 9/1/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.12 - */ -public class CoordinatesEditorDemoHandler implements UIHandler<CoordinatesEditorDemo> { - - @Override - public void beforeInit(CoordinatesEditorDemo ui) { - - CoordinatesEditorDemoModel model = new CoordinatesEditorDemoModel(); - model.setLatitude(-1.5261505f); - model.setLongitude(47.1963537f); - model.setQuadrant(1); - - ui.setContextValue(model); - - } - - @Override - public void afterInit(final CoordinatesEditorDemo ui) { - - ui.getEditor().init(); - - } - - public String getQuadrant(Integer quadrant) { - return t("jaxxdemo.coordinate.result.quadrant", quadrant); - } - - public String getLatitude(Float latitude) { - return t("jaxxdemo.coordinate.result.latitude", latitude); - } - - public String getLongitude(Float longitude) { - return t("jaxxdemo.coordinate.result.longitude", longitude); - } - -} \ No newline at end of file diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemoModel.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemoModel.java deleted file mode 100644 index d420326..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemoModel.java +++ /dev/null @@ -1,72 +0,0 @@ -package jaxx.demo.component.jaxx.widgets.gis; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.jdesktop.beans.AbstractSerializableBean; - -/** - * Created on 9/3/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.12 - */ -public class CoordinatesEditorDemoModel extends AbstractSerializableBean { - - private static final long serialVersionUID = 1L; - - protected Integer quadrant; - - protected Float latitude; - - protected Float longitude; - - public Integer getQuadrant() { - return quadrant; - } - - public void setQuadrant(Integer quadrant) { - Object oldValue = getQuadrant(); - this.quadrant = quadrant; - firePropertyChange("quadrant", oldValue, quadrant); - } - - public Float getLatitude() { - return latitude; - } - - public void setLatitude(Float latitude) { - Object oldValue = getLatitude(); - this.latitude = latitude; - firePropertyChange("latitude", oldValue, latitude); - } - - public Float getLongitude() { - return longitude; - } - - public void setLongitude(Float longitude) { - Object oldValue = getLongitude(); - this.longitude = longitude; - firePropertyChange("longitude", oldValue, longitude); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemo.jaxx deleted file mode 100644 index 0ec83fb..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemo.jaxx +++ /dev/null @@ -1,111 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - org.nuiton.jaxx.widgets.number.NumberEditor - - static org.nuiton.i18n.I18n.t - </import> - - <jaxx.demo.component.jaxx.widgets.number.NumberEditorDemoModel id='model' initializer="getContextValue(NumberEditorDemoModel.class)"/> - - <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> - <!-- config --> - <row> - <cell> - <Table id='numberEditorConfigurationPanel' insets='1' fill='both' weightx='1'> - <row> - <cell columns="3"> - <JCheckBox id='showPopupButton'/> - </cell> - </row> - <row> - <cell columns="3"> - <JCheckBox id='showResetButton'/> - </cell> - </row> - <row> - <cell columns="3"> - <JCheckBox id='autoPopupButton'/> - </cell> - </row> - <row> - <cell anchor="west"> - <JLabel id='integerNumberConfig'/> - </cell> - <cell weightx="1" fill="both"> - <JTextField id='integerNumberPattern' text='{"-?\\d{0,3}"}'/> - </cell> - <cell anchor="east"> - <JCheckBox id='integerNumberEnabled'/> - </cell> - </row> - <row> - <cell anchor="west"> - <JLabel id='floatNumberConfig'/> - </cell> - <cell weightx="1" fill="both"> - <JTextField id='floatNumberPattern' text='{"\\d{0,1}.\\d{0,2}"}'/> - </cell> - <cell anchor="east"> - <JCheckBox id='floatNumberEnabled'/> - </cell> - </row> - <row> - <cell anchor="west"> - <JLabel id='doubleNumberConfig'/> - </cell> - <cell weightx="1" fill="both"> - <JTextField id='doubleNumberPattern' text='{"-?\\d{0,4}.\\d{0,6}"}'/> - </cell> - <cell anchor="east"> - <JCheckBox id='doubleNumberEnabled'/> - </cell> - </row> - </Table> - </cell> - </row> - <!-- editors --> - <row> - <cell> - <JPanel layout="{new GridLayout()}"> - <org.nuiton.jaxx.widgets.number.NumberEditor id='integerEditor' constructorParams='this'/> - <org.nuiton.jaxx.widgets.number.NumberEditor id='floatEditor' constructorParams='this'/> - <org.nuiton.jaxx.widgets.number.NumberEditor id='doubleEditor' constructorParams='this'/> - </JPanel> - </cell> - </row> - <!-- result --> - <row> - <cell> - <JPanel id='resultPanel' layout='{new GridLayout(0,1)}'> - <JLabel id='resultInteger'/> - <JLabel id='resultFloat'/> - <JLabel id='resultDouble'/> - </JPanel> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> - diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemoHandler.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemoHandler.java deleted file mode 100644 index c053d2d..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemoHandler.java +++ /dev/null @@ -1,56 +0,0 @@ -package jaxx.demo.component.jaxx.widgets.number; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.spi.UIHandler; - -/** - * Created on 11/23/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since XXX - */ -public class NumberEditorDemoHandler implements UIHandler<NumberEditorDemo> { - - @Override - public void beforeInit(NumberEditorDemo ui) { - - NumberEditorDemoModel model = new NumberEditorDemoModel(); - model.setIntegerNumber(10); - model.setFloatNumber(-10.10f); - model.setDoubleNumber(-0.0001d); - - ui.setContextValue(model); - - } - - @Override - public void afterInit(NumberEditorDemo ui) { - - ui.integerEditor.init(); - ui.floatEditor.init(); - ui.doubleEditor.init(); - - } - -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemoModel.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemoModel.java deleted file mode 100644 index b1c80c0..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemoModel.java +++ /dev/null @@ -1,72 +0,0 @@ -package jaxx.demo.component.jaxx.widgets.number; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.jdesktop.beans.AbstractSerializableBean; - -/** - * Created on 11/23/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.17 - */ -public class NumberEditorDemoModel extends AbstractSerializableBean { - - private static final long serialVersionUID = 1L; - - protected Integer integerNumber; - - protected Float floatNumber; - - protected Double doubleNumber; - - public Integer getIntegerNumber() { - return integerNumber; - } - - public void setIntegerNumber(Integer integerNumber) { - Number oldValue = getIntegerNumber(); - this.integerNumber = integerNumber; - firePropertyChange("integerNumber", oldValue, integerNumber); - } - - public Float getFloatNumber() { - return floatNumber; - } - - public void setFloatNumber(Float floatNumber) { - Number oldValue = getFloatNumber(); - this.floatNumber = floatNumber; - firePropertyChange("floatNumber", oldValue, floatNumber); - } - - public Double getDoubleNumber() { - return doubleNumber; - } - - public void setDoubleNumber(Double doubleNumber) { - Number oldValue = getDoubleNumber(); - this.doubleNumber = doubleNumber; - firePropertyChange("doubleNumber", oldValue, doubleNumber); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemo.jaxx deleted file mode 100644 index 94be1e83..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemo.jaxx +++ /dev/null @@ -1,55 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - jaxx.demo.entities.People - org.nuiton.jaxx.widgets.select.FilterableDoubleList - </import> - - <FilterableDoubleListDemoModel id="model" initializer='getContextValue(FilterableDoubleListDemoModel.class)'/> - - <Table fill='both'> - <row> - <cell> - <JPanel id='configurationPanel' layout='{new GridLayout(0,1)}'> - <JCheckBox id='filterableButton'/> - <JCheckBox id='highlightFilterTextButton'/> - <JCheckBox id='showResetButton'/> - <JCheckBox id='showDecoratorButton'/> - <JCheckBox id='enableButton'/> - </JPanel> - </cell> - </row> - <row> - <cell weighty='0.5' weightx='1'> - <FilterableDoubleList id='doubleList' genericType='People'/> - </cell> - </row> - <row> - <cell weighty='0.5' weightx='1'> - <JTextPane id="result"/> - </cell> - </row> - </Table> - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemoHandler.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemoHandler.java deleted file mode 100644 index c6edefc..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemoHandler.java +++ /dev/null @@ -1,98 +0,0 @@ -package jaxx.demo.component.jaxx.widgets.select; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.demo.entities.DemoDataProvider; -import jaxx.demo.entities.DemoDecoratorProvider; -import jaxx.demo.entities.People; -import jaxx.runtime.spi.UIHandler; -import org.nuiton.decorator.JXPathDecorator; -import org.nuiton.jaxx.widgets.select.FilterableDoubleList; - -import java.util.List; - -import static org.nuiton.i18n.I18n.t; - -/** - * Created on 11/28/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.18 - */ -public class FilterableDoubleListDemoHandler implements UIHandler<FilterableDoubleListDemo> { - - private JXPathDecorator<People> decorator; - - @Override - public void beforeInit(FilterableDoubleListDemo ui) { - - decorator = (JXPathDecorator<People>) new DemoDecoratorProvider().getDecoratorByType(People.class); - - FilterableDoubleListDemoModel model = new FilterableDoubleListDemoModel(); - ui.setContextValue(model); - - } - - @Override - public void afterInit(final FilterableDoubleListDemo ui) { - - FilterableDoubleList<People> doubleList = ui.getDoubleList(); - - DemoDataProvider demoDataProvider = new DemoDataProvider(); - - List<People> data = demoDataProvider.getPeoples(); - List<People> selected = data.subList(0, 1); - - doubleList.init(decorator, data, selected); - - } - - public String updateResultText(List<People> selected) { - - StringBuilder builder = new StringBuilder(); - if (selected == null || selected.isEmpty()) { - - builder.append(t("jaxxdemo.beandoublelistdemo.noselected")); - - } else { - - builder.append(t("jaxxdemo.beandoublelistdemo.selected")); - builder.append("<ul>"); - - for (People people : selected) { - - String peopleStr = decorator.toString(people); - builder.append("<li>"); - builder.append(peopleStr); - builder.append("</li>"); - - } - - builder.append("</ul>"); - - } - - return builder.toString(); - - } -} \ No newline at end of file diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemoModel.java b/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemoModel.java deleted file mode 100644 index a0fb5ee..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemoModel.java +++ /dev/null @@ -1,52 +0,0 @@ -package jaxx.demo.component.jaxx.widgets.select; - -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.demo.entities.People; -import org.jdesktop.beans.AbstractSerializableBean; - -import java.util.List; - -/** - * Created on 11/28/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.18 - */ -public class FilterableDoubleListDemoModel extends AbstractSerializableBean { - - private static final long serialVersionUID = 1L; - - public static final String PROPERTY_SELECTED = "selected"; - - List<People> selected; - - public List<People> getSelected() { - return selected; - } - - public void setSelected(List<People> selected) { - this.selected = selected; - firePropertyChange(PROPERTY_SELECTED, null, selected); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/HidorButtonDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/HidorButtonDemo.jaxx deleted file mode 100644 index c016fa5..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/HidorButtonDemo.jaxx +++ /dev/null @@ -1,42 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel layout='{new GridLayout(0,1)}'> - - <HBox horizontalAlignment='center' verticalAlignment='middle'> - - <jaxx.runtime.swing.HidorButton target='{hidor1}' showText="show label1" - hideText='hide label1' - targetVisible='{true}'/> - - <JLabel id='hidor1' text='Label 1'/> - </HBox> - <HBox horizontalAlignment='center' verticalAlignment='middle'> - - <jaxx.runtime.swing.HidorButton target='{hidor2}' showText="show label2" - hideText='hide label2' - targetVisible='{false}'/> - - <JLabel id='hidor2' text='Label 2'/> - </HBox> - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JButtonDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JButtonDemo.jaxx deleted file mode 100644 index c5d013d..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JButtonDemo.jaxx +++ /dev/null @@ -1,61 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel id='topDemoPanel' decorator='help'> - <style> - JButton.fancy { - foreground: blue; - font-face: Arial; - font-size: 18; - } - - JButton.fancy:mouseover { - foreground: red; - font-style: italic; - } - </style> - - <script> - public void buttonClicked(JButton button) { - JOptionPane.showMessageDialog(this, button.getText() + " clicked!", - "onActionPerformed", - JOptionPane.INFORMATION_MESSAGE); - } - </script> - - <import> - javax.swing.JOptionPane - java.awt.Color - </import> - - <String id='helpDefaultId' initializer='"ui.component.swing.buttons.JButtonDemo"'/> - - <javax.swing.ImageIcon id='pencil' - constructorParams='getClass().getResource("/jaxx/demo/images/pencil_black.gif")'/> - - <VBox horizontalAlignment='center' verticalAlignment='middle'> - <JButton id='simpleButon' text='Simple Button' - onActionPerformed='buttonClicked((JButton) event.getSource())'/> - <JButton id='fancyButon' text='Fancy Button' styleClass='fancy' icon='{pencil}' - onActionPerformed='buttonClicked((JButton) event.getSource())'/> - </VBox> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JCheckBoxDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JCheckBoxDemo.jaxx deleted file mode 100644 index 273f5c3..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JCheckBoxDemo.jaxx +++ /dev/null @@ -1,62 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel> - <import> - java.awt.Font - </import> - <script><![CDATA[ - public String getText(boolean bold, boolean italic, boolean underline) { - String text ="Sample Text"; - if (bold) - text = "<b>" + text + "</b>"; - if (italic) - text = "<i>" + text + "</i>"; - if (underline) - text = "<u>" + text + "</u>"; - return "<html>" + text; - } - ]]></script> - <VBox horizontalAlignment='center' verticalAlignment='middle'> - <Table anchor='west'> - <row> - <cell> - <JCheckBox id='bold' text='Bold' mnemonic='B'/> - </cell> - <cell rows='3'> - <JLabel font='{new Font("Arial", 0, 18)}' - text='{getText(bold.isSelected(), italic.isSelected(), underline.isSelected())}'/> - </cell> - </row> - <row> - <cell> - <JCheckBox id='italic' text='Italic' mnemonic='I'/> - </cell> - </row> - <row> - <cell> - <JCheckBox id='underline' text='Underline' mnemonic='U'/> - </cell> - </row> - </Table> - </VBox> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JComboBoxDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JComboBoxDemo.jaxx deleted file mode 100644 index 0daf4c2..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JComboBoxDemo.jaxx +++ /dev/null @@ -1,70 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - - -<jaxx.demo.DemoPanel> - <import> - javax.swing.DefaultComboBoxModel - static org.nuiton.i18n.I18n.n - </import> - - <script><![CDATA[ -private void $afterCompleteSetup() { - jaxxComboBox.setSelectedIndex(0); -} -]]> - </script> - <Table> - <row> - <cell> - <JLabel text='Button label:'/> - </cell> - - <cell> - <JAXXComboBox id='jaxxComboBox' editable='true'> - <item value='{t("OK")}' selected='true'/> - <item value='{t("Cancel")}'/> - <item value='{t("Help")}'/> - </JAXXComboBox> - </cell> - - <cell> - <JButton text='{String.valueOf(jaxxComboBox.getSelectedItem())}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Button label:'/> - </cell> - - <cell> - <JComboBox id='comboBox' - editable='true' - model='{new DefaultComboBoxModel(new Object[]{n("OK"),n("Cancel"),n("Help")})}'/> - </cell> - - <cell> - <JButton text='{comboBox.getSelectedItem()+""}'/> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JDialogDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JDialogDemo.jaxx deleted file mode 100644 index c6cf5e9..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JDialogDemo.jaxx +++ /dev/null @@ -1,110 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel> - <import> - javax.swing.JRootPane - javax.swing.JComponent - javax.swing.KeyStroke - </import> - <script> - String username; - String password; - - private class OKAction extends javax.swing.AbstractAction { - public OKAction() { - putValue(NAME, "OK"); - } - - public void actionPerformed(ActionEvent e) { - username = usernameField.getText(); - password = new String(passwordField.getPassword()); - dialog.dispose(); - } - } - - - private class CancelAction extends javax.swing.AbstractAction { - public CancelAction() { - putValue(NAME, "Cancel"); - } - - - public void actionPerformed(ActionEvent e) { - dialog.dispose(); - } - } - { - JRootPane rootPane = dialog.getRootPane(); - rootPane.setDefaultButton(ok); - rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ESCAPE"), - "cancel"); - rootPane.getActionMap().put("cancel", new CancelAction()); - } - </script> - - <VBox horizontalAlignment='center' verticalAlignment='middle'> - <JButton text='Show password dialog' - onActionPerformed='dialog.setVisible(true)'/> - <VBox> - <JLabel text='{username != null ? "Username: " + username : ""}'/> - <JLabel text='{password != null ? "Password: " + password : ""}'/> - </VBox> - </VBox> - - <JDialog title='Sign on' id='dialog' modal='true' onWindowOpened='dialog.setLocationRelativeTo(JDialogDemo.this); - passwordField.setText("");'> - <Table> - <row> - <cell> - <JLabel text='Username:' displayedMnemonic='U' - labelFor='{usernameField}'/> - </cell> - - <cell> - <JTextField id='usernameField'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Password:' displayedMnemonic='P' - labelFor='{passwordField}'/> - </cell> - - <cell> - <JPasswordField id='passwordField'/> - </cell> - </row> - - <row> - <cell columns='2'> - <JPanel layout='{new GridLayout(1, 0, 6, 6)}'> - <JButton id='ok' text='OK' action='{new OKAction()}'/> - <JButton text='Cancel' action='{new CancelAction()}'/> - </JPanel> - </cell> - </row> - </Table> - </JDialog> - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JListDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JListDemo.jaxx deleted file mode 100644 index 9778fc2..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JListDemo.jaxx +++ /dev/null @@ -1,81 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel> - <Table> - <row> - <cell> - <JLabel text='Supported Swing components:'/> - </cell> - </row> - - <row> - <cell> - <JScrollPane> - <JAXXList> - <item value='JApplet'/> - <item value='JButton'/> - <item value='JCheckBox'/> - <item value='JCheckBoxMenuItem'/> - <item value='JColorChooser'/> - <item value='JComboBox'/> - <item value='JDesktopPane'/> - <item value='JDialog'/> - <item value='JEditorPane'/> - <item value='JFileChooser'/> - <item value='JFormattedTextField'/> - <item value='JFrame'/> - <item value='JInternalFrame'/> - <item value='JLabel'/> - <item value='JLayeredPane'/> - <item value='JList'/> - <item value='JMenu'/> - <item value='JMenuBar'/> - <item value='JMenuItem'/> - <item value='JOptionPane'/> - <item value='JPanel'/> - <item value='JPasswordField'/> - <item value='JPopupMenu'/> - <item value='JProgressBar'/> - <item value='JRadioButton'/> - <item value='JRadioButtonMenuItem'/> - <item value='JScrollBar'/> - <item value='JScrollPane'/> - <item value='JSeparator'/> - <item value='JSlider'/> - <item value='JSpinner'/> - <item value='JSplitPane'/> - <item value='JTabbedPane'/> - <item value='JTable'/> - <item value='JTextArea'/> - <item value='JTextField'/> - <item value='JTextPane'/> - <item value='JToggleButton'/> - <item value='JToolBar'/> - <item value='JTree'/> - <item value='JWindow'/> - </JAXXList> - </JScrollPane> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JMenuItemDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JMenuItemDemo.jaxx deleted file mode 100644 index 4da75f2..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JMenuItemDemo.jaxx +++ /dev/null @@ -1,49 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel> - <import> - javax.swing.JOptionPane - </import> - - <script> - void $afterCompleteSetup(){} - </script> - - <JDesktopPane width='350' height='400' background='{null}'> - <JInternalFrame title='JMenu demo' width='300' height='250' - resizable='true'> - <JMenuBar id='menuBar'> - <JMenu text='Demo'> - <JMenuItem text='Message Box' - onActionPerformed='JOptionPane.showMessageDialog(this, "Menu item clicked")'/> - </JMenu> - </JMenuBar> - - <JPanel id='framePanel'> - <JLabel text='JMenu demo' id='demoMessage' - horizontalAlignment='center'/> - </JPanel> - </JInternalFrame> - </JDesktopPane> - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JPasswordFieldDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JPasswordFieldDemo.jaxx deleted file mode 100644 index 20ea025..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JPasswordFieldDemo.jaxx +++ /dev/null @@ -1,32 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel> - <VBox horizontalAlignment='center' verticalAlignment='middle'> - <HBox> - <JLabel text='Password:' displayedMnemonic='P' labelFor='{password}'/> - <JPasswordField id='password'/> - </HBox> - - <JLabel text='You entered: {new String(password.getPassword())}'/> - </VBox> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JProgressBarDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JProgressBarDemo.jaxx deleted file mode 100644 index 9d59cdf..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JProgressBarDemo.jaxx +++ /dev/null @@ -1,120 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - <import> - java.awt.Color - javax.swing.Timer - javax.swing.UIManager - </import> - - <Integer id='red' javaBean='0'/> - <Integer id='green' javaBean='0'/> - <Integer id='blue' javaBean='0'/> - <Integer id='speed' initializer='2'/> - <Integer id='redDirection' initializer='1'/> - <Integer id='greenDirection' initializer='1'/> - <Integer id='blueDirection' initializer='1'/> - <Timer id='redTimer' constructorParams='5, null' - onActionPerformed='changeRedValue()'/> - <Timer id='greenTimer' constructorParams='50, null' - onActionPerformed='changeGreenValue()'/> - <Timer id='blueTimer' constructorParams='500, null' - onActionPerformed='changeBlueValue()'/> - - - <script><![CDATA[ -void startTimers() { - redTimer.start(); - greenTimer.start(); - blueTimer.start(); -} - -void stopTimers() { - redTimer.stop(); - greenTimer.stop(); - blueTimer.stop(); -} - -void $afterCompleteSetup() { - startTimers(); -} - -protected void changeRedValue() { - setRed(Math.max(0, Math.min(255, red + speed * redDirection))); - if (red == 0 || red == 255) { - redDirection = -redDirection; - } -} -protected void changeGreenValue() { - setGreen(Math.max(0, Math.min(255, green + speed * greenDirection))); - if (green == 0 || green == 255) { - greenDirection = -greenDirection; - } -} -protected void changeBlueValue() { - setBlue(Math.max(0, Math.min(255, blue + speed * blueDirection))); - if (blue == 0 || blue == 255) { - blueDirection = -blueDirection; - } -} - ]]></script> - - <Table insets='6' constraints='BorderLayout.CENTER'> - <row> - <cell columns='3'> - <JLabel text='Welcome to the JAXX framework!' - font='{UIManager.getFont("Label.font").deriveFont(18f)}' - foreground='{new Color(getRed(), getGreen(), getBlue())}'/> - </cell> - </row> - <row> - <cell columns='3' fill='horizontal'> - <JProgressBar id='redProgressBar' - foreground='{new Color(getRed(), 0, 0)}' - value='{getRed()}' maximum='255'/> - </cell> - </row> - <row> - <cell columns='3' fill='horizontal'> - <JProgressBar id='greenProgressBar' - foreground='{new Color(0, getGreen(), 0)}' - value='{getGreen()}' maximum='255'/> - </cell> - </row> - <row> - <cell columns='3' fill='horizontal'> - <JProgressBar id='blueProgressBar' - foreground='{new Color(0, 0, getBlue())}' - value='{getBlue()}' maximum='255'/> - </cell> - </row> - <row> - <cell weightx='1' anchor='east'> - <JButton text='Start' onActionPerformed='startTimers()'/> - </cell> - <cell> - <JButton text='Stop' onActionPerformed='stopTimers()'/> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JRadioButtonDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JRadioButtonDemo.jaxx deleted file mode 100644 index 633f296..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JRadioButtonDemo.jaxx +++ /dev/null @@ -1,41 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel> - <import> - javax.swing.ImageIcon - </import> - - <HBox horizontalAlignment='center' verticalAlignment='middle'> - <VBox> - <JRadioButton text='Animal' value='Lynx.jpg' buttonGroup='radioButtons' - selected='true'/> - <JRadioButton text='Vegetable' buttonGroup='radioButtons' - value='Tomato.jpg'/> - <JRadioButton text='Mineral' buttonGroup='radioButtons' - value='Amethyst.jpg'/> - </VBox> - - <JLabel - icon='{new ImageIcon(getClass().getResource("/jaxx/demo/images/" + radioButtons.getSelectedValue()))}'/> - </HBox> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSliderDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSliderDemo.jaxx deleted file mode 100644 index c5e45b7..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSliderDemo.jaxx +++ /dev/null @@ -1,39 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel> - <import> - java.awt.Color - </import> - - <HBox horizontalAlignment='center' verticalAlignment='middle'> - <VBox> - <JSlider id='red' maximum='255' value='200'/> - <JSlider id='green' maximum='255' value='180'/> - <JSlider id='blue' maximum='255' value='240'/> - </VBox> - - <JPanel border='{BorderFactory.createEtchedBorder()}' width='64' - height='64' - background='{new Color(red.getValue(), green.getValue(), blue.getValue())}'/> - </HBox> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSpinnerDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSpinnerDemo.jaxx deleted file mode 100644 index a057e24..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSpinnerDemo.jaxx +++ /dev/null @@ -1,34 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel> - - <JLabel text='Spacing:' displayedMnemonic='S' labelFor='{spinner}'/> - - <JSpinner minimum='0' maximum='50' id='spinner'/> - - <VBox spacing='{(Integer) spinner.getValue()}'> - <JLabel text='Use the spinner to'/> - <JLabel text='adjust the spacing'/> - <JLabel text='between these lines'/> - </VBox> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSplitPaneDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSplitPaneDemo.jaxx deleted file mode 100644 index c566abc..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSplitPaneDemo.jaxx +++ /dev/null @@ -1,38 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel> - <import> - javax.swing.ImageIcon - </import> - <JSplitPane> - <JScrollPane> - <JLabel - icon='{new ImageIcon(getClass().getResource("/jaxx/demo/images/Amethyst.jpg"))}'/> - </JScrollPane> - - <JScrollPane> - <JLabel - icon='{new ImageIcon(getClass().getResource("/jaxx/demo/images/Lynx.jpg"))}'/> - </JScrollPane> - </JSplitPane> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JTextAreaDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JTextAreaDemo.jaxx deleted file mode 100644 index f3f2dda..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JTextAreaDemo.jaxx +++ /dev/null @@ -1,51 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel> - <Table constraints='BorderLayout.CENTER'> - <row> - <cell> - <JLabel text='Normal text:' displayedMnemonic='N' - labelFor='{textArea}'/> - </cell> - - <cell weightx='1' fill='both' anchor='east'> - <JScrollPane> - <JTextArea id='textArea' text='Try typing some text here.'/> - </JScrollPane> - </cell> - </row> - - <row> - <cell> - <JLabel text='Upper case text:' labelFor='{upperTextArea}'/> - </cell> - - <cell weightx='1' fill='both'> - <JScrollPane> - <JTextArea id='upperTextArea' editable='false' background='{null}' - text='{textArea.getText().toUpperCase()}'/> - </JScrollPane> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JTextFieldDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JTextFieldDemo.jaxx deleted file mode 100644 index 9abd879..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JTextFieldDemo.jaxx +++ /dev/null @@ -1,45 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel> - <import> - javax.swing.JOptionPane - </import> - <Table> - <row> - <cell> - <JLabel text='Your name:' displayedMnemonic='n' labelFor='{textField}'/> - </cell> - - <cell> - <JTextField id='textField'/> - </cell> - </row> - - <row> - <cell columns='2'> - <JButton text='Greet' - onActionPerformed='JOptionPane.showMessageDialog(this, "Hello, " + textField.getText() + "!")'/> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JToggleButtonDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/component/swing/JToggleButtonDemo.jaxx deleted file mode 100644 index dae7d02..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JToggleButtonDemo.jaxx +++ /dev/null @@ -1,32 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel> - <HBox horizontalAlignment='center' verticalAlignment='middle'> - <JToggleButton text='1' id='one'/> - <JToggleButton text='2' id='two'/> - <JToggleButton text='3' id='three'/> - - <JLabel - text='Total: {(one.isSelected() ? 1 : 0) + (two.isSelected() ? 2 : 0) + (three.isSelected() ? 3 : 0)}'/> - </HBox> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/entities/AbstractDemoBean.java b/jaxx-demo/src/main/java/jaxx/demo/entities/AbstractDemoBean.java deleted file mode 100644 index a5571ef..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/entities/AbstractDemoBean.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.demo.entities; - -import org.jdesktop.beans.AbstractSerializableBean; - -import static org.nuiton.i18n.I18n.n; - -/** - * Abstract demo bean. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.2 - */ -public abstract class AbstractDemoBean extends AbstractSerializableBean { - - static { - n("jaxxdemo.common.id"); - n("jaxxdemo.common.image"); - } - - public static final String PROPERTY_ID = "id"; - - public static final String PROPERTY_IMAGE = "image"; - - private static final long serialVersionUID = 1L; - - protected String id; - - protected String image; - - public AbstractDemoBean() { - } - - protected AbstractDemoBean(String id, String image) { - this.id = id; - this.image = image; - } - - public String getId() { - return id; - } - - public String getImage() { - return image; - } - - public void setId(String id) { - String old = this.id; - this.id = id; - firePropertyChange(PROPERTY_ID, old, id); - } - - - public void setImage(String image) { - Object oldValue = this.image; - this.image = image; - firePropertyChange(PROPERTY_IMAGE, oldValue, image); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/entities/DemoDataProvider.java b/jaxx-demo/src/main/java/jaxx/demo/entities/DemoDataProvider.java deleted file mode 100644 index e853b40..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/entities/DemoDataProvider.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.entities; - -import jaxx.runtime.swing.nav.NavDataProvider; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * @author Sylvain Lletellier - * @since 2.1 - */ -public class DemoDataProvider implements NavDataProvider { - - /** Logger */ - static private final Log log = LogFactory.getLog(DemoDataProvider.class); - - protected Map<String, Movie> movies; - - protected Map<String, People> peoples; - - public DemoDataProvider() { - - movies = new HashMap<String, Movie>(); - peoples = new HashMap<String, People>(); - - if (log.isDebugEnabled()) { - log.debug("for " + this); - } - People a = new People("0", "Jack", "Black", 35, "/jaxx/demo/images/jack.jpg"); - People a2 = new People("1", "Héctor", "Jiménez", 28, "/jaxx/demo/images/hector.jpg"); - People a3 = new People("2", "Ana", "de la Reguera", 34, "/jaxx/demo/images/ana.jpg"); - People a4 = new People("3", "Jack", "Nicholson", 76, "/jaxx/demo/images/joker.jpg"); - People a5 = new People("4", "Jim", "Parsons", 30, "/jaxx/demo/images/jim.jpg"); - - Movie m = new Movie("0", "Nacho libre", 1996, "/jaxx/demo/images/nacho.jpg"); - m.addActor(a); - m.addActor(a2); - m.addActor(a3); - - Movie m2 = new Movie("1", "Nacho 2", 2009, "/jaxx/demo/images/nacho2.png"); - m2.addActor(a); - m2.addActor(a2); - - movies.put(m.getId(), m); - movies.put(m2.getId(), m2); - - peoples.put(a.getId(), a); - peoples.put(a2.getId(), a2); - peoples.put(a3.getId(), a3); - peoples.put(a4.getId(), a4); - peoples.put(a5.getId(), a5); - } - - @Override - public boolean isEnabled() { - return true; - } - - public Movie getMovie(String id) { - return movies.get(id); - } - - public People getPeople(String id) { - return peoples.get(id); - } - - public List<Movie> getMovies() { - return new ArrayList<Movie>(movies.values()); - } - - public List<People> getPeoples() { - return new ArrayList<People>(peoples.values()); - } - - public List<People> getPeoples(Movie m) { - return m.getActors(); - } - - public List<People> getPeoples(String moviesId) { - - if (log.isDebugEnabled()) { - log.debug("Get people for movie " + moviesId); - } - - return movies.get(moviesId).getActors(); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/entities/DemoDecoratorProvider.java b/jaxx-demo/src/main/java/jaxx/demo/entities/DemoDecoratorProvider.java deleted file mode 100644 index 7b25a10..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/entities/DemoDecoratorProvider.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.demo.entities; - -import org.nuiton.decorator.DecoratorProvider; - -/** - * Demo decorator provider. - * - * @author Tony Chemit - chemit@codelutin.com - * @see DecoratorProvider - * @since 2.2 - */ -public class DemoDecoratorProvider extends DecoratorProvider { - @Override - protected void loadDecorators() { - - // load movie decorator - registerMultiJXPathDecorator(Movie.class, - "${title}$s#${year}$s", "#", " - "); - - // load people decorator - registerMultiJXPathDecorator(People.class, - "${firstName}$s#${lastName}$s#${age}$s", - "#", - " - " - ); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/entities/Identity.java b/jaxx-demo/src/main/java/jaxx/demo/entities/Identity.java deleted file mode 100644 index 69b2997..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/entities/Identity.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.entities; - -import org.jdesktop.beans.AbstractSerializableBean; - -import java.io.File; - -public class Identity extends AbstractSerializableBean { - - private static final long serialVersionUID = 1L; - - protected String firstName = ""; - - protected String lastName = ""; - - protected String email = "dummy@codelutin.com"; - - protected int age = 51; - - protected File config = new File("/tmp"); - - protected File dir = new File("/tmp"); - - - public String getFirstName() { - return firstName; - } - - public String getLastName() { - return lastName; - } - - public String getEmail() { - return email; - } - - public int getAge() { - return age; - } - - public File getConfig() { - return config; - } - - public File getDir() { - return dir; - } - - public void setFirstName(String firstName) { - String oldFirstName = this.firstName; - this.firstName = firstName; - firePropertyChange("firstName", oldFirstName, firstName); - } - - public void setLastName(String lastName) { - String oldLastName = this.lastName; - this.lastName = lastName; - firePropertyChange("lastName", oldLastName, lastName); - } - - public void setEmail(String email) { - String oldEmail = this.email; - this.email = email; - firePropertyChange("email", oldEmail, email); - } - - public void setAge(int age) { - int oldAge = this.age; - this.age = age; - firePropertyChange("age", oldAge, age); - } - - public void setConfig(File config) { - File oldConfig = this.config; - this.config = config; - firePropertyChange("config", oldConfig, config); - } - - public void setDir(File dir) { - File oldDir = this.dir; - this.dir = dir; - firePropertyChange("dir", oldDir, dir); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/entities/Model.java b/jaxx-demo/src/main/java/jaxx/demo/entities/Model.java deleted file mode 100644 index 6d0f0e2..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/entities/Model.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.entities; - -import org.jdesktop.beans.AbstractSerializableBean; - -public class Model extends AbstractSerializableBean { - - private static final long serialVersionUID = 1L; - - protected String text = "text"; - - protected String text2 = "text2"; - - protected int ratio = 51; - - public String getText() { - return text; - } - - public String getText2() { - return text2; - } - - public int getRatio() { - return ratio; - } - - public void setText(String text) { - String oldText = this.text; - this.text = text; - firePropertyChange("text", oldText, text); - } - - public void setText2(String text2) { - String oldText2 = this.text2; - this.text2 = text2; - firePropertyChange("text2", oldText2, text2); - } - - public void setRatio(int ratio) { - int oldRatio = this.ratio; - this.ratio = ratio; - firePropertyChange("ratio", oldRatio, ratio); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/entities/Movie.java b/jaxx-demo/src/main/java/jaxx/demo/entities/Movie.java deleted file mode 100644 index 7fecda2..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/entities/Movie.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.entities; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -import java.util.ArrayList; -import java.util.List; - -import static org.nuiton.i18n.I18n.n; - -/** - * @author Tony Chemit - chemit@codelutin.com - * @since 1.7.2 - */ -public class Movie extends AbstractDemoBean { - - static { - n("jaxxdemo.common.movie"); - n("jaxxdemo.common.title"); - n("jaxxdemo.common.year"); - n("jaxxdemo.common.actors"); - } - - protected String title; - - protected int year; - - protected List<People> actors; - - private static final long serialVersionUID = 1L; - - private static final String PROPERTY_ACTORS = "actors"; - - private static final String PROPERTY_TITLE = "title"; - - private static final String PROPERTY_YEAR = "year"; - - private static final String PROPERTY_IMAGE = "image"; - - public Movie(String id, String title, int year, String image) { - super(id, image); - this.title = title; - this.year = year; - actors = new ArrayList<People>(); - } - - public Movie() { - actors = new ArrayList<People>(); - } - - public List<People> getActors() { - return actors; - } - - public String getTitle() { - return title; - } - - public int getYear() { - return year; - } - - public void setActors(List<People> actors) { - Object oldValue = this.actors; - this.actors = actors; - firePropertyChange(PROPERTY_ACTORS, null, actors); - } - - public void setTitle(String title) { - Object oldValue = this.title; - this.title = title; - firePropertyChange(PROPERTY_TITLE, oldValue, title); - } - - public void setYear(int year) { - Object oldValue = this.year; - this.year = year; - firePropertyChange(PROPERTY_YEAR, oldValue, year); - } - - - public void addActor(People actor) { - actors.add(actor); - firePropertyChange(PROPERTY_ACTORS, null, actors); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Movie other = (Movie) obj; - return !(id == null ? other.id != null : !id.equals(other.id)); - } - - @Override - public int hashCode() { - int hash = 5; - hash = 41 * hash + (id != null ? id.hashCode() : 0); - return hash; - } - - @Override - public String toString() { - ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); - b.append(PROPERTY_ID, id); - b.append(PROPERTY_TITLE, title); - b.append(PROPERTY_IMAGE, image); - b.append(PROPERTY_YEAR, year); - b.append(PROPERTY_ACTORS, actors); - return b.toString(); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/entities/People.java b/jaxx-demo/src/main/java/jaxx/demo/entities/People.java deleted file mode 100644 index 63179b5..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/entities/People.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.entities; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -import static org.nuiton.i18n.I18n.n; - -/** - * @author Tony Chemit - chemit@codelutin.com - * @since 1.7.2 - */ -public class People extends AbstractDemoBean { - - static { - n("jaxxdemo.common.people"); - n("jaxxdemo.common.firstName"); - n("jaxxdemo.common.lastName"); - n("jaxxdemo.common.age"); - } - - public static final String PROPERTY_FIRST_NAME = "firstName"; - - public static final String PROPERTY_LAST_NAME = "lastName"; - - public static final String PROPERTY_AGE = "age"; - - protected String firstName; - - protected String lastName; - - protected int age; - - private static final long serialVersionUID = 1L; - - public People() { - } - - public People(String id, - String firstName, - String lastName, - int age, - String image) { - super(id, image); - this.firstName = firstName; - this.lastName = lastName; - this.age = age; - } - - public int getAge() { - return age; - } - - public String getFirstName() { - return firstName; - } - - public String getLastName() { - return lastName; - } - - public String getImage() { - return image; - } - - public void setAge(int age) { - int old = this.age; - this.age = age; - firePropertyChange(PROPERTY_AGE, old, age); - } - - public void setFirstName(String firstName) { - String old = this.firstName; - this.firstName = firstName; - firePropertyChange(PROPERTY_FIRST_NAME, old, firstName); - } - - public void setLastName(String lastName) { - String old = this.lastName; - this.lastName = lastName; - firePropertyChange(PROPERTY_LAST_NAME, old, lastName); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - People other = (People) obj; - return !(id == null ? other.id != null : !id.equals(other.id)); - } - - @Override - public int hashCode() { - int hash = 7; - hash = 97 * hash + (id != null ? id.hashCode() : 0); - return hash; - } - - @Override - public String toString() { - ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); - b.append(PROPERTY_ID, id); - b.append(PROPERTY_FIRST_NAME, firstName); - b.append(PROPERTY_LAST_NAME, lastName); - b.append(PROPERTY_IMAGE, image); - b.append(PROPERTY_AGE, age); - return b.toString(); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BaseBeanDataBinding.jaxx b/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BaseBeanDataBinding.jaxx deleted file mode 100644 index 930e60a..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BaseBeanDataBinding.jaxx +++ /dev/null @@ -1,48 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel> - - <!-- a full java bean property of the class --> - <Boolean id='editing' javaBean='false'/> - - <!-- not full java bean property (must add script...) --> - <Boolean id='editing2' constructorParams='false'/> - - <String id='contentMessage' javaBean='"message..."'/> - - <script> - void $afterCompleteSetup(){ - } - - public Boolean isEditing2() { - return editing2; - } - - public void setEditing2(Boolean editing2) { - Boolean oldValue = this.editing2; - this.editing2 = editing2; - firePropertyChange("editing2", oldValue, editing2); - } - </script> - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BindingExtremeDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BindingExtremeDemo.jaxx deleted file mode 100644 index fbe7483..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BindingExtremeDemo.jaxx +++ /dev/null @@ -1,290 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - - -<jaxx.demo.DemoPanel id='mainFrame' implements='DemoUIModel' - layout='{new BorderLayout()}'> - - <import> - jaxx.runtime.JAXXBinding - jaxx.runtime.FileChooserUtil - java.awt.Color - javax.swing.border.TitledBorder - javax.swing.DefaultListModel - javax.swing.SwingUtilities - </import> - <style> - JTextArea { editable:false; } - - JCheckBox { enabled:false; } - - .nobinding { background:{Color.GRAY}; } - </style> - - <script><![CDATA[ -public JToggleButton getT3() { return t0; } - -private void $afterCompleteSetup() { - for (Object o : $objectMap.values()) { - if (o instanceof JCheckBox) { - JCheckBox c = (JCheckBox) o; - c.setBackground($bindings.containsKey(c.getName() + ".selected") ? Color.WHITE : Color.RED); - } - } - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - DefaultListModel m = (DefaultListModel) bindings.getModel(); - for (JAXXBinding b : getDataBindings()) { - m.addElement(b.getId()); - } - } - }); -} -@Override -protected String[] getSources() { - return addDefaultSources( "DemoUIModel.java", "DefaultDemoUIModel.java" ); -} - ]]> - </script> - - <Boolean id='f0' javaBean='Boolean.FALSE'/> - <Boolean id='f1' javaBean='Boolean.FALSE'/> - <java.io.File id='file' javaBean='new java.io.File(".")'/> - - <DefaultDemoUIModel id='model0' initializer='new DefaultDemoUIModel()'/> - - <DemoUIModel id='model1' javaBean='new DefaultDemoUIModel()'/> - - - <Table fill="both" constraints='BorderLayout.CENTER'> - <row> - <cell columns="3"> - <JPanel layout="{new GridLayout(1,0)}"> - <JCheckBox id='cf0' selected='{isF0()}' text='isF0()'/> - <JCheckBox id='cf1' selected='{isF1()}' text='isF1()'/> - <JCheckBox id='cf0O1' selected='{isF0() || isF1()}' - text='isF0() || isF1()'/> - <JCheckBox id='cf0A1' selected='{isF0() && isF1()}' - text='isF0() && isF1()'/> - </JPanel> - </cell> - </row> - <row> - <cell columns="3"> - <JPanel layout="{new GridLayout(1,0)}"> - <JCheckBox id='ct0' selected='{t0.isSelected()}' - text='t0.isSelected()'/> - <JCheckBox id='ct1' selected='{t1.isSelected()}' - text='t1.isSelected()'/> - <JCheckBox id='ct0O1' selected='{t0.isSelected() || t1.isSelected()}' - text='t0.isSelected() || t1.isSelected()'/> - <JCheckBox id='ct0A1' - selected='{t0.isSelected() && t1.isSelected()}' - text='t0.isSelected() && t1.isSelected()'/> - </JPanel> - </cell> - </row> - <row> - <cell columns="3"> - <JPanel layout="{new GridLayout(1,0)}"> - <JCheckBox id='cgett0' selected='{getT0().isSelected()}' - text='getT0().isSelected()'/> - <JCheckBox id='cgett1' selected='{getT1().isSelected()}' - text='getT1().isSelected()'/> - <JCheckBox id='cgett0O1' - selected='{getT0().isSelected() || getT1().isSelected()}' - text='getT0().isSelected() || getT1().isSelected()'/> - <JCheckBox id='cgett0A1' - selected='{getT0().isSelected() && getT1().isSelected()}' - text='getT0().isSelected() && getT1().isSelected()'/> - </JPanel> - </cell> - </row> - <row> - <cell columns="3"> - <JPanel layout="{new GridLayout(1,0)}"> - <JTextArea id='cfile' - border='{new TitledBorder("file.getAbsolutePath()")}' - text='{file.getAbsolutePath()}' - visible='{!$bindings.containsKey("cfile.text")}' - styleClass="nobinding"/> - <JTextArea id='cgetfile' - border='{new TitledBorder("getFile().getAbsolutePath()")}' - text='{getFile().getAbsolutePath()}' - visible='{$bindings.containsKey("cgetfile.text")}'/> - </JPanel> - </cell> - </row> - <row weightx='1'> - <cell> - <JToggleButton id='t0' text='f0' onActionPerformed='setF0(!f0)'/> - </cell> - <cell> - <JToggleButton id='t1' text='f1' onActionPerformed='setF1(!f1)' - javaBean='new JToggleButton()'/> - </cell> - <cell> - <JButton text="file..." - onActionPerformed='setFile(FileChooserUtil.getFile(this, new String[0]))'/> - </cell> - </row> - - <row> - <cell columns="3"> - <JPanel layout="{new GridLayout(1,0)}"> - <JCheckBox id='cmt0' selected='{model0.isF0()}' text='model0.isF0()'/> - <JCheckBox id='cmt1' selected='{model0.isF1()}' text='model0.isF1()'/> - <JCheckBox id='cmt0O1' selected='{model0.isF0() || model0.isF1()}' - text='model0.isF0() || model0.isF1()'/> - <JCheckBox id='cmt0A1' - selected='{model0.isF0() && model0.isF1()}' - text='model0.isF0() && model0.isF1()'/> - </JPanel> - </cell> - </row> - <row> - <cell columns="3"> - <JPanel layout="{new GridLayout(1,0)}"> - <JCheckBox id='cmgett0' selected='{getModel0().isF0()}' - text='getModel0().isF0()'/> - <JCheckBox id='cmgett1' selected='{getModel0().isF1()}' - text='getModel0().isF1()'/> - <JCheckBox id='cmgett0O1' - selected='{getModel0().isF0() || getModel0().isF1()}' - text='getModel0().isF0() || getModel0().isF1()'/> - <JCheckBox id='cmgett0A1' - selected='{getModel0().isF0() && getModel0().isF1()}' - text='getModel0().isF0() && getModel0().isF1()'/> - </JPanel> - </cell> - </row> - <row> - <cell columns="3"> - <JPanel layout="{new GridLayout(1,0)}"> - <JTextArea id='cMfile' - border='{new TitledBorder("model0.getFile().getAbsolutePath()")}' - text='{model0.getFile().getAbsolutePath()}' - visible='{$bindings.containsKey("cMfile.text")}'/> - <JTextArea id='cMgetfile' - border='{new TitledBorder("getModel0().getFile().getAbsolutePath()")}' - text='{getModel0().getFile().getAbsolutePath()}' - visible='{$bindings.containsKey("cMgetfile.text")}'/> - </JPanel> - </cell> - </row> - <row> - <cell> - <JToggleButton id='Mt0' text='model0.f0' - onActionPerformed='model0.setF0(!model0.isF0())'/> - </cell> - <cell> - <JToggleButton id='Mt1' text='model0.f1' - onActionPerformed='model0.setF1(!model0.isF1())' - javaBean='new JToggleButton()'/> - </cell> - <cell> - <JButton text="model0.file..." - onActionPerformed='model0.setFile(FileChooserUtil.getFile(this,new String[0]))'/> - </cell> - </row> - - <row> - <cell columns="3"> - <JPanel layout="{new GridLayout(1,0)}"> - <JCheckBox id='cit0' selected='{((DemoUIModel)model1).isF0()}' - text='model1.isF0()'/> - <JCheckBox id='cit1' selected='{((DemoUIModel)model1).isF1()}' - text='model1.isF1()'/> - <JCheckBox id='cit0O1' - selected='{((DemoUIModel)model1).isF0() || ((DemoUIModel)model1).isF1()}' - text='model1.isF0() || model1.isF1()'/> - <JCheckBox id='cit0A1' - selected='{((DemoUIModel)model1).isF0() && ((DemoUIModel)model1).isF1()}' - text='model1.isF0() && model1.isF1()'/> - </JPanel> - </cell> - </row> - <row> - <cell columns="3"> - <JPanel layout="{new GridLayout(1,0)}"> - <JCheckBox id='cigett0' selected='{getModel1().isF0()}' - text='getModel1().isF0()'/> - <JCheckBox id='cigett1' selected='{getModel1().isF1()}' - text='getModel1().isF1()'/> - <JCheckBox id='cigett0O1' - selected='{getModel1().isF0() || getModel1().isF1()}' - text='getModel1().isF0() || getModel1().isF1()'/> - <JCheckBox id='cigett0A1' - selected='{getModel1().isF0() && getModel1().isF1()}' - text='getModel1().isF0() && getModel1().isF1()'/> - </JPanel> - </cell> - </row> - <row> - <cell columns="3"> - <JPanel layout="{new GridLayout(1,0)}"> - <JTextArea id='cIfile' - border='{new TitledBorder("model1.getFile().getAbsolutePath()")}' - text='{model1.getFile().getAbsolutePath()}' - visible='{$bindings.containsKey("cIfile.text")}'/> - <JTextArea id='cIgetfile' - border='{new TitledBorder("getModel1().getFile().getAbsolutePath()")}' - text='{getModel1().getFile().getAbsolutePath()}' - visible='{$bindings.containsKey("cIgetfile.text")}'/> - </JPanel> - </cell> - </row> - <row> - <cell> - <JToggleButton id='It0' text='model1.f0' - onActionPerformed='model1.setF0(!model1.isF0())'/> - </cell> - <cell> - <JToggleButton id='It1' text='model1.f1' - onActionPerformed='model1.setF1(!model1.isF1())' - javaBean='new JToggleButton()'/> - </cell> - <cell> - <JButton text="model1.file..." - onActionPerformed='model1.setFile(FileChooserUtil.getFile(this,new String[0]))'/> - </cell> - </row> - - <row weighty="1"> - <cell columns="3"> - <JPanel layout="{new BorderLayout()}"> - <JTextArea id="bindingsLabel" editable='false' - text='{$bindings.size() + " bindings."}'/> - <JScrollPane constraints='BorderLayout.CENTER' - columnHeaderView='{bindingsLabel}'> - <JList id="bindings" model='{new DefaultListModel()}' - font-size='10'/> - </JScrollPane> - </JPanel> - </cell> - </row> - </Table> - - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/DefaultDemoUIModel.java b/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/DefaultDemoUIModel.java deleted file mode 100644 index 22cea42..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/DefaultDemoUIModel.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.demo.feature.databinding; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.beans.AbstractSerializableBean; - -import javax.swing.JToggleButton; -import java.io.File; - -/** - * Created: 3 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - */ -public class DefaultDemoUIModel extends AbstractSerializableBean implements DemoUIModel { - - - private static final long serialVersionUID = 1L; - - protected File file; - - protected File file1; - - protected Boolean f1 = false; - - protected Boolean f0 = false; - - protected JToggleButton t1; - - protected JToggleButton t0; - - public static final String PROPERTY_T1 = "t1"; - - public static final String PROPERTY_F1 = "f1"; - - public static final String PROPERTY_F0 = "f0"; - - public static final String PROPERTY_FILE = "file"; - - protected static final Log log = LogFactory.getLog(DefaultDemoUIModel.class); - - /*---------------------------------------------------------------------------------*/ - /*-- public acessor methods -------------------------------------------------------*/ - /*---------------------------------------------------------------------------------*/ - - public Boolean getF0() { - return f0; - } - - public Boolean getF1() { - return f1; - } - - @Override - public File getFile() { - return file; - } - - public File getFile1() { - return file1; - } - - @Override - public JToggleButton getT0() { - return t0; - } - - @Override - public JToggleButton getT1() { - return t1; - } - - @Override - public Boolean isF0() { - return f0 != null && f0; - } - - @Override - public Boolean isF1() { - return f1 != null && f1; - } - - /*---------------------------------------------------------------------------------*/ - /*-- public mutator methods -------------------------------------------------------*/ - /*---------------------------------------------------------------------------------*/ - - @Override - public void setF0(Boolean newValue) { - Boolean oldValue = f0; - f0 = newValue; - firePropertyChange(PROPERTY_F0, oldValue, newValue); - } - - @Override - public void setF1(Boolean newValue) { - Boolean oldValue = f1; - f1 = newValue; - firePropertyChange(PROPERTY_F1, oldValue, newValue); - } - - @Override - public void setFile(File newValue) { - File oldValue = file; - file = newValue; - firePropertyChange(PROPERTY_FILE, oldValue, newValue); - } - - - public void setT1(JToggleButton newValue) { - JToggleButton oldValue = t1; - t1 = newValue; - firePropertyChange(PROPERTY_T1, oldValue, newValue); - } - -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/DemoUIModel.java b/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/DemoUIModel.java deleted file mode 100644 index e210396..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/DemoUIModel.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.demo.feature.databinding; - -import javax.swing.JToggleButton; -import java.beans.PropertyChangeListener; -import java.io.File; - -/** - * Created: 2 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - * - * Mise a jour: $Date$ par : - * $Author$ - */ -public interface DemoUIModel { - - Boolean isF0(); - - Boolean isF1(); - - void setF0(Boolean b); - - void setF1(Boolean b); - - JToggleButton getT0(); - - JToggleButton getT1(); - - File getFile(); - - void setFile(File newValue); - -// /** -// * All <code>JAXXObject</code> implements are capable of broadcasting <code>PropertyChangeEvent</code>, and -// * furthermore (for technical reasons) must allow code in outside packages, specifically the JAXX runtime, -// * to trigger these events. -// * -// * @param name the name of the property which changed -// * @param oldValue the old value of the property -// * @param newValue the new value of the property -// */ -// void firePropertyChange(String name, Object oldValue, Object newValue); - - /** - * Register a general {@link PropertyChangeListener}. - * - * @param listener the listener to register - */ - void addPropertyChangeListener(PropertyChangeListener listener); - - /** - * Register a {@link PropertyChangeListener}. for the given {@code propertyName}. - * - * @param property the property name to listen - * @param listener the listener to register - */ - void addPropertyChangeListener(String property, PropertyChangeListener listener); - - /** - * Unregister a general {@link PropertyChangeListener}. - * - * @param listener the listener to unregister - */ - void removePropertyChangeListener(PropertyChangeListener listener); - - /** - * Unregister a {@link PropertyChangeListener}. for the given {@code propertyName}. - * - * @param property the property name to listen - * @param listener the listener to unregister - */ - void removePropertyChangeListener(String property, PropertyChangeListener listener); - -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/NavDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/NavDemo.jaxx deleted file mode 100644 index 0ab267f..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/NavDemo.jaxx +++ /dev/null @@ -1,98 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - jaxx.demo.feature.nav.tree.NavDemoTreeHelper - jaxx.demo.feature.nav.treetable.NavDemoTreeTableHelper - org.jdesktop.swingx.JXTreeTable - jaxx.demo.entities.DemoDataProvider - </import> - - <CardLayout2 id='contentLayout'/> - - <DemoDataProvider id='dataProvider'/> - - <NavDemoTreeHelper id='treeHelper' constructorParams='getDataProvider()'/> - - <NavDemoTreeTableHelper id='treeTableHelper' - constructorParams='getDataProvider()'/> - - <script><![CDATA[ - -@Override -protected String[] getSources() { - return addDefaultSources( - "tree/NavDemoTreeNode.java", - "tree/NavDemoTreeHelper.java", - "tree/NavDemoTreeCellRenderer.java", - "tree/ActorsTreeNodeLoador.java", - "tree/MoviesTreeNodeLoador.java", - "treetable/NavDemoTreeTableNode.java", - "treetable/NavDemoTreeTableHelper.java", - "treetable/ActorsTreeTableNodeLoador.java", - "treetable/MoviesTreeTableNodeLoador.java" - ); -} - ]]> - </script> - - <JSplitPane id='splitPane' - constraints='BorderLayout.CENTER' - oneTouchExpandable='true'> - - <JTabbedPane> - <tab title='jaxxdemo.tree.tabtitle'> - <JScrollPane border='{null}' - horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' - verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_NEVER}'> - - <JTree id="navigationTree" - font-size='11' - rootVisible='false' - showsRootHandles='false' - model='{treeHelper.createModel()}'/> - - </JScrollPane> - </tab> - <tab title='jaxxdemo.treeTable.tabtitle'> - <JScrollPane border='{null}' - horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' - verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_NEVER}'> - - <JXTreeTable id="navigationTreeTable" - font-size='11' - rootVisible='false' - showsRootHandles='false' - columnControlVisible='true' - treeTableModel='{treeTableHelper.createModel()}'/> - - </JScrollPane> - </tab> - </JTabbedPane> - - <JPanel id="content" layout="{contentLayout}"/> - - </JSplitPane> - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/NavDemoHandler.java b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/NavDemoHandler.java deleted file mode 100644 index 174ac52..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/NavDemoHandler.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.demo.feature.nav; - -import jaxx.demo.entities.AbstractDemoBean; -import jaxx.demo.entities.DemoDataProvider; -import jaxx.demo.entities.Movie; -import jaxx.demo.entities.People; -import jaxx.demo.feature.nav.content.AbstractContentUI; -import jaxx.demo.feature.nav.content.ActorContentUI; -import jaxx.demo.feature.nav.content.ActorsContentUI; -import jaxx.demo.feature.nav.content.MovieContentUI; -import jaxx.demo.feature.nav.content.MoviesContentUI; -import jaxx.demo.feature.nav.tree.NavDemoTreeCellRenderer; -import jaxx.demo.feature.nav.tree.NavDemoTreeNode; -import jaxx.demo.feature.nav.treetable.NavDemoTreeTableNode; -import jaxx.runtime.JAXXContext; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.spi.UIHandler; -import jaxx.runtime.swing.CardLayout2; -import jaxx.runtime.swing.ErrorDialogUI; -import jaxx.runtime.swing.nav.NavNode; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.JXTreeTable; -import org.nuiton.decorator.DecoratorProvider; -import org.nuiton.decorator.JXPathDecorator; - -import javax.swing.ImageIcon; -import javax.swing.JPanel; -import javax.swing.JTree; -import javax.swing.SwingUtilities; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.TreePath; -import java.awt.Component; -import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.List; - -import static org.nuiton.i18n.I18n.n; - -/** - * Handler of all uis in the Nave demo. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.2 - */ -public class NavDemoHandler implements UIHandler<NavDemo> { - - private static final Log log = LogFactory.getLog(NavDemoHandler.class); - - protected NavDemo ui; - - public static String MOVIES_CATEGORY_NODE = n("jaxxdemo.common.movies"); - - public static String ACTORS_CATEGORY_NODE = n("jaxxdemo.common.actors"); - - @Override - public void beforeInit(NavDemo ui) { - this.ui = ui; - } - - @Override - public void afterInit(final NavDemo ui) { - // share in context - - ui.setContextValue(this); - ui.setContextValue(ui.getTreeHelper(), "treeHelper"); - ui.setContextValue(ui.getTreeTableHelper(), "treeTableHelper"); - - // Creation of selection listener to open ui when tree selection change - TreeSelectionListener treeSelectionListener = new TreeSelectionListener() { - @Override - public void valueChanged(TreeSelectionEvent event) { - TreePath path = event.getPath(); - NavDemoTreeNode demoNode = - (NavDemoTreeNode) path.getLastPathComponent(); - - if (log.isDebugEnabled()) { - log.debug("Select demoNode " + demoNode); - } - - // Do nothing for root - if (demoNode.isRoot()) { - return; - } - openUI(demoNode); - } - }; - - // Creation of selection listener to open ui when tree selection change - TreeSelectionListener treeTableSelectionListener = new TreeSelectionListener() { - @Override - public void valueChanged(TreeSelectionEvent event) { - TreePath path = event.getPath(); - NavDemoTreeTableNode demoNode = - (NavDemoTreeTableNode) path.getLastPathComponent(); - - if (log.isDebugEnabled()) { - log.debug("Select demoNode " + demoNode); - } - - // Do nothing for root - if (demoNode.isRoot()) { - return; - } - openUI(demoNode); - } - }; - - final JTree tree = ui.getNavigationTree(); - JXTreeTable table = ui.getNavigationTreeTable(); - - // Attach renderer - NavDemoTreeCellRenderer renderer = new NavDemoTreeCellRenderer( - ui.getContextValue(DecoratorProvider.class), - ui.getDataProvider() - ); - tree.setCellRenderer(renderer); - - // Register tree - ui.getTreeHelper().setUI(tree, true, treeSelectionListener); - - // Register tree table - ui.getTreeTableHelper().setUI(table, true, treeTableSelectionListener); - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - tree.setSelectionInterval(0, 0); - ui.getSplitPane().resetToPreferredSizes(); - } - }); - - // expand the tree - SwingUtil.expandTree(tree); - SwingUtil.expandTreeTable(table); - - // auto-expand demoNode when selected - SwingUtil.addExpandOnClickListener(tree); - SwingUtil.addExpandOnClickListener(table); - } - - public void initUI(MoviesContentUI contentUI) { - DecoratorProvider provider = - contentUI.getContextValue(DecoratorProvider.class); - JXPathDecorator<Movie> decorator = - (JXPathDecorator<Movie>) provider.getDecoratorByType(Movie.class); - contentUI.getListHeader().init(decorator, new ArrayList<Movie>()); - } - - public void initUI(ActorsContentUI contentUI) { - DecoratorProvider provider = - contentUI.getContextValue(DecoratorProvider.class); - JXPathDecorator<People> decorator = - (JXPathDecorator<People>) provider.getDecoratorByType(People.class); - contentUI.getListHeader().init(decorator, new ArrayList<People>()); - } - - public void selectChild(AbstractContentUI<?> contentUI, - AbstractDemoBean selected) { - contentUI.getTreeHelper().selectNode(selected.getId()); - contentUI.getTreeTableHelper().selectNode(selected.getId()); - } - - public String getContent(AbstractDemoBean data) { - if (data == null) { - return "no content"; - } - StringBuilder buffer = new StringBuilder(); - buffer.append(data); - return buffer.toString(); - } - - public ImageIcon getImage(AbstractDemoBean data) { - return data == null ? null : SwingUtil.createIcon(data.getImage()); - } - - protected void openUI(NavNode<?, ?> demoNode) { - - // Get demoNode type - Class<?> editType = demoNode.getInternalClass(); - String id = demoNode.getId(); - - // If it's category demoNode - DemoDataProvider provider = ui.getDataProvider(); - if (editType.equals(String.class)) { - - // Actors categorie demoNode - if (ACTORS_CATEGORY_NODE.equals(id)) { - - List<People> peoples = provider.getPeoples(); - showUI(peoples, ActorsContentUI.class); - - // Movies categorie demoNode - } else if (MOVIES_CATEGORY_NODE.equals(id)) { - - List<Movie> movies = provider.getMovies(); - showUI(movies, MoviesContentUI.class); - } - - // People demoNode - } else if (editType.equals(People.class)) { - People people = provider.getPeople(id); - showUI(people, ActorContentUI.class); - - // Movie demoNode - } else if (editType.equals(Movie.class)) { - Movie movie = provider.getMovie(id); - showUI(movie, MovieContentUI.class); - } - } - - // Create by introspection content ui - - protected <B> void showUI(B bean, - Class<? extends AbstractContentUI<B>> uiClass) { - - // Verify if instance is existing - AbstractContentUI<B> ui = getContentIfExist(uiClass); - - // Get layout identifier - String contentName = uiClass.getName(); - - JPanel content = this.ui.getContent(); - if (ui == null) { - try { - // Get constructor - Constructor<? extends AbstractContentUI<B>> constructor = - uiClass.getConstructor(JAXXContext.class); - - // Invoke instance creation - ui = constructor.newInstance(this.ui); - } catch (Exception eee) { - log.error("Could not create ui of type " + uiClass, eee); - ErrorDialogUI.showError(eee); - return; - } - - // Add to content panel - content.add(ui, contentName); - } - - // Attach bean - ui.setData(bean); - - // show ui - this.ui.getContentLayout().show(content, contentName); - - // revalidate container - SwingUtilities.invokeLater(revalidateContent); - - } - - // Get content if exist in content, else return null - - protected <E extends Component> E getContentIfExist(Class<E> uiClass) { - String contentName = uiClass.getName(); - if (log.isDebugEnabled()) { - log.debug("Get content if exist " + contentName); - } - CardLayout2 layout2 = ui.getContentLayout(); - if (!layout2.contains(contentName)) { - return null; - } - return (E) layout2.getComponent(ui.getContent(), contentName); - } - - private final Runnable revalidateContent = new Runnable() { - - @Override - public void run() { - ui.revalidate(); - } - }; - -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/AbstractContentUI.jaxx b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/AbstractContentUI.jaxx deleted file mode 100644 index b17473c..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/AbstractContentUI.jaxx +++ /dev/null @@ -1,46 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<JPanel abstract='true' layout='{new BorderLayout()}' genericType='B'> - - <import> - jaxx.demo.feature.nav.NavDemoHandler - jaxx.demo.feature.nav.tree.NavDemoTreeHelper - jaxx.demo.feature.nav.treetable.NavDemoTreeTableHelper - </import> - - <NavDemoTreeHelper id='treeHelper' - initializer='getContextValue(NavDemoTreeHelper.class,"treeHelper")'/> - - <NavDemoTreeTableHelper id='treeTableHelper' - initializer='getContextValue(NavDemoTreeTableHelper.class,"treeTableHelper")'/> - - <NavDemoHandler id='handler' - initializer='getContextValue(NavDemoHandler.class)'/> - <script><![CDATA[ - -public abstract B getData(); - -public abstract void setData(B data); - ]]> - </script> -</JPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/ActorContentUI.jaxx b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/ActorContentUI.jaxx deleted file mode 100644 index ac51d2b..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/ActorContentUI.jaxx +++ /dev/null @@ -1,56 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<AbstractContentUI superGenericType='People'> - - <import> - jaxx.demo.entities.People - static org.nuiton.i18n.I18n.t - </import> - - <People id='data' javaBean='null'/> - - <JSplitPane id='splitPane' orientation='{JSplitPane.VERTICAL_SPLIT}' - resizeWeight='0.5' constraints='BorderLayout.CENTER' - oneTouchExpandable='true'> - - <JScrollPane border='{null}' - horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' - verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> - - <JTextPane editable='false' font-size='11' - border='{new TitledBorder(t("jaxxdemo.navigation.actor.title"))}' - text='{getHandler().getContent(getData())}'/> - </JScrollPane> - - <JScrollPane border='{new TitledBorder("Picture")}' - horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED}' - verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}' - minimumSize='{SwingUtil.newMinDimension()}'> - - <JLabel horizontalAlignment='center' - icon='{getHandler().getImage(getData())}'/> - - </JScrollPane> - - </JSplitPane> -</AbstractContentUI> diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/ActorsContentUI.jaxx b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/ActorsContentUI.jaxx deleted file mode 100644 index 573849c..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/ActorsContentUI.jaxx +++ /dev/null @@ -1,81 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<AbstractContentUI superGenericType='List<People>'> - - <import> - java.util.List - jaxx.demo.entities.People - jaxx.runtime.swing.editor.bean.BeanListHeader - jaxx.runtime.swing.renderer.DecoratorProviderListCellRenderer - - static org.nuiton.i18n.I18n.t - </import> - - <java.util.List id='data' genericType='People' javaBean='null'/> - - <script><![CDATA[ -private void $afterCompleteSetup() { - getHandler().initUI(this); -} - ]]></script> - - <JPanel layout='{new BorderLayout()}'> - - <JScrollPane - border='{new TitledBorder(t("jaxxdemo.navigation.actors.title"))}' - constraints='BorderLayout.CENTER' - columnHeaderView='{toolbar}' - horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' - verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> - - <!-- list of actors --> - <JList id='list' - cellRenderer='{getContextValue(DecoratorProviderListCellRenderer.class)}'/> - - <!-- list header --> - <JToolBar id='toolbar' floatable='false' layout='{new BorderLayout()}'> - <JPanel layout='{new GridLayout(1,0)}' - constraints='BorderLayout.CENTER'> - - <!-- to show the selected actor --> - <JButton text='jaxxdemo.action.show' - enabled='{list.getSelectedIndex()!=-1}' - onActionPerformed='getHandler().selectChild(this, (People) list.getSelectedValue())'/> - - <!-- to show a new actor --> - <JButton text='jaxxdemo.action.add'/> - - <!-- to delete the selected actor --> - <JButton text='jaxxdemo.action.remove' - enabled='{list.getSelectedIndex()!=-1}'/> - </JPanel> - - <BeanListHeader id='listHeader' constraints='BorderLayout.EAST' - i18nPrefix='jaxxdemo.common.' genericType='People' - data='{getData()}' list='{list}' showReset='true'/> - </JToolBar> - - </JScrollPane> - - </JPanel> -</AbstractContentUI> diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/MovieContentUI.jaxx b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/MovieContentUI.jaxx deleted file mode 100644 index 6a62da7..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/MovieContentUI.jaxx +++ /dev/null @@ -1,57 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<AbstractContentUI superGenericType='Movie'> - - <import> - jaxx.demo.entities.Movie - static org.nuiton.i18n.I18n.t - </import> - - <Movie id='data' javaBean='null'/> - - <JSplitPane id='splitPane' orientation='{JSplitPane.VERTICAL_SPLIT}' - resizeWeight='0.5' constraints='BorderLayout.CENTER' - oneTouchExpandable='true'> - - <JScrollPane border='{null}' - horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' - verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> - - <JTextPane - border='{new TitledBorder(t("jaxxdemo.navigation.movie.title"))}' - editable='false' font-size='11' - text='{getHandler().getContent(getData())}'/> - </JScrollPane> - - <JScrollPane border='{new TitledBorder("Picture")}' - horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED}' - verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}' - minimumSize='{SwingUtil.newMinDimension()}'> - - <JLabel horizontalAlignment='center' - icon='{getHandler().getImage(getData())}'/> - - </JScrollPane> - - </JSplitPane> -</AbstractContentUI> diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/MoviesContentUI.jaxx b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/MoviesContentUI.jaxx deleted file mode 100644 index ede7c80..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/MoviesContentUI.jaxx +++ /dev/null @@ -1,81 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<AbstractContentUI superGenericType='List<Movie>'> - - <import> - java.util.List - jaxx.demo.entities.Movie - jaxx.runtime.swing.editor.bean.BeanListHeader - jaxx.runtime.swing.renderer.DecoratorProviderListCellRenderer - - static org.nuiton.i18n.I18n.t - </import> - <script><![CDATA[ - -private void $afterCompleteSetup() { - getHandler().initUI(this); -} - ]]></script> - - <java.util.List id='data' genericType='Movie' javaBean='null'/> - - <JPanel layout='{new BorderLayout()}'> - - <JScrollPane - border='{new TitledBorder(t("jaxxdemo.navigation.movies.title"))}' - constraints='BorderLayout.CENTER' - columnHeaderView='{toolbar}' - horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' - verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> - - <!-- list of movies --> - <JList id='list' - cellRenderer='{getContextValue(DecoratorProviderListCellRenderer.class)}'/> - - <!-- list header --> - <JToolBar id='toolbar' floatable='false' layout='{new BorderLayout()}'> - <JPanel layout='{new GridLayout(1,0)}' - constraints='BorderLayout.CENTER'> - - <!-- to show the selected actor --> - <JButton text='jaxxdemo.action.show' - enabled='{list.getSelectedIndex()!=-1}' - onActionPerformed='getHandler().selectChild(this, (Movie) list.getSelectedValue())'/> - - <!-- to show a new actor --> - <JButton text='jaxxdemo.action.add'/> - - <!-- to delete the selected actor --> - <JButton text='jaxxdemo.action.remove' - enabled='{list.getSelectedIndex()!=-1}'/> - </JPanel> - - <BeanListHeader id='listHeader' constraints='BorderLayout.EAST' - i18nPrefix='jaxxdemo.common.' - data='{getData()}' genericType='Movie' - list='{list}' showReset='true'/> - </JToolBar> - </JScrollPane> - - </JPanel> -</AbstractContentUI> diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/ActorsTreeNodeLoador.java b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/ActorsTreeNodeLoador.java deleted file mode 100644 index 7da65e0..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/ActorsTreeNodeLoador.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.feature.nav.tree; - -import jaxx.demo.entities.DemoDataProvider; -import jaxx.demo.entities.People; -import jaxx.runtime.swing.nav.NavDataProvider; -import jaxx.runtime.swing.nav.tree.NavTreeNodeChildLoador; - -import java.util.List; - -/** - * @author Sylvain Lletellier - * @since 2.1 - */ -public class ActorsTreeNodeLoador extends NavTreeNodeChildLoador<People, People, NavDemoTreeNode> { - - private static final long serialVersionUID = 1L; - - public ActorsTreeNodeLoador() { - super(People.class); - } - - @Override - public List<People> getData(Class<?> parentClass, - String moviesId, - NavDataProvider dataProvider) throws Exception { - - // Get people for parentId - DemoDataProvider provider = (DemoDataProvider) dataProvider; - - // If its not root - if (moviesId != null) { - - // Return peoples for movies id - return provider.getPeoples(moviesId); - } - - // Return all peoples - return provider.getPeoples(); - } - - @Override - public NavDemoTreeNode createNode(People data, NavDataProvider dataProvider) { - - NavDemoTreeNode actorNode; - - // Create actor static nodes - actorNode = new NavDemoTreeNode( - getBeanType(), - data.getId(), - null, - null - ); - - return actorNode; - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/MoviesTreeNodeLoador.java b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/MoviesTreeNodeLoador.java deleted file mode 100644 index da5369e..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/MoviesTreeNodeLoador.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.feature.nav.tree; - -import jaxx.demo.entities.DemoDataProvider; -import jaxx.demo.entities.Movie; -import jaxx.demo.feature.nav.NavDemoHandler; -import jaxx.runtime.swing.nav.NavDataProvider; -import jaxx.runtime.swing.nav.NavHelper; -import jaxx.runtime.swing.nav.tree.NavTreeNodeChildLoador; - -import java.util.List; - -import static org.nuiton.i18n.I18n.n; - -/** - * @author Sylvain Lletellier - * @since 2.1 - */ -public class MoviesTreeNodeLoador extends NavTreeNodeChildLoador<Movie, Movie, NavDemoTreeNode> { - - private static final long serialVersionUID = 1L; - - protected boolean isTreeTable; - - public MoviesTreeNodeLoador() { - this(false); - } - - public MoviesTreeNodeLoador(boolean isTreeTable) { - super(Movie.class); - this.isTreeTable = isTreeTable; - } - - @Override - public List<Movie> getData(Class<?> parentClass, - String parentId, - NavDataProvider dataProvider) throws Exception { - - DemoDataProvider provider = (DemoDataProvider) dataProvider; - - // Return all movies - return provider.getMovies(); - } - - @Override - public NavDemoTreeNode createNode(Movie data, NavDataProvider dataProvider) { - - NavDemoTreeNode moviesNode; - NavDemoTreeNode actorsCategoryNode; - - // Create movies static nodes - moviesNode = new NavDemoTreeNode( - getBeanType(), - data.getId(), - null, - null - ); - - // Create clients category node - actorsCategoryNode = new NavDemoTreeNode( - String.class, - n(NavDemoHandler.ACTORS_CATEGORY_NODE), - null, - NavHelper.getChildLoador(ActorsTreeNodeLoador.class) - ); - - // Add actors nodes to movies node - moviesNode.add(actorsCategoryNode); - - return moviesNode; - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeCellRenderer.java b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeCellRenderer.java deleted file mode 100644 index 51ecbc8..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeCellRenderer.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.feature.nav.tree; - -import jaxx.demo.entities.DemoDataProvider; -import jaxx.demo.entities.Movie; -import jaxx.demo.entities.People; -import jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.decorator.Decorator; -import org.nuiton.decorator.DecoratorProvider; - -import javax.swing.JTree; -import javax.swing.tree.DefaultTreeModel; -import java.awt.Component; - -/** - * @author Sylvain Lletellier - * @since 2.1 - */ -public class NavDemoTreeCellRenderer extends AbstractNavTreeCellRenderer<DefaultTreeModel, NavDemoTreeNode> { - - /** Logger */ - protected static final Log log = - LogFactory.getLog(NavDemoTreeCellRenderer.class); - - protected DecoratorProvider decoratorProvider; - - public NavDemoTreeCellRenderer(DecoratorProvider decoratorProvider, - DemoDataProvider provider) { - setDataProvider(provider); - this.decoratorProvider = decoratorProvider; - } - - @Override - public DemoDataProvider getDataProvider() { - return (DemoDataProvider) super.getDataProvider(); - } - - @Override - protected String computeNodeText(NavDemoTreeNode node) { - - // Get node type - Class<?> editType = node.getInternalClass(); - String id = node.getId(); - - // get decorator - Decorator<?> decorator = decoratorProvider.getDecoratorByType(editType); - - Object toDecorate = null; - - // People node - if (editType.equals(People.class)) { - toDecorate = getDataProvider().getPeople(id); - - // Movie node - } else if (editType.equals(Movie.class)) { - toDecorate = getDataProvider().getMovie(id); - } - - // Get decorated value - String decorated = decorator.toString(toDecorate); - - if (log.isDebugEnabled()) { - log.debug("Compute text for node " + - node + " return " + - decorated); - } - - return decorated; - } - - @Override - public Component getTreeCellRendererComponent(JTree tree, - Object value, - boolean sel, - boolean expanded, - boolean leaf, int row, - boolean hasFocus) { - - if (!(value instanceof NavDemoTreeNode)) { - return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); - } - - // get node - NavDemoTreeNode node = (NavDemoTreeNode) value; - - // get text for node - String text = getNodeText(node); - - // Render node - return super.getTreeCellRendererComponent(tree, text, sel, expanded, leaf, row, hasFocus); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeHelper.java b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeHelper.java deleted file mode 100644 index 0c0d7a1..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeHelper.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.feature.nav.tree; - -import jaxx.demo.entities.DemoDataProvider; -import jaxx.demo.feature.nav.NavDemoHandler; -import jaxx.runtime.swing.nav.tree.NavTreeHelper; - -import javax.swing.tree.DefaultTreeModel; - -/** - * @author Sylvain Lletellier - * @since 2.1 - */ -public class NavDemoTreeHelper extends NavTreeHelper<NavDemoTreeNode> { - - public NavDemoTreeHelper(DemoDataProvider provider) { - setDataProvider(provider); - } - - @Override - public DemoDataProvider getDataProvider() { - return (DemoDataProvider) super.getDataProvider(); - } - - public DefaultTreeModel createModel() { - - // Create root static node - NavDemoTreeNode root = new NavDemoTreeNode( - String.class, - "Root node", - null, - null - ); - - // Create movies category node - NavDemoTreeNode moviesCategoryNode = new NavDemoTreeNode( - String.class, - NavDemoHandler.MOVIES_CATEGORY_NODE, - null, - getChildLoador(MoviesTreeNodeLoador.class) - ); - - // Create peoples category node - NavDemoTreeNode peoplesCategoryNode = new NavDemoTreeNode( - String.class, - NavDemoHandler.ACTORS_CATEGORY_NODE, - null, - getChildLoador(ActorsTreeNodeLoador.class) - ); - - // Add to root - root.add(moviesCategoryNode); - root.add(peoplesCategoryNode); - - // Create model - DefaultTreeModel model = createModel(root); - - // Populate childs nodes - root.populateChilds(getBridge(), getDataProvider()); - - return model; - } - -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeNode.java b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeNode.java deleted file mode 100644 index 9586c6a..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeNode.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.feature.nav.tree; - -import jaxx.runtime.swing.nav.tree.NavTreeNode; -import jaxx.runtime.swing.nav.tree.NavTreeNodeChildLoador; - -/** - * @author Sylvain Lletellier - * @since 2.1 - */ -public class NavDemoTreeNode extends NavTreeNode<NavDemoTreeNode> { - - private static final long serialVersionUID = 1L; - - public NavDemoTreeNode(String id) { - super(id); - } - - public NavDemoTreeNode(Class<?> internalClass, - String id, - String context, - NavTreeNodeChildLoador<?, ?, NavDemoTreeNode> loador) { - super(internalClass, id, context, loador); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/ActorsTreeTableNodeLoador.java b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/ActorsTreeTableNodeLoador.java deleted file mode 100644 index 2077d07..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/ActorsTreeTableNodeLoador.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.feature.nav.treetable; - -import jaxx.demo.entities.DemoDataProvider; -import jaxx.demo.entities.People; -import jaxx.runtime.swing.nav.NavDataProvider; -import jaxx.runtime.swing.nav.treetable.NavTreeTableNodeChildLoador; - -import java.util.List; - -/** - * @author Sylvain Lletellier - * @since 2.1 - */ -public class ActorsTreeTableNodeLoador extends NavTreeTableNodeChildLoador<People, People, NavDemoTreeTableNode> { - - private static final long serialVersionUID = 1L; - - public ActorsTreeTableNodeLoador() { - super(People.class); - } - - @Override - public List<People> getData(Class<?> parentClass, - String moviesId, - NavDataProvider dataProvider) throws Exception { - - // Get people for parentId - DemoDataProvider provider = (DemoDataProvider) dataProvider; - - // If its not root - if (moviesId != null) { - - // Return peoples for movies id - return provider.getPeoples(moviesId); - } - - // Return all peoples - return provider.getPeoples(); - } - - @Override - public NavDemoTreeTableNode createNode(People data, NavDataProvider dataProvider) { - - NavDemoTreeTableNode actorNode; - - // Create actor static nodes - - actorNode = new NavDemoTreeTableNode( - getBeanType(), - data.getId(), - null, - null - ); - - return actorNode; - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/MoviesTreeTableNodeLoador.java b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/MoviesTreeTableNodeLoador.java deleted file mode 100644 index 1dc1c2a..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/MoviesTreeTableNodeLoador.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.feature.nav.treetable; - -import jaxx.demo.entities.DemoDataProvider; -import jaxx.demo.entities.Movie; -import jaxx.demo.feature.nav.NavDemoHandler; -import jaxx.runtime.swing.nav.NavDataProvider; -import jaxx.runtime.swing.nav.NavHelper; -import jaxx.runtime.swing.nav.treetable.NavTreeTableNodeChildLoador; - -import java.util.List; - -import static org.nuiton.i18n.I18n.n; - -/** - * @author Sylvain Lletellier - * @since 2.1 - */ -public class MoviesTreeTableNodeLoador extends NavTreeTableNodeChildLoador<Movie, Movie, NavDemoTreeTableNode> { - - private static final long serialVersionUID = 1L; - - protected boolean isTreeTable; - - public MoviesTreeTableNodeLoador() { - this(false); - } - - public MoviesTreeTableNodeLoador(boolean isTreeTable) { - super(Movie.class); - this.isTreeTable = isTreeTable; - } - - @Override - public List<Movie> getData(Class<?> parentClass, - String parentId, - NavDataProvider dataProvider) throws Exception { - - DemoDataProvider provider = (DemoDataProvider) dataProvider; - - // Return all movies - return provider.getMovies(); - } - - @Override - public NavDemoTreeTableNode createNode(Movie data, - NavDataProvider dataProvider) { - - NavDemoTreeTableNode moviesNode; - NavDemoTreeTableNode actorsCategoryNode; - - // Create movies static nodes - moviesNode = new NavDemoTreeTableNode( - getBeanType(), - data.getId(), - null, - null - ); - - // Create clients category node - actorsCategoryNode = new NavDemoTreeTableNode( - String.class, - n(NavDemoHandler.ACTORS_CATEGORY_NODE), - null, - NavHelper.getChildLoador(ActorsTreeTableNodeLoador.class) - ); - - // Add actors nodes to movies node - moviesNode.add(actorsCategoryNode); - - return moviesNode; - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableHelper.java b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableHelper.java deleted file mode 100644 index e566de1..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableHelper.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.feature.nav.treetable; - -import jaxx.demo.entities.DemoDataProvider; -import jaxx.demo.feature.nav.NavDemoHandler; -import jaxx.runtime.swing.nav.treetable.NavTreeTableHelper; -import jaxx.runtime.swing.nav.treetable.NavTreeTableModel; - -/** - * @author Sylvain Lletellier - * @since 2.1 - */ -public class NavDemoTreeTableHelper extends NavTreeTableHelper<NavDemoTreeTableNode> { - - public NavDemoTreeTableHelper(DemoDataProvider provider) { - setDataProvider(provider); - } - - @Override - public DemoDataProvider getDataProvider() { - return (DemoDataProvider) super.getDataProvider(); - } - - - public NavTreeTableModel createModel() { - - // Create root static node - NavDemoTreeTableNode root = new NavDemoTreeTableNode( - String.class, - "Root node", - null, - null - ); - - // Create movies category node - NavDemoTreeTableNode moviesCategoryNode = new NavDemoTreeTableNode( - String.class, - NavDemoHandler.MOVIES_CATEGORY_NODE, - null, - getChildLoador(MoviesTreeTableNodeLoador.class) - ); - - // Create peoples category node - NavDemoTreeTableNode peoplesCategoryNode = new NavDemoTreeTableNode( - String.class, - NavDemoHandler.ACTORS_CATEGORY_NODE, - null, - getChildLoador(ActorsTreeTableNodeLoador.class) - ); - - // Add to root - root.add(moviesCategoryNode); - root.add(peoplesCategoryNode); - - // Create model - NavDemoTreeTableModel delegate = new NavDemoTreeTableModel(getDataProvider()); - NavTreeTableModel model = createModel(root, delegate); - - // Populate childs nodes - root.populateChilds(getBridge(), getDataProvider()); - - return model; - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableModel.java b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableModel.java deleted file mode 100644 index 2af8a60..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableModel.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.demo.feature.nav.treetable; - -import jaxx.demo.entities.DemoDataProvider; -import jaxx.demo.entities.Movie; -import jaxx.demo.entities.People; -import jaxx.runtime.swing.nav.NavNode; -import jaxx.runtime.swing.nav.treetable.NavTreeTableModel; - -import static org.nuiton.i18n.I18n.t; - -/** - * @author Sylvain Lletellier - * @since 2.1 - */ -public class NavDemoTreeTableModel extends NavTreeTableModel.MyDefaultTreeTableModel { - - protected DemoDataProvider dataProvider; - - public NavDemoTreeTableModel(DemoDataProvider dataProvider) { - this.dataProvider = dataProvider; - } - - @Override - public Object getValueAt(Object o, int i) { - NavNode node = (NavNode) o; - - // Get node type - Class<?> editType = node.getInternalClass(); - String id = node.getId(); - - // If it's category node - if (node.isStringNode()) { - if (i == 0) { - return t(id); - } - return ""; - - // People node - } else if (editType.equals(People.class)) { - People people = dataProvider.getPeople(id); - return getPeopleColumn(people, i); - - // Movie node - } else if (editType.equals(Movie.class)) { - Movie movie = dataProvider.getMovie(id); - return getMovieColumn(movie, i); - } - - // This never append - return "not found"; - } - - private String getMovieColumn(Movie movie, int i) { - String result = ""; - - switch (i) { - case 0: - result = movie.getTitle(); - break; - case 2: - result = String.valueOf(movie.getYear()); - break; - } - return result; - } - - protected String getPeopleColumn(People people, int i) { - String result = ""; - - switch (i) { - case 0: - result = people.getFirstName(); - break; - case 1: - result = people.getLastName(); - break; - case 2: - result = String.valueOf(people.getAge()); - break; - } - return result; - } - - @Override - public String[] getColumnsNames() { - return new String[]{t("jaxxdemo.common.firstName"), - t("jaxxdemo.common.lastName"), - t("jaxxdemo.common.age")}; - } - - @Override - public boolean isCellEditable(Object node, int column) { - return false; - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableNode.java b/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableNode.java deleted file mode 100644 index ad6edd9..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableNode.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.demo.feature.nav.treetable; - -import jaxx.runtime.swing.nav.treetable.NavTreeTableNode; -import jaxx.runtime.swing.nav.treetable.NavTreeTableNodeChildLoador; - -/** - * @author Sylvain Lletellier - * @since 2.1 - */ -public class NavDemoTreeTableNode extends NavTreeTableNode<NavDemoTreeTableNode> { - private static final long serialVersionUID = 1L; - - protected NavDemoTreeTableNode(String id) { - super(id); - } - - public NavDemoTreeTableNode(Class<?> internalClass, - String id, - String context, - NavTreeTableNodeChildLoador<?, ?, NavDemoTreeTableNode> childLoador) { - super(internalClass, id, context, childLoador); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/validation/list/ListBeanValidationDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/feature/validation/list/ListBeanValidationDemo.jaxx deleted file mode 100644 index 45f050b..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/validation/list/ListBeanValidationDemo.jaxx +++ /dev/null @@ -1,103 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - org.jdesktop.swingx.JXTable - javax.swing.JOptionPane - static org.nuiton.i18n.I18n.n - jaxx.demo.entities.People - org.nuiton.validator.bean.list.BeanListValidator - jaxx.runtime.validator.swing.SwingListValidatorMessageTableModel - - java.io.File - </import> - - <script><![CDATA[ -@Override -protected String[] getSources() { - return addDefaultSources( - "ListBeanValidationDemo.css", - "/jaxx.demo.entities.People.java", - "/jaxx.demo.entities.People-error-validation.xml", - "/jaxx.demo.entities.People-info-validation.xml", - "/jaxx.demo.entities.People-warning-validation.xml", - "ListBeanValidationDemoHandler.java", - "PeopleTableModel.java" - ); -} -]]></script> - - <!-- model --> - <PeopleTableModel id='model'/> - - <!-- validator --> - <BeanListValidator id='validator' genericType='People' - initializer='BeanListValidator.newValidator(People.class, null)'/> - - <!-- errors model --> - <SwingListValidatorMessageTableModel id='errorTableModel' - onTableChanged='handler.updateOkEnabled()'/> - - <Table fill='both' constraints='BorderLayout.CENTER'> - <row> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Form")}' - layout='{new GridLayout()}' width='250' height='120'> - <JScrollPane id='dataTableScrollePane' constraints='BorderLayout.CENTER'> - <JXTable id='dataTable' model='{model}' autoCreateRowSorter='true'/> - </JScrollPane> - </JPanel> - </cell> - </row> - <row> - <cell fill="both"> - <JPanel layout='{new GridLayout(1,3,0,0)}'> - <JButton id='addIdentity' text='jaxx.demo.action.add' - onActionPerformed='handler.addPeople()'/> - <JButton id='removeIdentity' text='jaxx.demo.action.remove' - onActionPerformed='handler.removePeople()'/> - <JButton id='ok' text='jaxx.demo.action.ok' - onActionPerformed='JOptionPane.showMessageDialog(this, ok.getText() + " clicked!", "onActionPerformed", JOptionPane.INFORMATION_MESSAGE);'/> - - </JPanel> - </cell> - </row> - <row> - <cell fill="both"> - <JPanel border='{BorderFactory.createTitledBorder("Messages")}' - layout='{new GridLayout()}' height='200' - width='500'> - <JScrollPane columnHeaderView='{errorTable.getTableHeader()}'> - <JTable id='errorTable' model='{errorTableModel}' - rowSelectionAllowed='true' - autoCreateRowSorter='true' - autoResizeMode='2' cellSelectionEnabled='false' - selectionMode='0'/> - </JScrollPane> - </JPanel> - </cell> - </row> - </Table> - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/validation/list/ListBeanValidationDemoHandler.java b/jaxx-demo/src/main/java/jaxx/demo/feature/validation/list/ListBeanValidationDemoHandler.java deleted file mode 100644 index d1a7534..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/validation/list/ListBeanValidationDemoHandler.java +++ /dev/null @@ -1,187 +0,0 @@ -package jaxx.demo.feature.validation.list; -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.demo.entities.DemoDecoratorProvider; -import jaxx.demo.entities.People; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.spi.UIHandler; -import jaxx.runtime.validator.swing.SwingListValidatorDataLocator; -import jaxx.runtime.validator.swing.SwingListValidatorMessageTableRenderer; -import jaxx.runtime.validator.swing.SwingValidatorUtil; -import org.apache.commons.lang3.tuple.Pair; -import org.jdesktop.swingx.JXTable; -import org.nuiton.decorator.Decorator; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.list.BeanListValidator; - -import javax.swing.JTable; -import javax.swing.RowSorter; -import javax.swing.SortOrder; -import javax.swing.table.TableModel; -import java.util.Arrays; -import java.util.UUID; - -import static org.nuiton.i18n.I18n.n; - -/** - * Handler of UI {@link ListBeanValidationDemo}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.3 - */ -public class ListBeanValidationDemoHandler implements UIHandler<ListBeanValidationDemo>{ - - private ListBeanValidationDemo ui; - - @Override - public void beforeInit(ListBeanValidationDemo ui) { - this.ui = ui; - } - - @Override - public void afterInit(ListBeanValidationDemo ui) { - - // customize data table - - JXTable dataTable = ui.getDataTable(); - - dataTable.getRowSorter().setSortKeys( - Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); - SwingUtil.setI18nTableHeaderRenderer( - dataTable, - n("jaxx.demo.label.id"), - n("jaxx.demo.label.id.tip"), - n("jaxx.demo.label.firstName"), - n("jaxx.demo.label.firstName.tip"), - n("jaxx.demo.label.lastName"), - n("jaxx.demo.label.lastName.tip"), - n("jaxx.demo.label.age"), - n("jaxx.demo.label.age.tip")); - - SwingUtil.fixTableColumnWidth(dataTable, 3, 35); - - // register validator - BeanListValidator<People> validator = ui.getValidator(); - - // customize error table - - JTable errorTable = ui.getErrorTable(); - - PeopleValidatorDataLocator dataLocator = new PeopleValidatorDataLocator(); - - SwingValidatorUtil.installUI(errorTable, - new SwingListValidatorMessageTableRenderer() { - - private static final long serialVersionUID = 1L; - - Decorator<People> decorator - = new DemoDecoratorProvider().getDecoratorByType(People.class); - - @Override - protected String decorateBean(Object bean) { - return decorator.toString(bean); - } - }); - - SwingValidatorUtil.registerListValidator( - validator, - ui.getErrorTableModel(), - dataTable, - errorTable, - dataLocator); - - SwingValidatorUtil.addHightLighterOnEditor( - validator, dataTable, dataLocator, - NuitonValidatorScope.ERROR, - NuitonValidatorScope.WARNING); - - // add some datas in model - - People a = new People("0", "Jack", "Black", 12, "/jaxx/demo/images/jack.jpg"); - People a2 = new People("1", "Héctor", "Jiménez", 28, "/jaxx/demo/images/hector.jpg"); - People a3 = new People("2", "Ana", "de la Reguera", 34, "/jaxx/demo/images/ana.jpg"); - - addPeople(a); - addPeople(a2); - addPeople(a3); - } - - public void addPeople() { - People bean = new People(); - bean.setId(UUID.randomUUID().toString()); - addPeople(bean); - } - - - public void addPeople(People bean) { - PeopleTableModel model = ui.getModel(); - model.addBean(bean); - } - - public void removePeople() { - int selectedRow = ui.getDataTable().getSelectedRow(); - PeopleTableModel model = ui.getModel(); - model.removeBean(selectedRow); - } - - public void updateOkEnabled() { - BeanListValidator<People> validator = ui.getValidator(); - boolean valid = !validator.hasErrors(); - ui.getOk().setEnabled(valid); - } - - private static class PeopleValidatorDataLocator implements SwingListValidatorDataLocator<People> { - - @Override - public boolean acceptType(Class<?> beanType) { - return People.class.isAssignableFrom(beanType); - } - - @Override - public Pair<Integer, Integer> locateDataCell(TableModel tableModel, - People bean, - String fieldName) { - PeopleTableModel model = (PeopleTableModel) tableModel; - - Pair<Integer, Integer> cell = - model.getCell(bean, fieldName); - return cell; - } - - @Override - public int locateBeanRowIndex(TableModel tableModel, People bean) { - PeopleTableModel model = (PeopleTableModel) tableModel; - return model.getBeanIndex(bean); - } - - @Override - public People locateBean(TableModel tableModel, int rowIndex) { - PeopleTableModel model = - (PeopleTableModel) tableModel; - return model.getBean(rowIndex); - } - } - -} - - diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/validation/list/PeopleTableModel.java b/jaxx-demo/src/main/java/jaxx/demo/feature/validation/list/PeopleTableModel.java deleted file mode 100644 index 1e44463..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/validation/list/PeopleTableModel.java +++ /dev/null @@ -1,150 +0,0 @@ -package jaxx.demo.feature.validation.list; -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.collect.Lists; -import jaxx.demo.entities.Identity; -import jaxx.demo.entities.People; -import jaxx.runtime.SwingUtil; -import org.apache.commons.lang3.tuple.Pair; - -import javax.swing.table.AbstractTableModel; -import java.util.Arrays; -import java.util.List; - -/** - * Table model of {@link Identity}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.3 - */ -public class PeopleTableModel extends AbstractTableModel { - - private static final long serialVersionUID = 1L; - - public static final List<String> columnNames = - Arrays.asList(People.PROPERTY_ID, - People.PROPERTY_FIRST_NAME, - People.PROPERTY_LAST_NAME, - People.PROPERTY_AGE); - - public static final Class<?>[] columnClasses = - {String.class, String.class, Integer.class}; - - private final List<People> data = Lists.newArrayList(); - - @Override - public int getRowCount() { - return data.size(); - } - - @Override - public String getColumnName(int column) { - SwingUtil.ensureColumnIndex(this, column); - return columnNames.get(column); - } - - @Override - public int getColumnCount() { - return columnNames.size(); - } - - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - return columnIndex > 0; - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - - SwingUtil.ensureColumnIndex(this, columnIndex); - SwingUtil.ensureRowIndex(this, rowIndex); - - People row = data.get(rowIndex); - if (columnIndex == 0) { - return row.getId(); - } - if (columnIndex == 1) { - return row.getFirstName(); - } - if (columnIndex == 2) { - return row.getLastName(); - } - if (columnIndex == 3) { - return row.getAge(); - } - - // should never come here - return null; - } - - @Override - public void setValueAt(Object aValue, int rowIndex, int columnIndex) { - SwingUtil.ensureColumnIndex(this, columnIndex); - SwingUtil.ensureRowIndex(this, rowIndex); - - People row = data.get(rowIndex); - - if (columnIndex == 0) { - row.setId(String.valueOf(aValue)); - } else if (columnIndex == 1) { - row.setFirstName(String.valueOf(aValue)); - } else if (columnIndex == 2) { - row.setLastName(String.valueOf(aValue)); - } else if (columnIndex == 3) { - row.setAge(Integer.valueOf(aValue.toString())); - } - } - - - public int getBeanIndex(People bean) { - int row = data.indexOf(bean); - return row; - } - - public People getBean(int row) { - SwingUtil.ensureRowIndex(this, row); - People bean = data.get(row); - return bean; - } - - public Pair<Integer, Integer> getCell(People bean, String fieldName) { - - int row = getBeanIndex(bean); - int col = columnNames.indexOf(fieldName); - - Pair<Integer, Integer> cell = Pair.of(row, col); - return cell; - } - - public void removeBean(int selectedRow) { - SwingUtil.ensureRowIndex(this, selectedRow); - data.remove(selectedRow); - fireTableRowsDeleted(selectedRow, selectedRow); - } - - public void addBean(People bean) { - data.add(bean); - int newrowIndex = data.size() - 1; - fireTableRowsInserted(newrowIndex, newrowIndex); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/validation/simple/SimpleBeanValidationByListDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/feature/validation/simple/SimpleBeanValidationByListDemo.jaxx deleted file mode 100644 index 8e9eb33..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/validation/simple/SimpleBeanValidationByListDemo.jaxx +++ /dev/null @@ -1,372 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - <style source="Validation.jcss"/> - - <import> - javax.swing.JOptionPane - static org.nuiton.i18n.I18n.n - jaxx.demo.entities.Identity - jaxx.demo.entities.Model - jaxx.runtime.validator.swing.SwingValidatorMessageListRenderer - jaxx.runtime.validator.swing.SwingValidatorMessageListModel - - java.io.File - </import> - - <script><![CDATA[ -@Override -protected String[] getSources() { - return addDefaultSources( - "Validation.css", - "/jaxx.demo.entities.Identity.java", - "/jaxx.demo.entities.Identity-error-validation.xml", - "/jaxx.demo.entities.Identity-info-validation.xml", - "/jaxx.demo.entities.Identity-warning-validation.xml", - "/jaxx.demo.entities.Model.java", - "/jaxx.demo.entities.Model-error-validation.xml", - "/jaxx.demo.entities.Model-info-validation.xml", - "/jaxx.demo.entities.Model-warning-validation.xml" - ); -} -]]> - </script> - <!-- models --> - <Model id='model1'/> - <Model id='model2'/> - <Identity id='identity'/> - - <!-- errors model --> - <SwingValidatorMessageListModel id='errorListModel' - onContentsChanged='ok.setEnabled(errorListModel.isEmpty())'/> - - <!-- validators --> - <BeanValidator id='validator' bean='model1' - uiClass="jaxx.runtime.validator.swing.ui.ImageValidationUI"> - <field name="text"/> - <field name="text2"/> - <field name="ratio"/> - </BeanValidator> - <BeanValidator id='validator2' bean='model2' - uiClass="jaxx.runtime.validator.swing.ui.IconValidationUI"> - <field name="text" component="_text"/> - <field name="text2" component="_text2"/> - <field name="ratio" component="_ratio"/> - </BeanValidator> - <BeanValidator id='validator3' autoField='true' bean='identity' - uiClass="jaxx.runtime.validator.swing.ui.TranslucentValidationUI"> - <field name="email" component="email2"/> - </BeanValidator> - - <Table fill='both' constraints='BorderLayout.CENTER'> - <row> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Form")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='Text:'/> - </cell> - <cell weightx='1'> - <JTextField id='text' text='{model1.getText()}' - _validatorLabel='{n("form.text")}' - onKeyReleased='model1.setText(text.getText())'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Text2:'/> - </cell> - <cell weightx='1'> - <JTextField id='text2' text='{model1.getText2()}' - _validatorLabel='{n("form.text2")}' - onKeyReleased='model1.setText2(text2.getText())'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Ratio:'/> - </cell> - <cell> - <JSlider id='ratio' minimum='0' maximum='100' - value='{model1.getRatio()}' - _validatorLabel='{n("form.ratio")}' - onStateChanged='model1.setRatio(ratio.getValue())'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Model")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='Text:'/> - </cell> - <cell weightx='1'> - <JLabel text='{model1.getText()}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Text2:'/> - </cell> - <cell weightx='1'> - <JLabel text='{model1.getText2()}'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Ratio:'/> - </cell> - <cell> - <JLabel text='{model1.getRatio()+""}'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - </row> - <row> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Form2")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='Text:'/> - </cell> - <cell weightx='1'> - <JTextField id='_text' text='{model2.getText()}' - _validatorLabel='{n("form2.text")}' - onKeyReleased='model2.setText(_text.getText())'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Text2:'/> - </cell> - <cell weightx='1'> - <JTextField id='_text2' text='{model2.getText2()}' - _validatorLabel='{n("form2.text2")}' - onKeyReleased='model2.setText2(_text2.getText())'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Ratio:'/> - </cell> - <cell> - <JSlider id='_ratio' minimum='0' maximum='100' - value='{model2.getRatio()}' - _validatorLabel='{n("form2.ratio")}' - onStateChanged='model2.setRatio(_ratio.getValue())'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Model2")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='Text:'/> - </cell> - <cell weightx='1'> - <JLabel text='{model2.getText()}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Text2:'/> - </cell> - <cell weightx='1'> - <JLabel text='{model2.getText2()}'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Ratio:'/> - </cell> - <cell> - <JLabel text='{model2.getRatio()+""}'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - </row> - <row> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Identify Form")}' - layout='{new GridLayout()}' width='250' height='180'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='FirstName:'/> - </cell> - <cell weightx='1'> - <JTextField id='firstName' text='{identity.getFirstName()}' - onKeyReleased='identity.setFirstName(firstName.getText())'/> - </cell> - </row> - <row> - <cell> - <JLabel text='LastName:'/> - </cell> - <cell weightx='1'> - <JTextField id='lastName' text='{identity.getLastName()}' - onKeyReleased='identity.setLastName(lastName.getText())'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Email:'/> - </cell> - <cell weightx='1'> - <JTextField id='email2' text='{identity.getEmail()}' - onKeyReleased='identity.setEmail(email2.getText())'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Age:'/> - </cell> - <cell> - <JSlider id='age' minimum='0' maximum='100' - value='{identity.getAge()}' - onStateChanged='identity.setAge(age.getValue())'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Config file :'/> - </cell> - <cell> - <JTextField id='config' text='{identity.getConfig()+""}' - onKeyReleased='identity.setConfig(new File(config.getText()))'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Working directory:'/> - </cell> - <cell> - <JTextField id='dir' text='{identity.getDir()+""}' - onKeyReleased='identity.setDir(new File(dir.getText()))'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Identity Model")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='FirstName:'/> - </cell> - <cell weightx='1'> - <JLabel text='{identity.getFirstName()}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='LastName:'/> - </cell> - <cell weightx='1'> - <JLabel text='{identity.getLastName()}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Email:'/> - </cell> - <cell weightx='1'> - <JLabel text='{identity.getEmail()}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Age:'/> - </cell> - <cell> - <JLabel text='{identity.getAge()+""}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Config file:'/> - </cell> - <cell> - <JLabel text='{identity.getConfig()+""}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Directory file:'/> - </cell> - <cell> - <JLabel text='{identity.getDir()+""}'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - </row> - <row> - <cell columns='2' fill="both"> - <JPanel border='{BorderFactory.createTitledBorder("Messages")}' - layout='{new GridLayout()}' height='200' - width='500'> - <JScrollPane> - <JList id='errorList' model='{errorListModel}' - cellRenderer='{new SwingValidatorMessageListRenderer()}'/> - </JScrollPane> - </JPanel> - </cell> - </row> - <row> - <cell columns='2' fill="both"> - <JPanel layout='{new GridLayout(1,2,0,0)}'> - <JButton id='cancel' text='cancel' - onActionPerformed='JOptionPane.showMessageDialog(this, cancel.getText() + " clicked!", "onActionPerformed", JOptionPane.INFORMATION_MESSAGE);'/> - <JButton id='ok' text='valid' - onActionPerformed='JOptionPane.showMessageDialog(this, ok.getText() + " clicked!", "onActionPerformed", JOptionPane.INFORMATION_MESSAGE);'/> - </JPanel> - </cell> - </row> - </Table> - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/validation/simple/SimpleBeanValidationByTableDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/feature/validation/simple/SimpleBeanValidationByTableDemo.jaxx deleted file mode 100644 index 4f51ed8..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/feature/validation/simple/SimpleBeanValidationByTableDemo.jaxx +++ /dev/null @@ -1,381 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - <style source="Validation.jcss"/> - - <import> - javax.swing.JOptionPane - static org.nuiton.i18n.I18n.n - jaxx.demo.entities.Identity - jaxx.demo.entities.Model - jaxx.runtime.validator.swing.SwingValidatorUtil - jaxx.runtime.validator.swing.SwingValidatorMessageTableRenderer - jaxx.runtime.validator.swing.SwingValidatorMessageTableModel - - java.io.File - </import> - - <script><![CDATA[ -void $afterCompleteSetup() { - SwingValidatorUtil.installUI(errorTable, new SwingValidatorMessageTableRenderer()); -} - -@Override -protected String[] getSources() { - return addDefaultSources ( - "Validation.css", - "/jaxx.demo.entities.Identity.java", - "/jaxx.demo.entities.Identity-error-validation.xml", - "/jaxx.demo.entities.Identity-info-validation.xml", - "/jaxx.demo.entities.Identity-warning-validation.xml", - "/jaxx.demo.entities.Model.java", - "/jaxx.demo.entities.Model-error-validation.xml", - "/jaxx.demo.entities.Model-info-validation.xml", - "/jaxx.demo.entities.Model-warning-validation.xml" - ); -} -]]></script> - - <!-- models --> - <Model id='model1'/> - <Model id='model2'/> - <Identity id='identity'/> - - <!-- errors model --> - <SwingValidatorMessageTableModel id='errorTableModel' - onTableChanged='ok.setEnabled(errorTableModel.getRowCount()==0)'/> - - <!-- validators --> - <BeanValidator id='validator' bean='model1' - uiClass="jaxx.runtime.validator.swing.ui.ImageValidationUI"> - <field name="text"/> - <field name="text2"/> - <field name="ratio"/> - </BeanValidator> - <BeanValidator id='validator2' bean='model2' - uiClass="jaxx.runtime.validator.swing.ui.IconValidationUI"> - <field name="text" component="_text"/> - <field name="text2" component="_text2"/> - <field name="ratio" component="_ratio"/> - </BeanValidator> - <BeanValidator id='validator3' autoField='true' bean='identity' - uiClass="jaxx.runtime.validator.swing.ui.TranslucentValidationUI"> - <field name="email" component="email2"/> - </BeanValidator> - - <Table fill='both' constraints='BorderLayout.CENTER'> - <row> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Form")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='Text:'/> - </cell> - <cell weightx='1'> - <JTextField id='text' text='{model1.getText()}' - onKeyReleased='model1.setText(text.getText())' - _validatorLabel='{n("form.text")}' - /> - </cell> - </row> - <row> - <cell> - <JLabel text='Text2:'/> - </cell> - <cell weightx='1'> - <JTextField id='text2' text='{model1.getText2()}' - onKeyReleased='model1.setText2(text2.getText())' - _validatorLabel='{n("form.text2")}' - /> - </cell> - </row> - - <row> - <cell> - <JLabel text='Ratio:'/> - </cell> - <cell> - <JSlider id='ratio' minimum='0' maximum='100' - value='{model1.getRatio()}' - _validatorLabel='{n("form.ratio")}' - onStateChanged='model1.setRatio(ratio.getValue())'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Model")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='Text:'/> - </cell> - <cell weightx='1'> - <JLabel text='{model1.getText()}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Text2:'/> - </cell> - <cell weightx='1'> - <JLabel text='{model1.getText2()}'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Ratio:'/> - </cell> - <cell> - <JLabel text='{model1.getRatio()+""}'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - </row> - <row> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Form2")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='Text:'/> - </cell> - <cell weightx='1'> - <JTextField id='_text' text='{model2.getText()}' - _validatorLabel='{n("form2.text")}' - onKeyReleased='model2.setText(_text.getText())'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Text2:'/> - </cell> - <cell weightx='1'> - <JTextField id='_text2' text='{model2.getText2()}' - _validatorLabel='{n("form2.text2")}' - onKeyReleased='model2.setText2(_text2.getText())'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Ratio:'/> - </cell> - <cell> - <JSlider id='_ratio' minimum='0' maximum='100' - value='{model2.getRatio()}' - _validatorLabel='{n("form2.ratio")}' - onStateChanged='model2.setRatio(_ratio.getValue())'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Model2")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='Text:'/> - </cell> - <cell weightx='1'> - <JLabel text='{model2.getText()}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Text2:'/> - </cell> - <cell weightx='1'> - <JLabel text='{model2.getText2()}'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Ratio:'/> - </cell> - <cell> - <JLabel text='{model2.getRatio()+""}'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - </row> - <row> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Identify Form")}' - layout='{new GridLayout()}' width='250' height='180'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='FirstName:'/> - </cell> - <cell weightx='1'> - <JTextField id='firstName' text='{identity.getFirstName()}' - onKeyReleased='identity.setFirstName(firstName.getText())'/> - </cell> - </row> - <row> - <cell> - <JLabel text='LastName:'/> - </cell> - <cell weightx='1'> - <JTextField id='lastName' text='{identity.getLastName()}' - onKeyReleased='identity.setLastName(lastName.getText())'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Email:'/> - </cell> - <cell weightx='1'> - <JTextField id='email2' text='{identity.getEmail()}' - onKeyReleased='identity.setEmail(email2.getText())'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Age:'/> - </cell> - <cell> - <JSlider id='age' minimum='0' maximum='100' - value='{identity.getAge()}' - onStateChanged='identity.setAge(age.getValue())'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Config file :'/> - </cell> - <cell> - <JTextField id='config' text='{identity.getConfig()+""}' - onKeyReleased='identity.setConfig(new File(config.getText()))'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Working directory:'/> - </cell> - <cell> - <JTextField id='dir' text='{identity.getDir()+""}' - onKeyReleased='identity.setDir(new File(dir.getText()))'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Identity Model")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='FirstName:'/> - </cell> - <cell weightx='1'> - <JLabel text='{identity.getFirstName()}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='LastName:'/> - </cell> - <cell weightx='1'> - <JLabel text='{identity.getLastName()}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Email:'/> - </cell> - <cell weightx='1'> - <JLabel text='{identity.getEmail()}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Age:'/> - </cell> - <cell> - <JLabel text='{identity.getAge()+""}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Config file:'/> - </cell> - <cell> - <JLabel text='{identity.getConfig()+""}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Directory file:'/> - </cell> - <cell> - <JLabel text='{identity.getDir()+""}'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - </row> - <row> - <cell columns='2' fill="both"> - <JPanel border='{BorderFactory.createTitledBorder("Messages")}' - layout='{new GridLayout()}' height='200' - width='500'> - <JScrollPane columnHeaderView='{errorTable.getTableHeader()}'> - <JTable id='errorTable' model='{errorTableModel}' rowSelectionAllowed='true' - autoCreateRowSorter='true' - autoResizeMode='2' cellSelectionEnabled='false' - selectionMode='0'/> - </JScrollPane> - </JPanel> - </cell> - </row> - <row> - <cell columns='2' fill="both"> - <JPanel layout='{new GridLayout(1,2,0,0)}'> - <JButton id='cancel' text='cancel' - onActionPerformed='JOptionPane.showMessageDialog(this, cancel.getText() + " clicked!", "onActionPerformed", JOptionPane.INFORMATION_MESSAGE);'/> - <JButton id='ok' text='valid' - onActionPerformed='JOptionPane.showMessageDialog(this, ok.getText() + " clicked!", "onActionPerformed", JOptionPane.INFORMATION_MESSAGE);'/> - </JPanel> - </cell> - </row> - </Table> - -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorDemo.jaxx deleted file mode 100644 index 49a1303..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorDemo.jaxx +++ /dev/null @@ -1,143 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - java.awt.Color - javax.swing.BorderFactory - javax.swing.border.BevelBorder - </import> - - <!--<style source='CalculatorDemo.jcss'/>--> - <script><![CDATA[ - plus.setText("+"); - sign.setText("+/-"); - -@Override -protected String[] getSources() { - return addDefaultSources( "CalculatorEngine.java" ); -} -]]> - </script> - <!-- use fully-qualified name just in case this is compiled into a different package --> - <CalculatorEngine id='engine'/> - - <Table fill='both'> - <row> - <cell columns='4'> - <JLabel id='display' text='{engine.getDisplayText()}'/> - </cell> - </row> - - <row> - <cell columns='2'> - <JButton id='c' text='C' onActionPerformed='engine.clear()' - styleClass='clear'/> - </cell> - <cell> - <JButton id='ce' text='CE' onActionPerformed='engine.clearEntry()' - styleClass='clear'/> - </cell> - <cell> - <JButton id='equals' text='=' onActionPerformed='engine.equal()' - styleClass='operator'/> - </cell> - </row> - - <row> - <cell> - <JButton id='d7' text='7' onActionPerformed='engine.digit(7)' - styleClass='digit'/> - </cell> - <cell> - <JButton id='d8' text='8' onActionPerformed='engine.digit(8)' - styleClass='digit'/> - </cell> - <cell> - <JButton id='d9' text='9' onActionPerformed='engine.digit(9)' - styleClass='digit'/> - </cell> - <cell> - <JButton id='plus' onActionPerformed='engine.add()' - styleClass='operator'/> - </cell> - </row> - - <row> - <cell> - <JButton id='d4' text='4' onActionPerformed='engine.digit(4)' - styleClass='digit'/> - </cell> - <cell> - <JButton id='d5' text='5' onActionPerformed='engine.digit(5)' - styleClass='digit'/> - </cell> - <cell> - <JButton id='d6' text='6' onActionPerformed='engine.digit(6)' - styleClass='digit'/> - </cell> - <cell> - <JButton id='subtract' text='-' onActionPerformed='engine.subtract()' - styleClass='operator'/> - </cell> - </row> - - <row> - <cell> - <JButton id='d1' text='1' onActionPerformed='engine.digit(1)' - styleClass='digit'/> - </cell> - <cell> - <JButton id='d2' text='2' onActionPerformed='engine.digit(2)' - styleClass='digit'/> - </cell> - <cell> - <JButton id='d3' text='3' onActionPerformed='engine.digit(3)' - styleClass='digit'/> - </cell> - <cell> - <JButton id='multiply' text='x' onActionPerformed='engine.multiply()' - styleClass='operator'/> - </cell> - </row> - - <row> - <cell> - <JButton id='d0' text='0' onActionPerformed='engine.digit(0)' - styleClass='digit'/> - </cell> - <cell> - <JButton id='sign' onActionPerformed='engine.toggleSign()' - styleClass='operator'/> - </cell> - <cell> - <JButton id='dot' text='.' onActionPerformed='engine.dot()' - styleClass='digit'/> - </cell> - <cell> - <JButton id='divide' text='÷' onActionPerformed='engine.divide()' - styleClass='operator'/> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorEngine.java b/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorEngine.java deleted file mode 100644 index b805f66..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorEngine.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.fun; - -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.math.BigDecimal; - -public class CalculatorEngine { - public static final String DISPLAY_TEXT_PROPERTY = "displayText"; - - public static final int ADD = 0; - - public static final int SUBTRACT = 1; - - public static final int MULTIPLY = 2; - - public static final int DIVIDE = 3; - - public static final int RESULT = 4; - - private int operation = -1; - - private boolean clear = true; // true to clear on next key - - private String displayText = "0"; - - private BigDecimal value; - - private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); - - - public String getDisplayText() { - return displayText; - } - - - public void setDisplayText(String displayText) { - String oldDisplayText = this.displayText; - this.displayText = displayText; - firePropertyChange(DISPLAY_TEXT_PROPERTY, oldDisplayText, displayText); - } - - - public void clear() { - clearEntry(); - value = new BigDecimal(0); - operation = -1; - } - - - public void clearEntry() { - setDisplayText("0"); - clear = true; - } - - - private void checkClear() { - if (clear) { - setDisplayText(""); - clear = false; - } - } - - - public void digit(int digit) { - checkClear(); - setDisplayText(getDisplayText() + String.valueOf(digit)); - } - - - public void dot() { - checkClear(); - if (getDisplayText().indexOf('.') == -1) { - if (getDisplayText().length() == 0) { - setDisplayText("0."); - } else { - setDisplayText(getDisplayText() + '.'); - } - } - } - - - public void toggleSign() { - String text = getDisplayText(); - if (text.startsWith("-")) { - text = text.substring(1); - } else if (!text.equals("0")) { - text = '-' + text; - } - setDisplayText(text); - } - - - public void equal() { - BigDecimal displayValue = new BigDecimal(getDisplayText()); - BigDecimal newValue = displayValue; - switch (operation) { - case ADD: - newValue = value.add(displayValue); - break; - case SUBTRACT: - newValue = value.subtract(displayValue); - break; - case MULTIPLY: - newValue = value.multiply(displayValue); - break; - case DIVIDE: - newValue = value.divide(displayValue, 8, BigDecimal.ROUND_HALF_UP); - break; - } - value = newValue; - setDisplayText(toString(newValue)); - clear = true; - operation = -1; - } - - - public static String toString(BigDecimal decimal) { - // can't use stripTrailingZeros, as it wasn't introduced until 1.5 - String result = decimal.toString(); - if (result.indexOf(".") != -1) { - while (result.endsWith("0")) { - result = result.substring(0, result.length() - 1); - } - if (result.endsWith(".")) { - result = result.substring(0, result.length() - 1); - } - } - return result; - } - - - public void operation(int operation) { - if (this.operation != -1) { - equal(); - } else { - value = new BigDecimal(getDisplayText()); - clear = true; - } - this.operation = operation; - } - - - public void add() { - operation(ADD); - } - - - public void subtract() { - operation(SUBTRACT); - } - - - public void multiply() { - operation(MULTIPLY); - } - - - public void divide() { - operation(DIVIDE); - } - - - public void addPropertyChangeListener(PropertyChangeListener listener) { - propertyChangeSupport.addPropertyChangeListener(listener); - } - - - public void addPropertyChangeListener(String property, PropertyChangeListener listener) { - propertyChangeSupport.addPropertyChangeListener(property, listener); - } - - - public void removePropertyChangeListener(PropertyChangeListener listener) { - propertyChangeSupport.removePropertyChangeListener(listener); - } - - - public void removePropertyChangeListener(String property, PropertyChangeListener listener) { - propertyChangeSupport.removePropertyChangeListener(property, listener); - } - - - protected void firePropertyChange(String property, Object oldValue, Object newValue) { - propertyChangeSupport.firePropertyChange(property, oldValue, newValue); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/fun/CounterDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/fun/CounterDemo.jaxx deleted file mode 100644 index 5bb8c82..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/fun/CounterDemo.jaxx +++ /dev/null @@ -1,31 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel> - <script>int count;</script> - <JTextField text='{count+""}' constraints='BorderLayout.NORTH'/> - <HBox constraints='BorderLayout.SOUTH'> - <JButton text='Dec (-)' onActionPerformed='count--'/> - <JButton text='Reset' onActionPerformed='count = 0'/> - <JButton text='Inc (+)' onActionPerformed='count++'/> - </HBox> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/fun/LabelStyleDemo.jaxx b/jaxx-demo/src/main/java/jaxx/demo/fun/LabelStyleDemo.jaxx deleted file mode 100644 index 4b06ab3..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/fun/LabelStyleDemo.jaxx +++ /dev/null @@ -1,121 +0,0 @@ -<!-- - #%L - JAXX :: Demo - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> - - <import> - java.awt.Color - javax.swing.BorderFactory - </import> - - <Table id='demoPanel' anchor='north' fill='both'> - <row> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='Text:'/> - </cell> - <cell weightx='1'> - <JTextField id='text' text='Data Binding'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Red:'/> - </cell> - <cell> - <JSlider id='red' value='128' maximum='255' styleClass='color'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Green:'/> - </cell> - <cell> - <JSlider id='green' value='0' maximum='255' styleClass='color'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Blue:'/> - </cell> - <cell> - <JSlider id='blue' value='255' maximum='255' styleClass='color'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Size:'/> - </cell> - <cell> - <JSlider id='dummySize' value='36' minimum='6' maximum='60'/> - </cell> - </row> - - <row> - <cell columns='2' fill='both' weighty='1'> - <JPanel border='{BorderFactory.createTitledBorder("Preview")}' - height='90' - layout='{new BorderLayout()}'> - <VBox - background='{(Color)( backgroundCheckbox.isSelected() ? backgroundColor.getSelectedValue() : null)}' - margin='0' - horizontalAlignment='center' - verticalAlignment='middle'> - <JLabel text='{text.getText()}' - font-size='{dummySize.getValue()}' - foreground='{new Color(red.getValue(), green.getValue(), blue.getValue())}'/> - </VBox> - </JPanel> - </cell> - </row> - </Table> - </cell> - - <cell> - <VBox spacing='0' - border='{BorderFactory.createTitledBorder("Background")}'> - <JCheckBox id='backgroundCheckbox' text='Show Background'/> - <JRadioButton text='Red' buttonGroup='backgroundColor' - value='{Color.RED}' selected='true'/> - <JRadioButton text='Orange' buttonGroup='backgroundColor' - value='{Color.ORANGE}'/> - <JRadioButton text='Yellow' buttonGroup='backgroundColor' - value='{Color.YELLOW}'/> - <JRadioButton text='Green' buttonGroup='backgroundColor' - value='{Color.GREEN}'/> - <JRadioButton text='Cyan' buttonGroup='backgroundColor' - value='{Color.CYAN}'/> - <JRadioButton text='Blue' buttonGroup='backgroundColor' - value='{Color.BLUE}'/> - <JRadioButton text='Purple' buttonGroup='backgroundColor' - value='{new Color(160, 30, 255)}'/> - </VBox> - </cell> - </row> - </Table> -</jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/tree/DemoCellRenderer.java b/jaxx-demo/src/main/java/jaxx/demo/tree/DemoCellRenderer.java deleted file mode 100644 index f53565f..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/tree/DemoCellRenderer.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.tree; - -import jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.JTree; -import javax.swing.tree.DefaultTreeModel; -import java.awt.Component; - -import static org.nuiton.i18n.I18n.t; - -/** - * @author Sylvain Lletellier - * @since 2.1 - */ -public class DemoCellRenderer extends AbstractNavTreeCellRenderer<DefaultTreeModel, DemoNode> { - - /** Logger */ - protected static final Log log = - LogFactory.getLog(DemoCellRenderer.class); - - - public DemoCellRenderer(jaxx.demo.tree.DemoDataProvider provider) { - setDataProvider(provider); - } - - @Override - public jaxx.demo.entities.DemoDataProvider getDataProvider() { - return (jaxx.demo.entities.DemoDataProvider) super.getDataProvider(); - } - - @Override - protected String computeNodeText(DemoNode node) { - - if (node == null) { - return ""; - } - - - String toDecorate; - - String id = node.getId(); - - if (node.isStringNode()) { - - // String node - toDecorate = t(id); - } else { - - // Demo node - toDecorate = id; - } - - if (log.isDebugEnabled()) { - log.debug("Compute text for node " + node + - " (" + node.getInternalClass() + ") = " + toDecorate); - } - - return toDecorate; - } - - @Override - public Component getTreeCellRendererComponent(JTree tree, - Object value, - boolean sel, - boolean expanded, - boolean leaf, int row, - boolean hasFocus) { - - if (!(value instanceof DemoNode)) { - return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); - } - - // get node - DemoNode node = (DemoNode) value; - - // get text for node - String text = getNodeText(node); - - // Render node - return super.getTreeCellRendererComponent(tree, text, sel, expanded, leaf, row, hasFocus); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/tree/DemoDataProvider.java b/jaxx-demo/src/main/java/jaxx/demo/tree/DemoDataProvider.java deleted file mode 100644 index 7f5e635..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/tree/DemoDataProvider.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.tree; - -import jaxx.demo.component.jaxx.BoxedDecoratorDemo; -import jaxx.demo.component.jaxx.StatusMessagePanelDemo; -import jaxx.demo.component.jaxx.editor.BeanComboBoxDemo; -import jaxx.demo.component.jaxx.editor.BeanDoubleListDemo; -import jaxx.demo.component.jaxx.editor.BeanFilterableComboBoxDemo; -import jaxx.demo.component.jaxx.editor.ComboEditorDemo; -import jaxx.demo.component.jaxx.editor.DatePickerDemo; -import jaxx.demo.component.jaxx.editor.FileEditorDemo; -import jaxx.demo.component.jaxx.editor.I18nEditorDemo; -import jaxx.demo.component.jaxx.editor.ListSelectorDemo; -import jaxx.demo.component.jaxx.editor.SimpleTimeEditorDemo; -import jaxx.demo.component.jaxx.editor.gis.CoordinateDemo; -import jaxx.demo.component.jaxx.widgets.datetime.DateTimeEditorDemo; -import jaxx.demo.component.jaxx.widgets.datetime.TimeEditorDemo; -import jaxx.demo.component.jaxx.widgets.gis.CoordinatesEditorDemo; -import jaxx.demo.component.jaxx.widgets.number.NumberEditorDemo; -import jaxx.demo.component.jaxx.widgets.select.FilterableDoubleListDemo; -import jaxx.demo.component.swing.HidorButtonDemo; -import jaxx.demo.component.swing.JButtonDemo; -import jaxx.demo.component.swing.JCheckBoxDemo; -import jaxx.demo.component.swing.JCheckBoxMenuItemDemo; -import jaxx.demo.component.swing.JComboBoxDemo; -import jaxx.demo.component.swing.JDialogDemo; -import jaxx.demo.component.swing.JListDemo; -import jaxx.demo.component.swing.JMenuItemDemo; -import jaxx.demo.component.swing.JPasswordFieldDemo; -import jaxx.demo.component.swing.JProgressBarDemo; -import jaxx.demo.component.swing.JRadioButtonDemo; -import jaxx.demo.component.swing.JRadioButtonMenuItemDemo; -import jaxx.demo.component.swing.JSliderDemo; -import jaxx.demo.component.swing.JSpinnerDemo; -import jaxx.demo.component.swing.JSplitPaneDemo; -import jaxx.demo.component.swing.JTextAreaDemo; -import jaxx.demo.component.swing.JTextFieldDemo; -import jaxx.demo.component.swing.JToggleButtonDemo; -import jaxx.demo.feature.databinding.BeanDataBindingDemo; -import jaxx.demo.feature.databinding.BindingExtremeDemo; -import jaxx.demo.feature.nav.NavDemo; -import jaxx.demo.feature.validation.list.ListBeanValidationDemo; -import jaxx.demo.feature.validation.simple.SimpleBeanValidationByListDemo; -import jaxx.demo.feature.validation.simple.SimpleBeanValidationByTableDemo; -import jaxx.demo.fun.CalculatorDemo; -import jaxx.demo.fun.CounterDemo; -import jaxx.demo.fun.LabelStyleDemo; -import jaxx.runtime.swing.nav.NavDataProvider; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.nuiton.i18n.I18n.n; - -/** - * Data provider of the navigation tree. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.1 - */ -public class DemoDataProvider implements NavDataProvider { - - /** Logger */ - static private final Log log = LogFactory.getLog(DemoDataProvider.class); - - /** mapping of demo per package */ - protected Map<String, List<Object>> mapping; - - public DemoDataProvider() { - - mapping = new HashMap<String, List<Object>>(); - - if (log.isDebugEnabled()) { - log.debug("for " + this); - } - - addMapping("jaxxdemo.tree", - n("jaxxdemo.component.swing"), - n("jaxxdemo.component.jaxx"), - n("jaxxdemo.feature"), - n("jaxxdemo.fun") - ); - - addMapping(n("jaxxdemo.component.swing"), - n("jaxxdemo.component.swing.buttons"), - n("jaxxdemo.component.swing.form"), - n("jaxxdemo.component.swing.layout"), - n("jaxxdemo.component.swing.menu"), - n("jaxxdemo.component.swing.window"), - JProgressBarDemo.class - ); - - addMapping(n("jaxxdemo.component.swing.buttons"), - JButtonDemo.class, - JCheckBoxDemo.class, - JRadioButtonDemo.class, - JToggleButtonDemo.class - ); - - addMapping(n("jaxxdemo.component.swing.form"), - n("jaxxdemo.component.swing.form.text"), - JComboBoxDemo.class, - JListDemo.class, - JSliderDemo.class, - JSpinnerDemo.class - ); - - addMapping(n("jaxxdemo.component.swing.form.text"), - JPasswordFieldDemo.class, - JTextFieldDemo.class, - JTextAreaDemo.class - ); - - addMapping(n("jaxxdemo.component.swing.layout"), - JSplitPaneDemo.class - ); - - addMapping(n("jaxxdemo.component.swing.menu"), - JMenuItemDemo.class, - JCheckBoxMenuItemDemo.class, - JRadioButtonMenuItemDemo.class - ); - - addMapping(n("jaxxdemo.component.swing.window"), - JDialogDemo.class - ); - - addMapping(n("jaxxdemo.component.jaxx"), - HidorButtonDemo.class, - n("jaxxdemo.component.jaxx.widgets"), - n("jaxxdemo.component.jaxx.editor"), - StatusMessagePanelDemo.class, - BoxedDecoratorDemo.class - ); - - addMapping(n("jaxxdemo.component.jaxx.widgets"), - n("jaxxdemo.component.jaxx.widgets.number"), - n("jaxxdemo.component.jaxx.widgets.select"), - n("jaxxdemo.component.jaxx.widgets.gis"), - n("jaxxdemo.component.jaxx.widgets.datetime") - ); - - addMapping(n("jaxxdemo.component.jaxx.widgets.number"), - NumberEditorDemo.class - ); - - addMapping(n("jaxxdemo.component.jaxx.widgets.select"), - FilterableDoubleListDemo.class - ); - - addMapping(n("jaxxdemo.component.jaxx.widgets.gis"), - CoordinatesEditorDemo.class - ); - - addMapping(n("jaxxdemo.component.jaxx.widgets.datetime"), - DateTimeEditorDemo.class, - TimeEditorDemo.class - ); - - addMapping(n("jaxxdemo.component.jaxx.editor"), - jaxx.demo.component.jaxx.editor.TimeEditorDemo.class, - SimpleTimeEditorDemo.class, - jaxx.demo.component.jaxx.editor.NumberEditorDemo.class, - ComboEditorDemo.class, - I18nEditorDemo.class, - DatePickerDemo.class, - FileEditorDemo.class, - ListSelectorDemo.class, - BeanComboBoxDemo.class, - BeanFilterableComboBoxDemo.class, - BeanDoubleListDemo.class, - CoordinateDemo.class - ); - - addMapping(n("jaxxdemo.feature"), - n("jaxxdemo.feature.databinding"), - n("jaxxdemo.feature.validation"), - n("jaxxdemo.feature.nav") - ); - - addMapping(n("jaxxdemo.feature.databinding"), - BindingExtremeDemo.class, - BeanDataBindingDemo.class - ); - - addMapping(n("jaxxdemo.feature.validation"), - n("jaxxdemo.feature.simple.validation"), - n("jaxxdemo.feature.list.validation") - ); - - addMapping(n("jaxxdemo.feature.simple.validation"), - SimpleBeanValidationByListDemo.class, - SimpleBeanValidationByTableDemo.class - ); - - addMapping(n("jaxxdemo.feature.list.validation"), - ListBeanValidationDemo.class - ); - addMapping(n("jaxxdemo.feature.nav"), - NavDemo.class - ); - - addMapping(n("jaxxdemo.fun"), - LabelStyleDemo.class, - CounterDemo.class, - CalculatorDemo.class - ); - } - - protected void addMapping(String packageName, Object... classes) { - List<Object> list = Arrays.asList(classes); - if (log.isDebugEnabled()) { - log.debug("Adding mapping [" + packageName + "] : " + list); - } - mapping.put(packageName, list); - } - - @Override - public boolean isEnabled() { - return true; - } - - public List<Object> getImplementations(String packageName) { - return mapping.get(packageName); - } - - -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/tree/DemoNode.java b/jaxx-demo/src/main/java/jaxx/demo/tree/DemoNode.java deleted file mode 100644 index 5590c97..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/tree/DemoNode.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.tree; - -import jaxx.runtime.swing.nav.tree.NavTreeNode; - -/** - * Basic node of the demo. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.1 - */ -public class DemoNode extends NavTreeNode<DemoNode> { - - private static final long serialVersionUID = 1L; - - public DemoNode(String id) { - super(String.class, - id, - null, - DemoTreeHelper.getChildLoador(DemoNodeLoador.class) - ); - } - - @Override - public DemoNode getContainerNode() { - if (isStringNode()) { - // on est sur un noeud de type String, donc on regarde sur le parent - return this; - } - - // fallback (should never comme here since root is Stringnode) - if (isRoot()) { - // si on arrive sur le root, quelque chose ne va pas, - // on bloque par null, a defaut de declancher une exception - return null; - } - - // cas final : sur un noeud de donnee + classe interne de donnee - return getParent().getContainerNode(); - } - - public DemoNode(Class<?> internalClass) { - super(internalClass, internalClass.getSimpleName(), null, null); - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/tree/DemoNodeLoador.java b/jaxx-demo/src/main/java/jaxx/demo/tree/DemoNodeLoador.java deleted file mode 100644 index b4e5ea4..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/tree/DemoNodeLoador.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.tree; - -import jaxx.runtime.swing.nav.NavDataProvider; -import jaxx.runtime.swing.nav.NavNodeChildLoador; -import jaxx.runtime.swing.nav.tree.NavTreeNodeChildLoador; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.List; - -/** - * @author Tony Chemit - chemit@codelutin.com - * @since 2.1 - */ -public class DemoNodeLoador extends NavTreeNodeChildLoador<Object, Object, DemoNode> { - - private static final long serialVersionUID = 1L; - - /** Logger */ - static private final Log log = LogFactory.getLog(NavNodeChildLoador.class); - - public DemoNodeLoador() { - super(Object.class); - } - - @Override - public List<Object> getData(Class<?> parentClass, - String packageName, - NavDataProvider dataProvider) throws Exception { - - DemoDataProvider provider = (DemoDataProvider) dataProvider; - List<Object> implementations = provider.getImplementations(packageName); - return implementations; - } - - @Override - public DemoNode createNode(Object data, NavDataProvider dataProvider) { - - if (log.isDebugEnabled()) { - log.debug("Creating node for object : " + data); - } - - DemoNode node = null; - - if (data instanceof String) { - // package node - node = new DemoNode((String) data); - } - - if (data instanceof Class<?>) { - // demo node - node = new DemoNode((Class<?>) data); - } - - if (node == null) { - throw new IllegalArgumentException("Data [" + data + "] can not be use to build a node"); - } - - - return node; - } -} diff --git a/jaxx-demo/src/main/java/jaxx/demo/tree/DemoTreeHelper.java b/jaxx-demo/src/main/java/jaxx/demo/tree/DemoTreeHelper.java deleted file mode 100644 index 8253f4d..0000000 --- a/jaxx-demo/src/main/java/jaxx/demo/tree/DemoTreeHelper.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo.tree; - -import jaxx.runtime.swing.nav.tree.NavTreeHelper; - -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreeModel; - -/** - * @author Tony Chemit - chemit@codelutin.com - * @since 2.1 - */ -public class DemoTreeHelper extends NavTreeHelper<DemoNode> { - - public DemoTreeHelper(DemoDataProvider provider) { - setDataProvider(provider); - } - - @Override - public DemoDataProvider getDataProvider() { - return (DemoDataProvider) super.getDataProvider(); - } - - public TreeModel createModel() { - - // Create root static node - DemoNode root = new DemoNode("jaxxdemo.tree"); - - // Create model - DefaultTreeModel model = createModel(root); - - // load all nodes of model - loadAllNodes(root, getDataProvider()); - - return model; - } -} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoApplicationContext.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoApplicationContext.java new file mode 100644 index 0000000..72ca60c --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoApplicationContext.java @@ -0,0 +1,175 @@ +package org.nuiton.jaxx.demo; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.JAXXContext; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.context.DefaultApplicationContext; +import org.nuiton.jaxx.runtime.context.JAXXContextEntryDef; +import org.nuiton.jaxx.runtime.swing.help.JAXXHelpBroker; +import org.nuiton.jaxx.runtime.swing.help.JAXXHelpUIHandler; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.InputStream; +import java.net.URI; +import java.util.Properties; + +import static org.nuiton.i18n.I18n.t; + +/** + * Created on 1/9/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since XXX + */ +public class DemoApplicationContext extends DefaultApplicationContext implements JAXXHelpUIHandler { + + static final JAXXContextEntryDef<DemoUI> MAIN_UI = + JAXXUtil.newContextEntryDef("MainUI", DemoUI.class); + + /** The singleton instance of the main context */ + private static volatile DemoApplicationContext context; + + /** Logger. */ + private static final Log log = LogFactory.getLog(DemoApplicationContext.class); + + /** + * @return <code>true</code> si le context a été initialisé via la méthode + * {@link #init(DemoConfig)}, <code>false</code> autrement. + */ + protected static boolean isInit() { + return context != null; + } + + /** + * Permet l'initialisation du contexte applicatif et positionne + * l'context partagée. + * + * Note : Cette méthode ne peut être appelée qu'une seule fois. + * + * @param config application config + * @return le context partagée + * @throws IllegalStateException si un contexte applicatif a déja été positionné. + */ + protected static DemoApplicationContext init(DemoConfig config) throws IllegalStateException { + if (isInit()) { + throw new IllegalStateException("there is an already application context registred."); + } + context = new DemoApplicationContext(config); + return context; + } + + /** + * Récupération du contexte applicatif. + * + * @return l'context partagé du contexte. + * @throws IllegalStateException si le contexte n'a pas été initialisé via + * la méthode {@link #init(DemoConfig)} + */ + public static DemoApplicationContext get() throws IllegalStateException { + if (!isInit()) { + throw new IllegalStateException("no application context registred."); + } + return context; + } + + public DemoApplicationContext(DemoConfig config) { + + // share config + setContextValue(config); + + //--------------------------------------------------------------------// + // init help + //--------------------------------------------------------------------// + + // load help mapping + String mappingProperties = "/jaxxdemo-help-fr.properties"; + try { + + InputStream resourceAsStream = + getClass().getResourceAsStream(mappingProperties); + helpMapping = new Properties(); + helpMapping.load(resourceAsStream); + + } catch (Exception eee) { + log.error("Failed to load help mapping file at '" + + mappingProperties + "'", eee); + } + } + + public DemoConfig getConfig() { + return getContextValue(DemoConfig.class); + } + + private Properties helpMapping; + + @Override + public void showHelp(JAXXContext context, JAXXHelpBroker broker, String helpId) { + + if (helpId == null) { + helpId = broker.getDefaultID(); + } + + if (log.isInfoEnabled()) { + log.info("help-id: " + helpId); + } + + String value = (String) helpMapping.get(helpId); + + if (value == null) { + throw new RuntimeException(t("jaxxdemo.context.helpPage.notFound", helpId)); + } + + String helpDirectory = getConfig().getHelpResourceWithLocale(value); + boolean withFragment = helpDirectory.contains("#"); + + String fragment = null; + if (withFragment) { + fragment = StringUtils.substringAfter(helpDirectory, "#"); + helpDirectory = StringUtils.substringBefore(helpDirectory, "#"); + } + + URI resolvedUri = URI.create(helpDirectory); +// try { + + if (withFragment) { + resolvedUri = URI.create(resolvedUri.toString() + "#" + fragment); + } + if (log.isInfoEnabled()) { + log.info("help-uri: " + resolvedUri); + } + getMainUI().getP().setStatus(t("jaxxdemo.openHelp", helpId)); +// SwingUtil.openLink(resolvedUri); +// } catch (URISyntaxException e) { +// throw new RuntimeException(t("jaxxdemo.context.helpPage.notFound", resolvedUri)); +// } + } + + public DemoUI getMainUI() { + + return MAIN_UI.getContextValue(this); + } + +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoConfig.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoConfig.java new file mode 100644 index 0000000..38c659e --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoConfig.java @@ -0,0 +1,512 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo; + +import com.google.common.base.Supplier; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.beans.AbstractBean; +import org.nuiton.config.ApplicationConfig; +import org.nuiton.config.ArgumentsParserException; +import org.nuiton.config.ConfigOptionDef; +import org.nuiton.jaxx.demo.component.swing.JButtonDemo; +import org.nuiton.version.Version; +import org.nuiton.version.Versions; + +import javax.swing.KeyStroke; +import java.awt.Color; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Date; +import java.util.Locale; +import java.util.Properties; + +import static org.nuiton.i18n.I18n.t; + +/** + * La configuration de l'application. + * + * Il s'agit de l'objet partagé par toutes les démos. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.7.2 + */ +public class DemoConfig extends AbstractBean implements Supplier<ApplicationConfig> { + + /** Logger */ + private static final Log log = LogFactory.getLog(DemoConfig.class); + + /** + * le fichier de configuration de l'application avec les informations sur + * le projet (version, license,...) et la configuration des ui (icons, ...) + */ + public static final String APPLICATION_PROPERTIES = "/jaxx-demo.properties"; + + public static final String PROPERTY_FULLSCREEN = "fullscreen"; + + public static final String PROPERTY_LOCALE = "locale"; + + public static final String PROPERTY_FONT_SIZE = "fontSize"; + + public static final String PROPERTY_DEMO_COLOR = "demoColor"; + + public static final String PROPERTY_DEMO_CLASS = "demoClass"; + + public static final String PROPERTY_LOG_LEVEL = "logLevel"; + + public static final String PROPERTY_LOG_PATTERN_LAYOUT = "logPatternLayout"; + + public static final String PROPERTY_KEY_OPEN_CONFIG = "keyOpenConfig"; + + private final ApplicationConfig applicationConfig; + + @Override + public ApplicationConfig get() { + return applicationConfig; + } + + public DemoConfig(String... args) { + + applicationConfig = new ApplicationConfig(); + applicationConfig.setConfigFileName(Option.CONFIG_FILE.defaultValue); + + // chargement de la configuration interne + + InputStream stream = + getClass().getResourceAsStream(APPLICATION_PROPERTIES); + + Properties p = new Properties(); + try { + p.load(stream); + for (Object k : p.keySet()) { + String key = k + ""; + Object value = p.get(k); + if (log.isDebugEnabled()) { + log.debug("install properties " + k + " : " + value); + } + applicationConfig.setDefaultOption(key, "" + value); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + + applicationConfig.loadDefaultOptions(Option.values()); + + String sVersion = applicationConfig.getOption("application.version"); + Version version = Versions.valueOf(sVersion); + if (version.isSnapshot()) { + // on supprime le stamp de snapshot s'il existe + version = Versions.removeSnapshot(version); + } + applicationConfig.setDefaultOption("version", version.getVersion()); + + installSaveUserAction(PROPERTY_FULLSCREEN, + PROPERTY_FONT_SIZE, + PROPERTY_LOCALE, + PROPERTY_DEMO_CLASS, + PROPERTY_DEMO_COLOR); + + try { + applicationConfig.parse(args); + } catch (ArgumentsParserException e) { + throw new IllegalStateException("Could not parse configuration", e); + } + } + + /** + * TODO Remove this when the method in ApplicationConfig will be public + * + * Action to save user configuration. + * + * Add it as a listener of the configuration for a given property. + * + * <b>Note:</b> Will not save if {@link ApplicationConfig#isAdjusting()} is {@code true}. + * + * @since 2.5.4 + */ + private final PropertyChangeListener saveUserAction = + new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (applicationConfig.isAdjusting()) { + if (log.isDebugEnabled()) { + log.debug("Skip save while adjusting"); + } + } else { + if (log.isDebugEnabled()) { + log.debug("Saving configuration fired by property [" + + evt.getPropertyName() + "] at " + + new Date()); + } + saveForUser(); + } + } + }; + + /** + * TODO Remove this when the method in ApplicationConfig will be public + * + * Install the {@link #saveUserAction} on givne {@code properties}. + * + * @param properties properties on which insalls the saveUserAction + */ + protected void installSaveUserAction(String... properties) { + + // pass in adjusting state + applicationConfig.setAdjusting(true); + + try { + // ajout de tous les listeners pour sauver la configuration + // lors de la modification des options de la configuration + for (String propertyKey : properties) { + // add a listener + if (log.isDebugEnabled()) { + log.debug("register saveUserAction on property [" + + propertyKey + ']'); + } + addPropertyChangeListener(propertyKey, saveUserAction); + } + } finally { + + // ok back to normal adjusting state + applicationConfig.setAdjusting(false); + } + } + + public String getCopyrightText() { + return "Version " + getVersion() + " Codelutin @ 2008-2009"; + } + + /** @return la version de l'application. */ + public Version getVersion() { + Version option = applicationConfig.getOption(Version.class, "version"); + return option; + } + + public boolean isFullScreen() { + boolean result = applicationConfig.getOptionAsBoolean(Option.FULL_SCREEN.key); + return result; + } + + public Locale getLocale() { + Locale result = applicationConfig.getOption(Locale.class, Option.LOCALE.key); + return result; + } + + public String getDemoPath() { + String result = applicationConfig.getOption(Option.DEMO_PATH.key); + return result; + } + + public Float getFontSize() { + Float result = applicationConfig.getOption(Float.class, Option.FONT_SIZE.key); + return result; + } + + public Color getDemoColor() { + Color result = applicationConfig.getOptionAsColor(Option.DEMO_COLOR.key); + return result; + } + + public Class<?> getDemoClass() { + Class<?> result = applicationConfig.getOptionAsClass(Option.DEMO_CLASS.key); + return result; + } + + public String getLogLevel() { + String level = applicationConfig.getOption(Option.LOG_LEVEL.key); + return level; + } + + public String getLogPatternLayout() { + String result = applicationConfig.getOption(Option.LOG_PATTERN_LAYOUT.key); + return result; + } + + public KeyStroke getKeyOpenConfig() { + return applicationConfig.getOptionAsKeyStroke(Option.KEY_OPEN_CONFIG.key); + } + + public void setFullscreen(boolean fullscreen) { + applicationConfig.setOption(Option.FULL_SCREEN.key, fullscreen + ""); + firePropertyChange(PROPERTY_FULLSCREEN, null, fullscreen); + } + + public void setLocale(Locale newLocale) { + applicationConfig.setOption(Option.LOCALE.key, newLocale.toString()); + firePropertyChange(PROPERTY_LOCALE, null, newLocale); + } + + public void setFontSize(Float newFontSize) { + Float oldValue = getFontSize(); + if (log.isDebugEnabled()) { + log.debug("changing font-size to " + newFontSize); + } + applicationConfig.setOption(Option.FONT_SIZE.key, newFontSize.toString()); + firePropertyChange(PROPERTY_FONT_SIZE, oldValue, newFontSize); + } + + public void setDemoColor(Color color) { + Color oldValue = getDemoColor(); + if (log.isDebugEnabled()) { + log.debug("changing demo-color to " + color); + } + applicationConfig.setOption(Option.DEMO_COLOR.key, color.toString()); + firePropertyChange(PROPERTY_DEMO_COLOR, oldValue, color); + } + + public void setDemoClass(Class<?> newClass) { + Class<?> oldValue = getDemoClass(); + if (log.isDebugEnabled()) { + log.debug("changing demo-class to " + newClass); + } + applicationConfig.setOption(Option.DEMO_CLASS.key, newClass.getName()); + firePropertyChange(PROPERTY_DEMO_CLASS, oldValue, newClass); + } + + public void setLogLevel(String logLevel) { + String oldValue = getLogLevel(); + applicationConfig.setOption(Option.LOG_LEVEL.key, logLevel); + firePropertyChange(PROPERTY_LOG_LEVEL, oldValue, logLevel); + } + + public void setLogPatternLayout(String logPatternLayout) { + String oldValue = getLogPatternLayout(); + applicationConfig.setOption(Option.LOG_PATTERN_LAYOUT.key, logPatternLayout); + firePropertyChange(PROPERTY_LOG_PATTERN_LAYOUT, oldValue, logPatternLayout); + } + + public void setKeyOpenConfig(KeyStroke keyStroke) { + KeyStroke oldValue = getKeyOpenConfig(); + applicationConfig.setOption(Option.KEY_OPEN_CONFIG.key, keyStroke.toString()); + firePropertyChange(PROPERTY_KEY_OPEN_CONFIG, oldValue, keyStroke); + } + + + public void saveForUser() { + // shoudl we never save any conf ? + applicationConfig.saveForUser(); + } + + public static final String[] DEFAULT_JAXX_PCS = { + PROPERTY_FULLSCREEN, + PROPERTY_LOCALE, + PROPERTY_FONT_SIZE, + ApplicationConfig.ADJUSTING_PROPERTY + }; + + public void removeJaxxPropertyChangeListener() { + PropertyChangeListener[] toRemove; + toRemove = JAXXUtil.findJaxxPropertyChangeListener( + DEFAULT_JAXX_PCS, + applicationConfig.getPropertyChangeListeners()); + if (toRemove == null || toRemove.length == 0) { + return; + } + if (log.isDebugEnabled()) { + log.debug("before remove : " + applicationConfig.getPropertyChangeListeners().length); + log.debug("toRemove : " + toRemove.length); + } + for (PropertyChangeListener listener : toRemove) { + removePropertyChangeListener(listener); + } + if (log.isDebugEnabled()) { + log.debug("after remove : " + getPropertyChangeListeners().length); + } + } + + public URL getApplicationSiteUrl() { + return applicationConfig.getOptionAsURL("application.site.url"); + } + + public String getIconPath() { + return applicationConfig.getOption("application.icon.path"); + } + + public String getHelpLocation() { + return applicationConfig.getOption("application.help.path"); + } + + public String getHelpResourceWithLocale(String value) { + String result = getHelpLocation() + "/" + + getLocale().getLanguage() + "/" + + value; + return result; + } + + ////////////////////////////////////////////////// + // Toutes les options disponibles + ////////////////////////////////////////////////// + + public enum Option implements ConfigOptionDef { + + CONFIG_FILE( + ApplicationConfig.CONFIG_FILE_NAME, + t("jaxxdemo.config.configFileName.description"), + "jaxxdemo", + String.class, + true, + true), + FULL_SCREEN( + "ui.fullscreen", + t("jaxxdemo.config.ui.fullscreen"), + "false", + Boolean.class, + false, + false), + LOCALE( + "ui." + PROPERTY_LOCALE, + t("jaxxdemo.config.ui.locale"), + Locale.FRANCE.toString(), + Locale.class, + false, + false), + FONT_SIZE( + "ui." + PROPERTY_FONT_SIZE, + t("jaxxdemo.config.ui.fontSize"), + "10f", + Float.class, + false, + false), + DEMO_COLOR( + "ui." + PROPERTY_DEMO_COLOR, + t("jaxxdemo.config.ui.demoColor"), + "#ffffff", + Color.class, + false, + false), + DEMO_CLASS( + "ui." + PROPERTY_DEMO_CLASS, + t("jaxxdemo.config.ui.demoClass"), + "java.io.File", + Class.class, + false, + false), + + LOG_LEVEL( + "ui." + PROPERTY_LOG_LEVEL, + t("jaxxdemo.config.ui.logLevel"), + "INFO", + String.class, + false, + false), + LOG_PATTERN_LAYOUT( + "ui." + PROPERTY_LOG_PATTERN_LAYOUT, + t("jaxxdemo.config.ui.logPatternLayout"), + "%5p [%t] (%F:%L) %M - %m%n", + String.class, + false, + false), + KEY_OPEN_CONFIG( + "ui." + PROPERTY_KEY_OPEN_CONFIG, + t("jaxxdemo.config.ui.keyOpenConfig"), + "ctrl alt pressed S", + KeyStroke.class, + false, + false), + DEMO_PATH( + "ui.demo.path", + t("jaxxdemo.config.ui.demo.path"), + "jaxxdemo.tree/jaxxdemo.component.swing/jaxxdemo.component.swing.buttons/" + JButtonDemo.class.getSimpleName(), + String.class, + false, + true); + + public final String key; + + public final String description; + + public String defaultValue; + + public final Class<?> type; + + public boolean _transient; + + public boolean _final; + + Option(String key, + String description, + String defaultValue, + Class<?> type, + boolean _transient, + boolean _final) { + this.key = key; + this.description = description; + this.defaultValue = defaultValue; + this.type = type; + this._final = _final; + this._transient = _transient; + } + + @Override + public boolean isFinal() { + return _final; + } + + @Override + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + @Override + public void setTransient(boolean _transient) { + this._transient = _transient; + } + + @Override + public void setFinal(boolean _final) { + this._final = _final; + } + + @Override + public boolean isTransient() { + return _transient; + } + + @Override + public String getDefaultValue() { + return defaultValue; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getKey() { + return key; + } + + @Override + public Class<?> getType() { + return type; + } + + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoHelpBroker.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoHelpBroker.java new file mode 100644 index 0000000..5987fe1 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoHelpBroker.java @@ -0,0 +1,148 @@ +package org.nuiton.jaxx.demo; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.awt.visitor.BuildTreeVisitor; +import org.nuiton.jaxx.runtime.awt.visitor.ComponentTreeNode; +import org.nuiton.jaxx.runtime.awt.visitor.DebugComponentTreeNodeVisitor; +import org.nuiton.jaxx.runtime.awt.visitor.GetCompopentAtPointVisitor; +import org.nuiton.jaxx.runtime.swing.help.JAXXHelpBroker; +import org.nuiton.jaxx.runtime.swing.help.JAXXHelpUI; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.AbstractButton; +import java.awt.Component; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; + +/** + * Help broker. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.1 + */ +public class DemoHelpBroker extends JAXXHelpBroker { + + /** Logger */ + private static final Log log = LogFactory.getLog(DemoHelpBroker.class); + + public DemoHelpBroker(String defaultID) { + super("tutti", "help", + defaultID, + DemoApplicationContext.get()); + } + + @Override + public void prepareUI(JAXXObject c) { + + Preconditions.checkNotNull(c, "parameter c can not be null!"); + + // l'ui doit avoir un boutton showHelp + AbstractButton help = getShowHelpButton(c); + + if (help != null) { + + // attach context to button + if (log.isDebugEnabled()) { + log.debug("attach context to showhelp button " + c); + } + help.putClientProperty(JAXX_CONTEXT_ENTRY, c); + + // add tracking action + ActionListener listener = getShowHelpAction(); + if (log.isDebugEnabled()) { + log.debug("adding tracking action " + listener); + } + help.addActionListener(listener); + + if (log.isDebugEnabled()) { + log.debug("done for " + c); + } + } + } + + @Override + public String findHelpId(Component comp) { + + if (comp == null) { + comp = DemoApplicationContext.get().getMainUI(); + } + JAXXHelpUI parentContainer = SwingUtil.getParent(comp, JAXXHelpUI.class); + + String result; + if (parentContainer != null && this != parentContainer.getBroker()) { + + JAXXHelpBroker broker = parentContainer.getBroker(); + result = broker.findHelpId(comp); + } else { + result = super.findHelpId(comp); + } + + if (result == null) { + result = "ui.main.menu"; + } + + return result; + } + + @Override + public Component getDeppestComponent(Component mouseComponent, MouseEvent event) { + ComponentTreeNode tree = BuildTreeVisitor.buildTree(mouseComponent); + + DebugComponentTreeNodeVisitor debugTree = new DebugComponentTreeNodeVisitor() { + @Override + public String getMessage(ComponentTreeNode componentTree) { + String message = super.getMessage(componentTree); + Component userObject = componentTree.getUserObject(); + if (userObject.isShowing() && userObject.isVisible()) { + Rectangle rectangle = new Rectangle(userObject.getLocationOnScreen(), userObject.getSize()); + message += " visible - " + rectangle; + } else { + message += " invisible"; + } + return message; + } + }; + + debugTree.setDebug(log.isDebugEnabled()); + + debugTree.parse(tree); + +// Point point = event.getPoint(); + Point point = event.getLocationOnScreen(); + + Component component = GetCompopentAtPointVisitor.get(tree, point); + if (log.isDebugEnabled()) { + log.debug("Component at (" + point + "): " + component); + } + return component; + } + + +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoPanel.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoPanel.jaxx new file mode 100644 index 0000000..cd23d16 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoPanel.jaxx @@ -0,0 +1,63 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JPanel id='top' abstract='true'> + + <import> + org.nuiton.jaxx.demo.DemoHelpBroker + org.nuiton.util.StringUtil + </import> + + <script><![CDATA[ + +//protected String getHelpDefaultId() { return "ui.main.menu"; } + +protected String[] getSources() { + if (DemoPanel.class.equals(getClass())) { + return StringUtil.EMPTY_STRING_ARRAY; + } + return addDefaultSources(); +} + +protected String[] addDefaultSources(String... sources) { + return DemoSourcesHandler.addDefaultSources(this, sources); +} + +public String getLabel() { + String name = getClass().getSimpleName(); + if (name.endsWith("Demo")) { + name = name.substring(0, name.length() - "Demo".length()); + } + return name; +} + +public String getDemoTabTitle() { + return getLabel() + " Demo"; +} + ]]> + </script> + + <String id='helpDefaultId' javaBean='"ui.main.menu"'/> + + <DemoHelpBroker id='broker' constructorParams='getHelpDefaultId()'/> + +</JPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoSources.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoSources.jaxx new file mode 100644 index 0000000..409cf36 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoSources.jaxx @@ -0,0 +1,90 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JPanel layout='{new BorderLayout()}' decorator='help'> + + <import> + org.nuiton.jaxx.demo.DemoHelpBroker + org.nuiton.jaxx.runtime.SwingUtil + org.nuiton.jaxx.runtime.swing.FontSizor + + java.awt.RenderingHints + javax.swing.DefaultComboBoxModel + + org.fife.ui.rsyntaxtextarea.RSyntaxTextArea + </import> + + <script><![CDATA[ + +public void init() { + handler.init(this); +} + +public DemoConfig getConfig() { + return getContextValue(DemoConfig.class); +} + + + ]]> + </script> + + <DemoHelpBroker id='broker' constructorParams='"ui.main.sources"'/> + + <Class id='incomingClass' javaBean='null' genericType='?'/> + + <String id='currentSource' javaBean='null'/> + + <java.util.List id='sources' genericType='String' javaBean='null'/> + + <JToolBar id='editorPaneHeader' + floatable='false' + borderPainted='false' + opaque='false' + constraints='BorderLayout.SOUTH'> + + <JComboBox id='sourceTabs' + model='{new DefaultComboBoxModel()}' + onItemStateChanged='if(event.getStateChange() == ItemEvent.SELECTED) { handler.updateSource(event); }'/> + <javax.swing.Box.Filler + constructorParams='SwingUtil.newMinDimension(), SwingUtil.newMinDimension(), SwingUtil.newMaxXDimension()'/> + <FontSizor id='fontSizor' opaque='false' showFontSize='true' + fontSize='{getConfig().getFontSize()}'/> + </JToolBar> + + <JScrollPane id='editorPane' columnHeaderView='{editorPaneHeader}' + constraints='BorderLayout.CENTER'> + <RSyntaxTextArea id='editor' + font-size='{getConfig().getFontSize()}' + minimumSize="{SwingUtil.newMinDimension()}" + antiAliasingEnabled='true' + editable="false" + wrapStyleWord="false" + columns="80" + lineWrap="true"/> + <!--font-size='{updateSize(getFontSizor().getFontSize())}'--> + <!-- TC-20091221 : can not use binding since we want to do something after assigment... --> + <!--text='{handler.getSourceContent(DemoSources.this, getCurrentSource())}'--> + <!--syntaxEditingStyle='{handler.getSourceEditingStyle(DemoSources.this, getCurrentSource())}'--> + </JScrollPane> + + +</JPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/DemoSources.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoSources.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/DemoSources.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoSources.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoSourcesHandler.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoSourcesHandler.java new file mode 100644 index 0000000..d6289e7 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoSourcesHandler.java @@ -0,0 +1,199 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.demo; + +import com.google.common.collect.Lists; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.swing.FontSizor; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; + +import java.awt.event.ItemEvent; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * Created: 21 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + * + * Mise a jour: $Date$ par : + * $Author$ + */ +public class DemoSourcesHandler implements UIHandler<DemoSources> { + + /** Logger */ + private static final Log log = LogFactory.getLog(DemoSourcesHandler.class); + + protected static Map<String, String> sourcesCache; + + public static String[] addDefaultSources(JAXXObject ui, String... extraSources) { + List<String> sources = Lists.newArrayList(); + String packageName = ui.getClass().getPackage().getName(); + String simpleName = ui.getClass().getSimpleName(); + addIfExist(ui, sources, packageName, simpleName + ".jaxx"); + addIfExist(ui, sources, packageName, simpleName + ".css"); + addIfExist(ui, sources, packageName, simpleName + "Handler.java"); + addIfExist(ui, sources, packageName, simpleName + "Model.java"); + Collections.addAll(sources, extraSources); + return sources.toArray(new String[sources.size()]); + } + + private static void addIfExist(JAXXObject ui, + List<String> sources, + String packageName, + String resourcePath) { + String path = "/" + packageName.replaceAll("\\.", "/"); + path += "/" + resourcePath; + InputStream resource = ui.getClass().getResourceAsStream(path); + try { + if (resource != null) { + sources.add(resourcePath); + } + } finally { + IOUtils.closeQuietly(resource); + } + + } + + public static Map<String, String> getSourcesCache() { + if (sourcesCache == null) { + sourcesCache = new TreeMap<String, String>(); + } + return sourcesCache; + } + + public String getSourceContent(String name) { + if (name == null) { + return ""; + } + String result = getSourcesCache().get(name); + if (result == null) { + try { + if (log.isDebugEnabled()) { + log.debug(name + " from " + ui.getIncomingClass()); + } + int lastDotIndex = name.lastIndexOf(""); + String path = "/" + name.substring(0, lastDotIndex).replaceAll("\\.", "/"); + path += name.substring(lastDotIndex); + result = IOUtils.toString(ui.getIncomingClass().getResourceAsStream(path)); + if (log.isDebugEnabled()) { + log.debug("source [" + name + "], loaded content =\n" + result); + } + } catch (Exception e) { + log.error("could not load file " + name, e); + result = "could not load file " + name; + } + getSourcesCache().put(name, result); + } + return result; + } + + public String getSourceEditingStyle(String source) { + + if (source == null) { + return ""; + } + ui.getEditor().setFractionalFontMetricsEnabled(true); + String s = null; + if (source.matches(".*\\.jaxx") || source.matches(".*\\.xml")) { + s = RSyntaxTextArea.SYNTAX_STYLE_XML; + } else if (source.matches(".*\\.java")) { + s = RSyntaxTextArea.SYNTAX_STYLE_JAVA; + } else if (source.matches(".*\\.css")) { + s = RSyntaxTextArea.SYNTAX_STYLE_CSS; + } + if (log.isDebugEnabled()) { + log.debug("source [" + source + "] style = " + s); + } + return s; + } + + DemoSources ui; + + @Override + public void beforeInit(DemoSources ui) { + this.ui = ui; + } + + @Override + public void afterInit(final DemoSources ui) { + + //fontSizor.setDefaultFontSize(getConfig().getFontSize()); + final FontSizor fontSizor = ui.getFontSizor(); + fontSizor.init(); + fontSizor.setCallBack(new Runnable() { + + @Override + public void run() { + log.info("update font size : " + fontSizor.getFontSize()); + ui.getConfig().setFontSize(fontSizor.getFontSize()); + } + }); + } + + public void updateSource(ItemEvent event) { + ui.setCurrentSource((String) ui.sourceTabs.getSelectedItem()); + ui.editor.setText(getSourceContent(ui.getCurrentSource())); + ui.editor.setSyntaxEditingStyle(getSourceEditingStyle(ui.getCurrentSource())); + ui.editor.setCaretPosition(0); + } + + public void init(final DemoSources ui) { + List<String> sources = ui.getSources(); + if (sources == null) { + return; + } + + List<String> toFill = new ArrayList<String>(); + String prefix = ui.getIncomingClass() == null ? "" : + ui.getIncomingClass().getPackage().getName() + ""; + for (String source : sources) { + String path; + if (source.startsWith("/")) { + path = source.substring(1); + } else { + path = prefix + source; + } + if (log.isDebugEnabled()) { + log.debug("adding resource " + path); + } + toFill.add(path); + } + SwingUtil.fillComboBox(ui.getSourceTabs(), toFill, null); + if (!toFill.isEmpty()) { + ui.getSourceTabs().setSelectedIndex(0); + } + toFill.clear(); + ui.getEditor().discardAllEdits(); + } + +} diff --git a/jaxx-demo/src/main/java/jaxx/demo/DemoTab.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoTab.jaxx similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/DemoTab.jaxx rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoTab.jaxx diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoUI.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoUI.jaxx new file mode 100644 index 0000000..2c2f847 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoUI.jaxx @@ -0,0 +1,110 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JFrame id='mainFrame' width='1024' height='800' + decorator='help' onWindowClosing='handler.close(mainFrame)'> + + <import> + org.nuiton.jaxx.demo.tree.DemoTreeHelper + org.nuiton.jaxx.demo.tree.DemoCellRenderer + + org.nuiton.jaxx.runtime.SwingUtil + org.nuiton.jaxx.runtime.swing.CardLayout2 + org.nuiton.jaxx.runtime.swing.StatusMessagePanel + + java.awt.Dimension + java.util.Locale + </import> + + <CardLayout2 id='contentLayout'/> + + <DemoConfig id='config' initializer='getContextValue(DemoConfig.class)'/> + + <DemoTreeHelper id='treeHelper' + initializer='getContextValue(DemoTreeHelper.class)'/> + + <DemoHelpBroker id='broker' constructorParams='"ui.main.menu"'/> + + <script><![CDATA[ + +public boolean acceptLocale(Locale l, String expected) { + return l !=null && l.toString().equals(expected); +} +]]> + </script> + + <JMenuBar id='menu'> + + <JMenu id='menuFile'> + <JMenuItem id='menuFileConfiguration' + onActionPerformed="handler.showConfig(this)"/> + <JMenu id='menuFileLanguage'> + <JMenuItem id='menuFileLanguageFR' + onActionPerformed="handler.changeLanguage(this, Locale.FRANCE)"/> + <JMenuItem id='menuFileLanguageUK' + onActionPerformed="handler.changeLanguage(this, Locale.UK)"/> + </JMenu> + <JSeparator/> + <JMenuItem id='menuFileFullscreen' + onActionPerformed="handler.changeScreen(this, true)"/> + <JMenuItem id='menuFileNormalscreen' + onActionPerformed="handler.changeScreen(this, false)"/> + <JSeparator/> + <JMenuItem id='menuFileExit' + onActionPerformed="handler.close(this)"/> + </JMenu> + + <JMenu id='menuHelp'> + <JMenuItem id='menuHelpLogs' + onActionPerformed="handler.showLogs(this)"/> + <JMenuItem id='menuHelpHelp' + onActionPerformed="handler.showHelp(this, null)"/> + <JMenuItem id='menuHelpSite' + onActionPerformed="handler.gotoSite(this)"/> + <JMenuItem id='menuHelpAbout' + onActionPerformed="handler.showAbout(this)"/> + </JMenu> + + <JToolBar layout='{new BorderLayout()}'> + + <!-- pour afficher l'aide contextuelle --> + <JButton id='showHelp' constraints='BorderLayout.EAST'/> + </JToolBar> + + + </JMenuBar> + + <JPanel id='mainPane' layout='{new BorderLayout()}'> + + <JSplitPane id='splitPane' constraints='BorderLayout.CENTER'> + <JScrollPane id='navigationPane'> + <JTree id='navigation'/> + </JScrollPane> + + <JPanel id='content'/> + + </JSplitPane> + + <StatusMessagePanel id='p' constraints='BorderLayout.SOUTH'/> + + </JPanel> +</JFrame> diff --git a/jaxx-demo/src/main/java/jaxx/demo/DemoUI.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoUI.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/DemoUI.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoUI.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoUIHandler.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoUIHandler.java new file mode 100644 index 0000000..cdfa344 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/DemoUIHandler.java @@ -0,0 +1,581 @@ +package org.nuiton.jaxx.demo; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.JAXXContext; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.context.DefaultApplicationContext; +import org.nuiton.jaxx.runtime.context.JAXXContextEntryDef; +import org.nuiton.jaxx.runtime.context.JAXXInitialContext; +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.swing.ErrorDialogUI; +import org.nuiton.jaxx.runtime.swing.log.JAXXLog4jUI; +import org.nuiton.jaxx.runtime.swing.renderer.DecoratorProviderListCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.decorator.DecoratorProvider; +import org.nuiton.i18n.I18n; +import org.nuiton.jaxx.config.ConfigUIHelper; +import org.nuiton.jaxx.demo.tree.DemoNode; +import org.nuiton.jaxx.demo.tree.DemoTreeHelper; +import org.nuiton.jaxx.widgets.about.AboutUI; +import org.nuiton.jaxx.widgets.about.AboutUIBuilder; + +import javax.swing.AbstractAction; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTree; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.TreePath; +import java.awt.Component; +import java.awt.Desktop; +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Constructor; +import java.net.URL; +import java.util.Arrays; +import java.util.Locale; + +import static org.nuiton.i18n.I18n.n; +import static org.nuiton.i18n.I18n.t; + +/** + * Le handler de l'ui principale. + * + * @author Tony Chemit - chemit@codelutin.com + * @see DemoUI + */ +public class DemoUIHandler implements UIHandler<DemoUI> { + + /** Logger */ + static private Log log = LogFactory.getLog(DemoUIHandler.class); + + static final JAXXContextEntryDef<DemoUI> MAIN_UI_ENTRY_DEF = + JAXXUtil.newContextEntryDef("mainui", DemoUI.class); + + public static final String OPEN_CONFIG_ACTION = "openConfig"; + + /** + * Methode pour initialiser l'ui principale sans l'afficher. + * + * @param rootContext le context applicatif + * @param config la configuration a utiliser + * @return l'ui instancie et initialisee mais non visible encore + */ + public DemoUI initUI(DefaultApplicationContext rootContext, DemoConfig config) { + + if (log.isDebugEnabled()) { + log.debug("fullscreen ? " + config.isFullScreen()); + } + DecoratorProvider decoratorProvider = + rootContext.getContextValue(DecoratorProvider.class); + + if (!config.getLocale().equals(I18n.getDefaultLocale())) { + if (log.isInfoEnabled()) { + log.info("re-init I18n with locale " + config.getLocale()); + } + // change i18n language + I18n.setDefaultLocale(config.getLocale()); + // reload decorators + decoratorProvider.reload(); + } + + // create restrict context for ui + JAXXInitialContext context = new JAXXInitialContext(); + + // share handler + context.add(this); + + // share tree helper + context.add(rootContext.getContextValue(DemoTreeHelper.class)); + + // share config + context.add(rootContext.getContextValue(DemoConfig.class)); + + // share a unique DecoratorProvider + context.add(decoratorProvider); + + // share a unique DecoratorProviderListCellRenderer + context.add(new DecoratorProviderListCellRenderer(decoratorProvider)); + + // instanciate ui + DemoUI ui = new DemoUI(context); + + // add key strokes + addKeyStrokes(ui, config); + + // keep it in root context + MAIN_UI_ENTRY_DEF.setContextValue(rootContext, ui); + + // synch to error dialog + ErrorDialogUI.init(ui); + + // set fullscreen propery on main ui + ui.getGraphicsConfiguration().getDevice().setFullScreenWindow(config.isFullScreen() ? ui : null); + + return ui; + } + + protected void addKeyStrokes(final DemoUI ui, DemoConfig config) { + + // Use WHEN_IN_FOCUSED_WINDOW to don't have focus check for binding keys + JPanel mainPane = ui.getMainPane(); + mainPane.getActionMap().put(OPEN_CONFIG_ACTION, new AbstractAction() { + + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + showConfig(ui); + } + }); + final InputMap inputMap = mainPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + config.addPropertyChangeListener(DemoConfig.PROPERTY_KEY_OPEN_CONFIG, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + KeyStroke oldValue = (KeyStroke) evt.getOldValue(); + inputMap.remove(oldValue); + setShowConfigInputMap(inputMap, (KeyStroke) evt.getNewValue()); + } + }); + setShowConfigInputMap(inputMap, config.getKeyOpenConfig()); + } + + protected void setShowConfigInputMap(InputMap inputMap, KeyStroke keyStroke) { + inputMap.put(keyStroke, OPEN_CONFIG_ACTION); + } + + @Override + public void beforeInit(DemoUI ui) { + + } + + @Override + public void afterInit(final DemoUI ui) { + + // Creation of selection listener to open ui when tree selection change + TreeSelectionListener listener = new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent event) { + TreePath path = event.getPath(); + DemoNode node = (DemoNode) path.getLastPathComponent(); + + if (log.isDebugEnabled()) { + log.debug("Select node " + node); + } + + if (node == null || node.isStringNode()) { + + // noeud de présentation, rien a faire + return; + } + showUI(ui, node.getInternalClass()); + } + }; + + JTree tree = ui.getNavigation(); + + ui.getTreeHelper().setUI(tree, true, listener); + + // auto-expand node when selected + SwingUtil.addExpandOnClickListener(tree); + + } + + protected void showUI(DemoUI ui, Class<?> type) { + + JPanel content = ui.getContent(); + + String constraints = type.getName(); + + log.info("Show for " + constraints); + + // Verify if instance is existing + DemoTab demoContent = getContentIfExist(ui, constraints); + + if (demoContent == null) { + + log.info("Will instanciate a new " + constraints); + try { + // Get constructor + Constructor<?> constructor = + type.getConstructor(JAXXContext.class); + + JAXXInitialContext tx = + new JAXXInitialContext().add(ui.getDelegateContext()); + + DemoPanel panel = (DemoPanel) constructor.newInstance(tx); + + log.info("Demo panel to use : " + panel); + + demoContent = new DemoTab(tx.add("content", panel)); + + } catch (Exception eee) { + log.error(eee, eee); + ErrorDialogUI.showError(eee); + } + + // Add to content panel + content.add(demoContent, constraints); + } + + // show ui + ui.getContentLayout().show(content, constraints); + } + +// Get content if exist in content, else return null + + protected <E extends Component> E getContentIfExist(DemoUI ui, String constraints) { + if (log.isDebugEnabled()) { + log.debug("Get content if exist " + constraints); + } + if (!ui.getContentLayout().contains(constraints)) { + return null; + } + return (E) ui.getContentLayout().getComponent(ui.getContent(), constraints); + } + + public void displayUI(final DemoUI ui, final String[] nodePath) { + + // expend all nodes of the demo tree + SwingUtil.expandTree(ui.getNavigation()); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + String[] path; + if (nodePath == null) { + // take first node + path = new String[]{"jaxxdemo.tree"}; + } else { + // take selected node + path = nodePath; + + } + log.info("node to re select " + Arrays.toString(path)); + // select node + ui.getTreeHelper().selectNode(path); + + // use best dimensions + ui.getSplitPane().resetToPreferredSizes(); + } + }); + + // show ui after all (in another invocation, tu avoid layout adjustement + // to be seen). + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + // show ui + ui.setVisible(true); + } + }); + } + + /** + * Permet de recharger l'ui principale et de changer de le mode d'affichage. + * + * @param rootContext le contexte applicatif + * @param config la configuration a utiliser + */ + public void reloadUI(DefaultApplicationContext rootContext, DemoConfig config) { + + // scan main ui + DemoUI ui = getUI(rootContext); + + String[] node = null; + if (ui != null) { + + ui.getConfig().removeJaxxPropertyChangeListener(); + + node = ui.getTreeHelper().getSelectedIds(); + + if (node != null) { + if (log.isDebugEnabled()) { + log.debug("selected node " + Arrays.toString(node)); + } + } + + ErrorDialogUI.init(null); + + ui.dispose(); + + ui.setVisible(false); + + MAIN_UI_ENTRY_DEF.removeContextValue(rootContext); + } + + ui = initUI(rootContext, config); + + displayUI(ui, node); + } + + /** + * Méthode pour changer de mode d'affichage. + * + * Si <code>fullscreen</code> est à <code>true</code> alors on passe en + * mode console (c'est à dire en mode plein écran exclusif), sinon on + * passe en mode fenetré normal. + * + * @param context l'ui principale de l'application + * @param fullscreen le nouvel état requis. + */ + public void changeScreen(JAXXContext context, boolean fullscreen) { + + DemoUI ui = getUI(context); + + // sauvegarde de l'état dans la configuration + DemoConfig config = ui.getConfig(); + config.setFullscreen(fullscreen); + + // rechargement de l'ui + reloadUI(DemoApplicationContext.get(), config); + } + + public void changeLanguage(JAXXContext context, Locale newLocale) { + + DemoUI ui = getUI(context); + + DemoConfig config = ui.getConfig(); + + // sauvegarde de la nouvelle locale + config.setLocale(newLocale); + + // rechargement de l'ui + reloadUI(DemoApplicationContext.get(), config); + } + + /** + * Ferme l'application. + * + * @param context l'ui principale de l'application + */ + public void close(JAXXContext context) { + log.info("JAXX Demo quitting..."); + try { + + DemoUI ui = getUI(context); + ui.dispose(); + } finally { + System.exit(0); + } + } + + final Runnable reloadUICallback = new Runnable() { + + @Override + public void run() { + if (log.isInfoEnabled()) { + log.info("will reload ui"); + } + DefaultApplicationContext context = DemoApplicationContext.get(); + DemoUI ui = getUI(context); + DemoConfig config = ui.getConfig(); + reloadUI(context, config); + } + }; + + final Runnable reloadApplicationCallback = new Runnable() { + + @Override + public void run() { + if (log.isInfoEnabled()) { + log.info("will reload appplication"); + } + close(DemoApplicationContext.get()); + } + }; + + final Runnable reloadLogAppenderCallback = new Runnable() { + + @Override + public void run() { + if (log.isInfoEnabled()) { + log.info("will reload log appender"); + } + DefaultApplicationContext context = DemoApplicationContext.get(); + DemoUI ui = getUI(context); + DemoConfig config = ui.getConfig(); + + // init jaxx logger + JAXXLog4jUI.init(config.getLogLevel(), config.getLogPatternLayout()); + } + }; + + public void showConfig(JAXXContext context) { + DemoUI ui = getUI(context); + DemoConfig config = ui.getConfig(); + + ConfigUIHelper helper = new ConfigUIHelper(config); + + helper.registerCallBack("ui", + n("demo.action.reload.ui"), + SwingUtil.createActionIcon("reload-ui"), + reloadUICallback); + + helper.registerCallBack("application", + n("demo.action.reload.application"), + SwingUtil.createActionIcon("reload-application"), + reloadApplicationCallback); + + helper.registerCallBack("log", + n("demo.action.reload.logAppender"), + SwingUtil.createActionIcon("reload-log"), + reloadLogAppenderCallback); + + // categorie repertoires + + helper.addCategory(n("jaxxdemo.config.category.directories"), + n("jaxxdemo.config.category.directories.description")); + + helper.addOption(DemoConfig.Option.CONFIG_FILE); + + // others + helper.addCategory(n("jaxxdemo.config.category.other"), + n("jaxxdemo.config.category.other.description")); + + helper.addOption(DemoConfig.Option.FULL_SCREEN). + setOptionPropertyName(DemoConfig.PROPERTY_FULLSCREEN). + setOptionCallBack("ui"); + + helper.addOption(DemoConfig.Option.FONT_SIZE). + setOptionPropertyName(DemoConfig.PROPERTY_FONT_SIZE). + setOptionCallBack("ui"); + + helper.addOption(DemoConfig.Option.LOCALE). + setOptionPropertyName(DemoConfig.PROPERTY_LOCALE). + setOptionCallBack("ui"); + + helper.addOption(DemoConfig.Option.DEMO_COLOR). + setOptionPropertyName(DemoConfig.PROPERTY_DEMO_COLOR). + setOptionCallBack("ui"); + + helper.addOption(DemoConfig.Option.DEMO_CLASS). + setOptionPropertyName(DemoConfig.PROPERTY_DEMO_CLASS). + setOptionCallBack("ui"); + + helper.addOption(DemoConfig.Option.KEY_OPEN_CONFIG). + setOptionPropertyName(DemoConfig.PROPERTY_KEY_OPEN_CONFIG). + setOptionCallBack("ui"); + + helper.addOption(DemoConfig.Option.LOG_LEVEL). + setOptionPropertyName(DemoConfig.PROPERTY_LOG_LEVEL). + setOptionCallBack("log"); + + helper.addOption(DemoConfig.Option.LOG_PATTERN_LAYOUT). + setOptionPropertyName(DemoConfig.PROPERTY_LOG_PATTERN_LAYOUT). + setOptionCallBack("log"); + + helper.buildUI(context, "jaxxdemo.config.category.other"); + + helper.displayUI(ui, false); + } + + public void showHelp(DemoUI ui) { + + DemoApplicationContext.get().showHelp(ui, ui.getBroker(), null); + } + + public void showHelp(JAXXContext context, String helpId) { + log.info(context + " :: " + helpId); +// DemoUI mainUI = getUI(context); +// ObserveHelpBroker helpBroker = context.getContextValue(ObserveHelpBroker.class); +// +// if (helpId == null) { +// helpId = helpBroker.getDefaultID(); +// } +// log.debug("show help " + helpId); +// mainUI.getHelp().setCurrentID(helpId); + } + + public void showLogs(DemoUI ui) { + + JAXXLog4jUI log4jUI = new JAXXLog4jUI(); + String title = t("jaxxdemo.title.showLog"); + log4jUI.setTitle(title); + log4jUI.showInDialog(ui, false); + } + + public void gotoSite(JAXXContext context) { + + DemoUI ui = getUI(context); + DemoConfig config = ui.getConfig(); + + URL siteURL = config.getApplicationSiteUrl(); + + log.info(t("jaxxdemo.message.goto.site", siteURL)); + + if (log.isDebugEnabled()) { + log.debug("goto " + siteURL); + } + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + try { + Desktop.getDesktop().browse(siteURL.toURI()); + } catch (Exception ex) { + log.error(ex.getMessage(), ex); + ErrorDialogUI.showError(ex); + } + } + } + + public void showAbout(DemoUI ui) { + + DemoConfig config = ui.getConfig(); + + String iconPath = config.getIconPath(); + + String name = "jaxx-demo"; + AboutUI about = AboutUIBuilder.builder(ui) + .setIconPath(config.getIconPath()) + .setTitle(t("jaxxdemo.title.about")) + .setBottomText(ui.getConfig().getCopyrightText()) + .addAboutTab(t("jaxxdemo.about.message"), true) + .addDefaultLicenseTab(name, false) + .addDefaultThirdPartyTab(name, false) + .addDefaultChangelogTab(name, false) + .build(); + + about.display(); + + } + + DemoUI getUI(JAXXContext context) { + if (context instanceof DemoUI) { + return (DemoUI) context; + } + DemoUI ui = MAIN_UI_ENTRY_DEF.getContextValue(context); + return ui; + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/RunDemo.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/RunDemo.java new file mode 100644 index 0000000..135a527 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/RunDemo.java @@ -0,0 +1,158 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo; + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.swing.ErrorDialogUI; +import org.nuiton.jaxx.runtime.swing.log.JAXXLog4jUI; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.decorator.DecoratorProvider; +import org.nuiton.i18n.I18n; +import org.nuiton.i18n.init.DefaultI18nInitializer; +import org.nuiton.jaxx.demo.entities.DemoDecoratorProvider; +import org.nuiton.jaxx.demo.tree.DemoDataProvider; +import org.nuiton.jaxx.demo.tree.DemoTreeHelper; +import org.nuiton.util.StringUtil; + +import java.util.Arrays; +import java.util.Date; + +import static org.nuiton.i18n.I18n.t; + +/** @author Tony Chemit - chemit@codelutin.com */ +public class RunDemo { + + /** Logger */ + private static Log log = LogFactory.getLog(RunDemo.class); + + public static void main(String... args) { + + long startingTime = System.nanoTime(); + log.info("JAXX Demo start at " + new Date() + " args: " + Arrays.toString(args)); + + try { + + // init root context + // to enable javassist on webstart, must remove any securityManager, + // see if this can be dangerous (should not be since jnlp is signed ?) + // moreover it speeds up the loading :) + System.setSecurityManager(null); + + long t0 = System.nanoTime(); + + I18n.init(new DefaultI18nInitializer("jaxx-demo-i18n"), null); + + Runtime.getRuntime().addShutdownHook(new ShutdownHook()); + + // init config + DemoConfig config = new DemoConfig(args); + + // init root context + DemoApplicationContext rootContext = DemoApplicationContext.init(config); + + // share a tree helper + rootContext.setContextValue(new DemoTreeHelper(new DemoDataProvider())); + + // share the config + rootContext.setContextValue(config); + + // init decorator provider + DecoratorProvider p = new DemoDecoratorProvider(); + + // share the decorator provider + rootContext.setContextValue(p); + + long t00 = System.nanoTime(); + + // init i18n + I18n.setDefaultLocale(config.getLocale()); + + log.info("language : " + config.getLocale()); + + if (log.isDebugEnabled()) { + log.debug("i18n loading time : " + StringUtil.convertTime(t00, System.nanoTime())); + } + + log.info(t("jaxxdemo.message.config.loaded", config.getVersion())); + + // init jaxx logger + JAXXLog4jUI.init(config.getLogLevel(), config.getLogPatternLayout()); + + // prepare ui look&feel and load ui properties + try { + SwingUtil.initNimbusLoookAndFeel(); + } catch (Exception e) { + // could not find nimbus look-and-feel + log.warn(t("jaxxdemo.warning.nimbus.landf")); + } catch (Throwable e) { + log.warn(t("jaxxdemo.warning.no.ui")); + + } + + if (log.isDebugEnabled()) { + log.debug("init done in " + StringUtil.convertTime(t0, System.nanoTime())); + } + + log.info(t("jaxxdemo.init.context.done", StringUtil.convertTime(startingTime, System.nanoTime()))); + + // on affiche l'ui principale + DemoUIHandler handler = new DemoUIHandler(); + + DemoUI ui = handler.initUI(rootContext, config); + + log.info(t("jaxxdemo.init.ui.done")); + + DemoApplicationContext.MAIN_UI.setContextValue(rootContext, ui); + + handler.displayUI(ui, config.getDemoPath().split("/")); + + } catch (Exception e) { + log.error(e.getMessage(), e); + ErrorDialogUI.showError(e); + System.exit(1); + } + } + + protected static class ShutdownHook extends Thread { + + public ShutdownHook() { + super("shutdown JAXXDemo"); + } + + @Override + public void run() { + try { + super.run(); + + // force to kill main thread + + log.info(t("jaxxdemo.init.closed", new Date())); + Runtime.getRuntime().halt(0); + } catch (Exception ex) { + log.error("error while closing " + ex.getMessage(), ex); + Runtime.getRuntime().halt(1); + } + } + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/BoxedDecoratorDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/BoxedDecoratorDemo.jaxx new file mode 100644 index 0000000..bfba1b9 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/BoxedDecoratorDemo.jaxx @@ -0,0 +1,122 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.runtime.SwingUtil + org.nuiton.jaxx.runtime.swing.BlockingLayerUI + org.nuiton.jaxx.runtime.swing.BlockingLayerUI2 + + java.awt.Color + java.awt.event.ActionEvent + + javax.swing.AbstractAction + javax.swing.DefaultListModel + javax.swing.JComponent + </import> + <BlockingLayerUI id='layerUI' + acceptAction='{new AbstractAction() { + private static final long serialVersionUID = 1L; + @Override + public void actionPerformed(ActionEvent e) { + accept(e, "from icon of layer"); + } + }}'/> + <BlockingLayerUI2 id='layerUI2' + acceptAction='{new AbstractAction() { + private static final long serialVersionUID = 1L; + @Override + public void actionPerformed(ActionEvent e) { + accept(e, "from icon of layer"); + } + }}'/> + <script><![CDATA[ + +void $afterCompleteSetup() { + for (JComponent boxed : SwingUtil.getLayeredComponents(this)) { + if (boxed == buttonD) { + SwingUtil.setLayerUI(boxed, layerUI2); + continue; + } + + BlockingLayerUI ui = layerUI.clone(); + if (boxed == buttonC) { + ui.setBlock(true); + } + SwingUtil.setLayerUI(boxed, ui); + } +} + +public void setLayer(boolean active) { + for (JComponent boxed : SwingUtil.getLayeredComponents(this)) { + if (boxed == buttonD) { + continue; + } + BlockingLayerUI ui = (BlockingLayerUI) SwingUtil.getLayer(boxed).getUI(); + if (boxed == buttonC) { + ui.setBlock(active); + } + ui.setUseIcon(active); + } +} + +protected void accept(ActionEvent e, String suffix) { + JButton source = (JButton) e.getSource(); + String clickedMessage = (String) source.getClientProperty("clickedText"); + String msg = "'" + source.getText() + "' clicked - " + suffix + " : " + clickedMessage; + ((DefaultListModel)messages.getModel()).addElement(msg); +}]]> + </script> + <Table fill='both' weightx='1' constraints='BorderLayout.CENTER'> + <row> + <cell> + <JCheckBox id='toggle' selected='true' + text='{toggle.isSelected() ? "Active layer" : "No layer"}' + onActionPerformed='setLayer(toggle.isSelected());'/> + </cell> + </row> + <row> + <cell weighty='0.5'> + <JPanel id='buttonPane'> + <JButton id='buttonA' decorator='boxed' + _clickedText='"button A was clicked"' + onActionPerformed='accept(event, "from button (no layer)")'/> + <JButton id='buttonB' decorator='boxed' + onActionPerformed='accept(event, "from button (no layer)")'/> + <JButton id='buttonC' decorator='boxed' + onActionPerformed='accept(event, "from button (no layer)");'/> + <JButton id='buttonD' decorator='boxed' + onActionPerformed='accept(event, "from button (no layer)");'/> + </JPanel> + </cell> + </row> + <row> + <cell weighty='0.5'> + <JScrollPane> + <JList id='messages'/> + </JScrollPane> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/BoxedDecoratorDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/BoxedDecoratorDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/jaxx/BoxedDecoratorDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/BoxedDecoratorDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/StatusMessagePanelDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/StatusMessagePanelDemo.jaxx new file mode 100644 index 0000000..ea98774 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/StatusMessagePanelDemo.jaxx @@ -0,0 +1,31 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + <JPanel layout='{new GridLayout(0,1)}' constraints='BorderLayout.CENTER'> + <JButton text='Fool me once' + onActionPerformed='p.setStatus(((JButton)event.getSource()).getText() + " ? shame on you!")'/> + <JButton text='Fool me twice' + onActionPerformed='p.setStatus(((JButton)event.getSource()).getText() + " ? shame on ...")'/> + </JPanel> + <org.nuiton.jaxx.runtime.swing.StatusMessagePanel id='p' constraints='BorderLayout.SOUTH'/> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanComboBoxDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanComboBoxDemo.jaxx new file mode 100644 index 0000000..86a4fbb --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanComboBoxDemo.jaxx @@ -0,0 +1,53 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.demo.entities.People + org.nuiton.jaxx.runtime.swing.editor.bean.BeanComboBox + </import> + + <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> + <row> + <cell> + <JPanel id='configurationPanel' layout='{new GridLayout(0,1)}'> + <JCheckBox id='autoCompleteButton'/> + <JCheckBox id='showResetButton'/> + <JCheckBox id='showDecoratorButton'/> + </JPanel> + </cell> + </row> + <row> + <cell> + <BeanComboBox id='comboBox' genericType='People'/> + </cell> + </row> + <row> + <cell> + <JPanel id='resultPanel' layout='{new BorderLayout()}'> + <JLabel id='selectedResult' constraints='BorderLayout.CENTER'/> + </JPanel> + </cell> + </row> + </Table> + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanComboBoxDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanComboBoxDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanComboBoxDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanComboBoxDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanComboBoxDemoHandler.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanComboBoxDemoHandler.java new file mode 100644 index 0000000..60a822d --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanComboBoxDemoHandler.java @@ -0,0 +1,76 @@ +package org.nuiton.jaxx.demo.component.jaxx.editor; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.nuiton.decorator.JXPathDecorator; +import org.nuiton.jaxx.demo.entities.DemoDataProvider; +import org.nuiton.jaxx.demo.entities.DemoDecoratorProvider; +import org.nuiton.jaxx.demo.entities.People; + +import java.util.List; + +import static org.nuiton.i18n.I18n.n; +import static org.nuiton.i18n.I18n.t; + +/** + * Handlerof {@link BeanComboBoxDemo}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.9 + */ +public class BeanComboBoxDemoHandler implements UIHandler<BeanComboBoxDemo> { + + private JXPathDecorator<People> decorator; + + @Override + public void beforeInit(BeanComboBoxDemo ui) { + this.decorator = (JXPathDecorator<People>) + new DemoDecoratorProvider().getDecoratorByType(People.class); + } + + @Override + public void afterInit(BeanComboBoxDemo ui) { + List<People> data = new DemoDataProvider().getPeoples(); + + ui.getComboBox().init(decorator, data); + } + + public String getSelectedResult(People people) { + String result; + + if (people == null) { + result = t("jaxxdemo.beancomboboxdemo.no.people.selected"); + } else { + result = t("jaxxdemo.beancomboboxdemo.selected.people", decorator.toString(people)); + } + return result; + } + + static { + n("jaxxdemo.common.people"); + n("jaxxdemo.common.firstName"); + n("jaxxdemo.common.lastName"); + n("jaxxdemo.common.age"); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanDoubleListDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanDoubleListDemo.jaxx new file mode 100644 index 0000000..22ae48f --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanDoubleListDemo.jaxx @@ -0,0 +1,48 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.demo.entities.People + org.nuiton.jaxx.runtime.swing.editor.bean.BeanDoubleList + </import> + + <Table fill='both'> + <row> + <cell> + <JPanel id='configurationPanel' layout='{new GridLayout(0,1)}'> + <JCheckBox id='filterableButton'/> + <JCheckBox id='highlightFilterTextButton'/> + <JCheckBox id='showResetButton'/> + <JCheckBox id='showDecoratorButton'/> + <JCheckBox id='filterOnNachoButton'/> + </JPanel> + </cell> + </row> + <row> + <cell weighty='1' weightx='1'> + <BeanDoubleList id='doubleList' genericType='People'/> + </cell> + </row> + </Table> + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanDoubleListDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanDoubleListDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanDoubleListDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanDoubleListDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanDoubleListDemoHandler.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanDoubleListDemoHandler.java new file mode 100644 index 0000000..ee6f9b6 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanDoubleListDemoHandler.java @@ -0,0 +1,77 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.nuiton.jaxx.demo.component.jaxx.editor; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Predicate; +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.nuiton.decorator.JXPathDecorator; +import org.nuiton.jaxx.demo.entities.DemoDataProvider; +import org.nuiton.jaxx.demo.entities.DemoDecoratorProvider; +import org.nuiton.jaxx.demo.entities.Movie; +import org.nuiton.jaxx.demo.entities.People; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.util.List; + +/** @author kmorin */ +public class BeanDoubleListDemoHandler implements UIHandler<BeanDoubleListDemo> { + + private BeanDoubleListDemo ui; + + @Override + public void beforeInit(BeanDoubleListDemo ui) { + this.ui = ui; + } + + @Override + public void afterInit(BeanDoubleListDemo ui) { + DemoDataProvider demoDataProvider = new DemoDataProvider(); + List<People> data = demoDataProvider.getPeoples(); + JXPathDecorator<People> decorator = (JXPathDecorator<People>) new DemoDecoratorProvider().getDecoratorByType(People.class); + ui.getDoubleList().init(decorator, data, data.subList(0, 1)); + + final Movie nacho = demoDataProvider.getMovie("0"); + final Predicate<People> filter = new Predicate<People>() { + + public boolean apply(People input) { + return nacho.getActors().contains(input); + } + }; + ui.getFilterOnNachoButton().addChangeListener(new ChangeListener() { + + public void stateChanged(ChangeEvent e) { + if (BeanDoubleListDemoHandler.this.ui.getFilterOnNachoButton().isSelected()) { + BeanDoubleListDemoHandler.this.ui.getDoubleList().getHandler().addFilter(filter); + + } else { + BeanDoubleListDemoHandler.this.ui.getDoubleList().getHandler().clearFilters(); + } + } + }); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemo.jaxx new file mode 100644 index 0000000..33e4931 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemo.jaxx @@ -0,0 +1,54 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.demo.entities.People + org.nuiton.jaxx.runtime.swing.editor.bean.BeanFilterableComboBox + </import> + + <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> + <row> + <cell> + <JPanel id='configurationPanel' layout='{new GridLayout(0,1)}'> + <JCheckBox id='filterableButton'/> + <JCheckBox id='showResetButton'/> + <JCheckBox id='showDecoratorButton'/> + <JCheckBox id='colorizeInvalidComboEditorTextButton'/> + </JPanel> + </cell> + </row> + <row> + <cell> + <BeanFilterableComboBox id='comboBox' genericType='People'/> + </cell> + </row> + <row> + <cell> + <JPanel id='resultPanel' layout='{new BorderLayout()}'> + <JLabel id='selectedResult' constraints='BorderLayout.CENTER'/> + </JPanel> + </cell> + </row> + </Table> + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemoHandler.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemoHandler.java new file mode 100644 index 0000000..ae92ba8 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/BeanFilterableComboBoxDemoHandler.java @@ -0,0 +1,78 @@ +package org.nuiton.jaxx.demo.component.jaxx.editor; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.nuiton.decorator.JXPathDecorator; +import org.nuiton.jaxx.demo.entities.DemoDataProvider; +import org.nuiton.jaxx.demo.entities.DemoDecoratorProvider; +import org.nuiton.jaxx.demo.entities.People; + +import java.util.List; + +import static org.nuiton.i18n.I18n.n; +import static org.nuiton.i18n.I18n.t; + +/** + * Handlerof {@link BeanComboBoxDemo}. + * + * @author Kevin Morin - morin@codelutin.com + * @since 2.5.12 + */ +public class BeanFilterableComboBoxDemoHandler implements UIHandler<BeanFilterableComboBoxDemo> { + + private JXPathDecorator<People> decorator; + + + @Override + public void beforeInit(BeanFilterableComboBoxDemo ui) { + this.decorator = (JXPathDecorator<People>) + new DemoDecoratorProvider().getDecoratorByType(People.class); + } + + @Override + public void afterInit(BeanFilterableComboBoxDemo ui) { + + List<People> data = new DemoDataProvider().getPeoples(); + + ui.getComboBox().init(decorator, data); + } + + public String getSelectedResult(Object people) { + String result; + + if (people == null || !People.class.isInstance(people)) { + result = t("jaxxdemo.beanfilterablecomboboxdemo.no.people.selected"); + } else { + result = t("jaxxdemo.beanfilterablecomboboxdemo.selected.people", decorator.toString(people)); + } + return result; + } + + static { + n("jaxxdemo.common.people"); + n("jaxxdemo.common.firstName"); + n("jaxxdemo.common.lastName"); + n("jaxxdemo.common.age"); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/ComboEditorDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/ComboEditorDemo.jaxx new file mode 100644 index 0000000..c6ddf41 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/ComboEditorDemo.jaxx @@ -0,0 +1,66 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.i18n.LanguageEnum + org.nuiton.i18n.CountryEnum + </import> + + <Table fill='both' constraints='BorderLayout.CENTER'> + <row> + <cell> + <JLabel text='Locale editor:' labelFor='{localeEditor}'/> + </cell> + + <cell> + <LocaleEditor id='localeEditor'/> + </cell> + </row> + <row> + <cell> + <JLabel text='EnumEditor (language) :' labelFor='{languageEditor}'/> + </cell> + <cell> + <EnumEditor id='languageEditor' genericType='LanguageEnum' + constructorParams='LanguageEnum.class'/> + </cell> + </row> + <row> + <cell> + <JLabel text='EnumEditor (country) :' labelFor='{countryEditor}'/> + </cell> + <cell> + <EnumEditor id='countryEditor' genericType='CountryEnum' + constructorParams='CountryEnum.class'/> + </cell> + </row> + <row> + <cell columns="2"> + <JTextArea + text='{"locale : "+ localeEditor.getSelectedItem() + "\nlanguage : "+ languageEditor.getSelectedItem() + "\ncountry : " + countryEditor.getSelectedItem()}'/> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/DatePickerDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/DatePickerDemo.jaxx new file mode 100644 index 0000000..fa6e577 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/DatePickerDemo.jaxx @@ -0,0 +1,96 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + java.beans.PropertyChangeEvent + java.beans.PropertyChangeListener + java.text.SimpleDateFormat + java.util.Date + </import> + + <String id='patternLayout' javaBean='"dd/MM/yyyy HH:mm:ss"'/> + + <SimpleDateFormat id='dateFormat' constructorParams='patternLayout'/> + + <Date id='date' javaBean='new Date()'/> + + <script><![CDATA[ + protected void $afterCompleteSetup() { + + addPropertyChangeListener(PROPERTY_PATTERN_LAYOUT, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + dateFormat = new SimpleDateFormat(patternLayout); + datePicker.setPatternLayout(patternLayout); + resultView.setText(dateFormat.format(date)); + } + }); + + addPropertyChangeListener(PROPERTY_DATE, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + resultView.setText(dateFormat.format(date)); + } + }); + } + ]]></script> + + <Table fill='both' constraints='BorderLayout.CENTER'> + <row> + <cell columns='2' fill='horizontal' weightx='1'> + <JCheckBox id='showPopupButton' + text='jaxxdemo.datePickerEditor.showPopupButton' + selected='false'/> + </cell> + </row> + <row> + <cell> + <JLabel text='jaxxdemo.datePickerEditor.patternLayout'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JTextField id='patternLayoutField' + text='{patternLayout}' + onFocusLost='setPatternLayout(patternLayoutField.getText())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1' columns='2'> + <JAXXDatePicker id='datePicker' + date='{date}' + patternLayout='{patternLayout}' + showPopupButton='{showPopupButton.isSelected()}' + onActionPerformed='setDate(datePicker.getDate())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='jaxxdemo.datePickerEditor.dateResult'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JLabel id='resultView' text='{dateFormat.format(date)}'/> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/FileEditorDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/FileEditorDemo.jaxx new file mode 100644 index 0000000..6e10e52 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/FileEditorDemo.jaxx @@ -0,0 +1,121 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + <import> + org.nuiton.jaxx.runtime.swing.editor.FileEditor + </import> + + <String id='title' javaBean='"Open file"'/> + <String id='exts' javaBean='"txt, png"'/> + <String id='extsDescription' javaBean='"Text (*.txt), Image (*.png)"'/> + <Boolean id='acceptAllFileFilterUsed' javaBean='Boolean.TRUE'/> + <Boolean id='directoryEnabled' javaBean='Boolean.TRUE'/> + <Boolean id='fileEnabled' javaBean='Boolean.FALSE'/> + <Boolean id='showReset' javaBean='Boolean.TRUE'/> + + <Table fill='both' constraints='BorderLayout.CENTER'> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.fileEditor.titleLbl'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JTextField id='titleField' + text='{getTitle()}' + onKeyReleased='setTitle(titleField.getText())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.fileEditor.directoryEnabled'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JCheckBox id='directoryEnabledField' + selected='{isDirectoryEnabled()}' + onActionPerformed='setDirectoryEnabled(directoryEnabledField.isSelected())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.fileEditor.fileEnabled'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JCheckBox id='fileEnabledField' + selected='{isFileEnabled()}' + onActionPerformed='setFileEnabled(fileEnabledField.isSelected())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.fileEditor.extsLbl'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JTextField id='extsField' + enabled='{isFileEnabled()}' + text='{getExts()}' + onKeyReleased='setExts(extsField.getText())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.fileEditor.extsDescLbl'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JTextField id='extsDescriptionField' + enabled='{isFileEnabled()}' + text='{getExtsDescription()}' + onKeyReleased='setExtsDescription(extsDescriptionField.getText())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.fileEditor.acceptAllFileFilterUsed'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JCheckBox id='acceptAllFileFilterUsedField' + selected='{isAcceptAllFileFilterUsed()}' + onActionPerformed='setAcceptAllFileFilterUsed(acceptAllFileFilterUsedField.isSelected())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.fileEditor.showResetLabel'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JCheckBox id='showResetCheckBox' + selected='{isShowReset()}' + onActionPerformed='setShowReset(showResetCheckBox.isSelected())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1' columns='2'> + <FileEditor id='fileChooser' + title='{getTitle()}' + exts='{getExts()}' + directoryEnabled='{isDirectoryEnabled()}' + showReset='{isShowReset()}' + fileEnabled='{isFileEnabled()}' + acceptAllFileFilterUsed='{isAcceptAllFileFilterUsed()}' + extsDescription='{getExtsDescription()}'/> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/I18nEditorDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/I18nEditorDemo.jaxx new file mode 100644 index 0000000..ab6e5cc --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/I18nEditorDemo.jaxx @@ -0,0 +1,92 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + <import> + javax.swing.border.Border + org.nuiton.jaxx.runtime.swing.editor.I18nEditor + org.nuiton.i18n.I18n + java.util.Arrays + </import> + <script><![CDATA[ +protected Border getPopupBorder(String text) { + if (text==null || text.trim().isEmpty()) { + return null; + } + return new TitledBorder(t(text)); +} +]]> + </script> + <Table fill='both' constraints='BorderLayout.CENTER'> + <row> + <cell> + <JPanel + border='{new TitledBorder(t("jaxxdemo.i18neditor.configuration"))}' + layout='{new GridLayout(0,1)}'> + + <JCheckBox id='showText' + text='jaxxdemo.i18neditor.showText' + selected='true'/> + + <JCheckBox id='showIcon' + text='jaxxdemo.i18neditor.showIcon' + selected='true'/> + + <JCheckBox id='showPopupText' + text='jaxxdemo.i18neditor.showPopupText' + selected='true'/> + + <JCheckBox id='showPopupIcon' + text='jaxxdemo.i18neditor.showPopupIcon' + selected='true'/> + + <JPanel> + <JLabel text='jaxxdemo.i18neditor.popupBorderText' + labelFor='{popupBorderText}'/> + <JTextField id='popupBorderText' + text='{t("jaxxdemo.i18neditor.popup.title")}'/> + </JPanel> + + </JPanel> + </cell> + </row> + <row> + <cell> + <I18nEditor id='editor' + showText='{showText.isSelected()}' + showIcon='{showIcon.isSelected()}' + showPopupText='{showPopupText.isSelected()}' + showPopupIcon='{showPopupIcon.isSelected()}' + popupBorder='{getPopupBorder(popupBorderText.getText())}' + locales='{Arrays.asList(I18n.getStore().getLocales())}'/> + </cell> + </row> + <row> + <cell> + <JLabel + border='{new TitledBorder(t("jaxxdemo.i18neditor.selected.locale"))}' + text='{editor.getSelectedLocale().toString()}'/> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/ListSelectorDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/ListSelectorDemo.jaxx new file mode 100644 index 0000000..6527aeb --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/ListSelectorDemo.jaxx @@ -0,0 +1,102 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + <import> + org.nuiton.jaxx.runtime.swing.ListSelector + com.google.common.collect.Lists + java.util.List + org.nuiton.jaxx.demo.entities.People + org.nuiton.jaxx.demo.entities.Movie + org.nuiton.jaxx.demo.entities.DemoDataProvider + org.nuiton.jaxx.demo.entities.DemoDecoratorProvider + org.nuiton.jaxx.runtime.swing.renderer.DecoratorProviderListCellRenderer + java.util.Collection + org.nuiton.jaxx.runtime.swing.model.GenericListModel + </import> + + <ListCellRenderer id='listCellRenderer' + initializer='new DecoratorProviderListCellRenderer(new DemoDecoratorProvider())'/> + <DemoDataProvider id='dataProvider'/> + + <String id='addToolTip' javaBean='"Add"'/> + <String id='removeToolTip' javaBean='"Remove"'/> + + <script><![CDATA[ +public List<People> getActors(Collection<Movie> movies) { + List<People> actors = Lists.newArrayList(); + for (Movie m : movies) { + List<People> actorsToAdd = m.getActors(); + actors.removeAll(actorsToAdd); + actors.addAll(actorsToAdd); + } + return actors; +} +]]></script> + + <Table fill='both' constraints='BorderLayout.CENTER'> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.listSelector.addToolTipLbl'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JTextField id='addToolTipField' + text='{getAddToolTip()}' + onKeyReleased='setAddToolTip(addToolTipField.getText())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.listSelector.removeToolTipLbl'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JTextField id='removeToolTipField' + text='{getRemoveToolTip()}' + onKeyReleased='setRemoveToolTip(removeToolTipField.getText())'/> + </cell> + </row> + <row> + <cell fill='both' weightx='1' weighty='0.5' columns='2'> + <JScrollPane> + <ComboToListSelector id='comboToListSelector' + genericType='Movie' + addToolTip='{getAddToolTip()}' + removeToolTip='{getRemoveToolTip()}' + values='{dataProvider.getMovies()}' + renderer='{listCellRenderer}' + onValuesAdded='listToListSelector.setValues(getActors(comboToListSelector.getSelectedValues()))' + onValuesRemoved='listToListSelector.setValues(getActors(comboToListSelector.getSelectedValues()))'/> + </JScrollPane> + </cell> + </row> + <row> + <cell fill='both' weightx='1' weighty='0.5' columns='2'> + <JScrollPane> + <ListToListSelector id='listToListSelector' + genericType='People' + addToolTip='{getAddToolTip()}' + removeToolTip='{getRemoveToolTip()}' + renderer='{listCellRenderer}'/> + </JScrollPane> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/NumberEditorDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/NumberEditorDemo.jaxx new file mode 100644 index 0000000..4063fef --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/NumberEditorDemo.jaxx @@ -0,0 +1,113 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.runtime.swing.editor.NumberEditor + static org.nuiton.i18n.I18n.t + </import> + + <!-- model --> + <NumberEditorDemoModel id='demoModel'/> + + <script><![CDATA[ + +public void changeNumberPattern() { + editor.setNumberPattern(numberPattern.getText()); +} + +void $afterCompleteSetup() { + editor.init(); + changeNumberPattern(); +} + +]]> + </script> + + <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> + <row> + <cell> + <JPanel + border='{new TitledBorder(t("jaxxdemo.numbereditor.configuration"))}' + layout='{new GridLayout(0,1)}'> + + <JCheckBox id='useFloat' + text='jaxxdemo.numbereditor.useFloat' + selected='true'/> + + <JCheckBox id='useSign' + text='jaxxdemo.numbereditor.useSign' + selected='true'/> + + <JCheckBox id='showPopupButton' + text='jaxxdemo.numbereditor.showPopupButton' + selected='true'/> + + <JCheckBox id='showResetButton' + text='jaxxdemo.numbereditor.showReset' + selected='true'/> + + <JCheckBox id='autoPopup' + text='jaxxdemo.numbereditor.autoPopup' + selected='false'/> + <JPanel + border='{new TitledBorder(t("jaxxdemo.numbereditor.numberPattern.configuration"))}' + layout='{new GridLayout(1,0)}'> + <JTextField id='numberPattern' text='{"\\d{0,3}"}'/> + <JButton id='applyNumberPattern' + text='jaxxdemo.numbereditor.applyNumberPattern' + onActionPerformed='changeNumberPattern();'/> + </JPanel> + </JPanel> + </cell> + </row> + <row> + <cell> + <org.nuiton.jaxx.runtime.swing.editor.NumberEditor id='editor' + constructorParams='this' + bean='{demoModel}' + property='{useFloat.isSelected() ? "floatProperty" : "integerProperty"}' + useFloat='{useFloat.isSelected()}' + useSign='{useSign.isSelected()}' + autoPopup='{autoPopup.isSelected()}' + showPopupButton='{showPopupButton.isSelected()}' + showReset='{showResetButton.isSelected()}'/> + </cell> + </row> + <row> + <cell> + <JPanel border='{new TitledBorder(t("jaxxdemo.numbereditor.model"))}' + layout='{new GridLayout(0,1)}'> + <JLabel + text='{t("jaxxdemo.numbereditor.model.numberPattern", editor.getNumberPattern())}'/> + <JLabel + text='{t("jaxxdemo.numbereditor.model.int", demoModel.getIntegerProperty())}'/> + <JLabel + text='{t("jaxxdemo.numbereditor.model.float", demoModel.getFloatProperty())}'/> + + </JPanel> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> + diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/NumberEditorDemoModel.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/NumberEditorDemoModel.java new file mode 100644 index 0000000..ca40750 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/NumberEditorDemoModel.java @@ -0,0 +1,62 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.component.jaxx.editor; + +import org.jdesktop.beans.AbstractSerializableBean; + +/** + * @author Tony Chemit - chemit@codelutin.com + * @since 1.5 + */ +public class NumberEditorDemoModel extends AbstractSerializableBean { + + public static final String INTEGER_PROPERTY = "integerProperty"; + + public static final String FLOAT_PROPERTY = "floatProperty"; + + private static final long serialVersionUID = 1L; + + protected int integerProperty; + + protected float floatProperty; + + public float getFloatProperty() { + return floatProperty; + } + + public int getIntegerProperty() { + return integerProperty; + } + + public void setFloatProperty(float floatProperty) { + float old = this.floatProperty; + this.floatProperty = floatProperty; + firePropertyChange(FLOAT_PROPERTY, old, floatProperty); + } + + public void setIntegerProperty(int integerProperty) { + int old = this.integerProperty; + this.integerProperty = integerProperty; + firePropertyChange(INTEGER_PROPERTY, old, integerProperty); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemo.jaxx new file mode 100644 index 0000000..d4dbd14 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemo.jaxx @@ -0,0 +1,81 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.runtime.swing.editor.SimpleTimeEditor + + static org.nuiton.i18n.I18n.t + </import> + + <!-- model --> + <SimpleTimeEditorDemoModel id='demoModel'/> + + <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> + <row> + <cell> + <JPanel id="configPanel"> + + <!--JCheckBox id='useFloat' + text='jaxxdemo.numbereditor.useFloat' + selected='true'/> + + <JCheckBox id='useSign' + text='jaxxdemo.numbereditor.useSign' + selected='true'/> + + <JCheckBox id='showPopupButton' + text='jaxxdemo.numbereditor.showPopupButton' + selected='true'/> + + <JCheckBox id='showResetButton' + text='jaxxdemo.numbereditor.showReset' + selected='true'/> + + <JCheckBox id='autoPopup' + text='jaxxdemo.numbereditor.autoPopup' + selected='false'/--> + + </JPanel> + </cell> + </row> + <row> + <cell> + <SimpleTimeEditor id='editor' constructorParams='this' + border='{new TitledBorder(t("jaxxdemo.timeeditor.editor"))}'/> + </cell> + </row> + <row> + <cell> + + <JPanel id='resultPane'> + + <JLabel constraints='BorderLayout.CENTER' + text='{t("jaxxdemo.timeeditor.value", demoModel.getTime())}'/> + </JPanel> + + </cell> + </row> + </Table> + + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemoHandler.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemoHandler.java new file mode 100644 index 0000000..6260a88 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemoHandler.java @@ -0,0 +1,47 @@ +package org.nuiton.jaxx.demo.component.jaxx.editor; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.spi.UIHandler; + +/** + * Created on 11/22/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class SimpleTimeEditorDemoHandler implements UIHandler<SimpleTimeEditorDemo> { + @Override + public void beforeInit(SimpleTimeEditorDemo ui) { + + } + + @Override + public void afterInit(SimpleTimeEditorDemo ui) { + // init time editor + ui.editor.init(); + + // set current time in model + ui.demoModel.setTime(new java.util.Date()); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemoModel.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemoModel.java new file mode 100644 index 0000000..a3b0411 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/SimpleTimeEditorDemoModel.java @@ -0,0 +1,54 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.demo.component.jaxx.editor; + +import org.nuiton.jaxx.runtime.swing.editor.SimpleTimeEditor; +import org.jdesktop.beans.AbstractSerializableBean; + +import java.util.Date; + +/** + * Model of a bean using the {@link SimpleTimeEditor}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class SimpleTimeEditorDemoModel extends AbstractSerializableBean { + + public static final String TIME_PROPERTY = "time"; + + private static final long serialVersionUID = 1L; + + protected Date time; + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + Date old = this.time; + this.time = time; + firePropertyChange(TIME_PROPERTY, old, time); + } + + +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/TimeEditorDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/TimeEditorDemo.jaxx new file mode 100644 index 0000000..268ff2a --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/TimeEditorDemo.jaxx @@ -0,0 +1,84 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.runtime.swing.editor.TimeEditor + static org.nuiton.i18n.I18n.t + </import> + + <!-- model --> + <org.nuiton.jaxx.demo.component.jaxx.editor.TimeEditorDemoModel id='demoModel'/> + + <script><![CDATA[ + +void $afterCompleteSetup() { + + // init time editor + editor.init(); + + // set current time in model + demoModel.setTime(new java.util.Date()); +} +]]> + </script> + + + <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> + <row> + <cell> + <JPanel id="configPanel"> + + <JPanel layout='{new BorderLayout()}'> + + <JLabel id='labelConfigLabel' constraints='BorderLayout.WEST'/> + + <JTextField id='labelConfig' constraints='BorderLayout.CENTER'/> + </JPanel> + + </JPanel> + </cell> + </row> + <row> + <cell> + <org.nuiton.jaxx.runtime.swing.editor.TimeEditor id='editor' constructorParams='this' property='time' + border='{new TitledBorder(t("jaxxdemo.timeeditor.editor"))}' + bean='{demoModel}' + date="{demoModel.getTime()}" + label="{labelConfig.getText()}"/> + </cell> + </row> + <row> + <cell> + + <JPanel id='resultPane'> + + <JLabel constraints='BorderLayout.CENTER' + text='{t("jaxxdemo.timeeditor.value", demoModel.getTime())}'/> + </JPanel> + + </cell> + </row> + </Table> + + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/TimeEditorDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/TimeEditorDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/TimeEditorDemoModel.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/TimeEditorDemoModel.java new file mode 100644 index 0000000..39b97d3 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/TimeEditorDemoModel.java @@ -0,0 +1,53 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.demo.component.jaxx.editor; + +import org.nuiton.jaxx.runtime.swing.editor.TimeEditor; +import org.jdesktop.beans.AbstractSerializableBean; + +import java.util.Date; + +/** + * Model of a bean using the {@link TimeEditor}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.2 + */ +public class TimeEditorDemoModel extends AbstractSerializableBean { + + public static final String TIME_PROPERTY = "time"; + + private static final long serialVersionUID = 1L; + + protected Date time; + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + Date old = this.time; + this.time = time; + firePropertyChange(TIME_PROPERTY, old, time); + } + +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/gis/CoordinateDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/gis/CoordinateDemo.jaxx new file mode 100644 index 0000000..99ba05d --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/gis/CoordinateDemo.jaxx @@ -0,0 +1,97 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.runtime.swing.editor.NumberEditor + org.nuiton.jaxx.runtime.swing.editor.gis.DmsCoordinate + org.nuiton.jaxx.runtime.swing.editor.gis.DmsCoordinateEditor + org.nuiton.jaxx.runtime.swing.editor.gis.DmdCoordinate + org.nuiton.jaxx.runtime.swing.editor.gis.DmdCoordinateEditor + </import> + + <!-- model --> + <CoordinateDemoModel id='model'/> + + <!-- internal editor models --> + <DmsCoordinate id='latitudeDms'/> + <DmdCoordinate id='latitudeDmd'/> + <Float id='latitudeDd' javaBean='null'/> + <DmsCoordinate id='longitudeDms'/> + <DmdCoordinate id='longitudeDmd'/> + <Float id='longitudeDd' javaBean='null'/> + + <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> + <row> + <cell> + <JPanel id='config' layout='{new GridLayout(1,0)}'> + + <JPanel id='configLatitude' layout='{new GridLayout(0,1)}'> + <JCheckBox id='latitudeShowReset'/> + <JRadioButton id='latitudeUseDms' + onActionPerformed='handler.useLatitudeDmsEditor()'/> + <JRadioButton id='latitudeUseDmd' + onActionPerformed='handler.useLatitudeDmdEditor()'/> + <JRadioButton id='latitudeUseDd' + onActionPerformed='handler.useLatitudeDdEditor()'/> + </JPanel> + <JPanel id='configLongitude' layout='{new GridLayout(0,1)}'> + <JCheckBox id='longitudeShowReset'/> + <JRadioButton id='longitudeUseDms' + onActionPerformed='handler.useLongitudeDmsEditor()'/> + <JRadioButton id='longitudeUseDmd' + onActionPerformed='handler.useLongitudeDmdEditor()'/> + <JRadioButton id='longitudeUseDd' + onActionPerformed='handler.useLongitudeDdEditor()'/> + </JPanel> + </JPanel> + </cell> + </row> + <row> + <cell> + <JPanel layout='{new GridLayout(1,0)}'> + <JPanel id='latitudePane' layout='{new GridLayout(0,1)}'> + <DmsCoordinateEditor id='latitudeDmsEditor' constructorParams='this'/> + <DmdCoordinateEditor id='latitudeDmdEditor' constructorParams='this'/> + <NumberEditor id='latitudeDdEditor' constructorParams='this'/> + </JPanel> + <JPanel id='longitudePane' layout='{new GridLayout(0,1)}'> + <DmsCoordinateEditor id='longitudeDmsEditor' + constructorParams='this'/> + <DmdCoordinateEditor id='longitudeDmdEditor' + constructorParams='this'/> + <NumberEditor id='longitudeDdEditor' constructorParams='this'/> + </JPanel> + </JPanel> + </cell> + </row> + <row> + <cell> + <JPanel id='result' layout='{new GridLayout(0,1)}'> + <JLabel id='resultLatitude'/> + <JLabel id='resultLongitude'/> + + </JPanel> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/gis/CoordinateDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/gis/CoordinateDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/gis/CoordinateDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/gis/CoordinateDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/gis/CoordinateDemoHandler.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/gis/CoordinateDemoHandler.java new file mode 100644 index 0000000..8399ca6 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/gis/CoordinateDemoHandler.java @@ -0,0 +1,175 @@ +package org.nuiton.jaxx.demo.component.jaxx.editor.gis; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.swing.editor.gis.DmdCoordinate; +import org.nuiton.jaxx.runtime.swing.editor.gis.DmsCoordinate; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import static org.nuiton.i18n.I18n.t; + +/** + * Created on 11/26/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class CoordinateDemoHandler implements UIHandler<CoordinateDemo> { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(CoordinateDemoHandler.class); + + private CoordinateDemo ui; + + @Override + public void beforeInit(CoordinateDemo ui) { + if (log.isInfoEnabled()) { + log.info("BeforeInit " + ui.getName()); + } + this.ui = ui; + } + + @Override + public void afterInit(CoordinateDemo ui) { + + if (log.isInfoEnabled()) { + log.info("AfterInit " + ui.getName()); + } + + ui.getLatitudeDmsEditor().init(false); + ui.getLatitudeDmdEditor().init(false); + ui.getLatitudeDdEditor().init(); + ui.getLongitudeDmsEditor().init(true); + ui.getLongitudeDmdEditor().init(true); + ui.getLongitudeDdEditor().init(); + + ui.getLatitudeDms().addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + DmsCoordinate source = (DmsCoordinate) evt.getSource(); + getModel().setLatitude(source.toDecimal()); + } + }); + ui.getLatitudeDmd().addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + DmdCoordinate source = (DmdCoordinate) evt.getSource(); + getModel().setLatitude(source.toDecimal()); + } + }); + + ui.addPropertyChangeListener("latitudeDd", new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + Float source = (Float) evt.getNewValue(); + getModel().setLatitude(source); + } + }); + + ui.getLongitudeDms().addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + DmsCoordinate source = (DmsCoordinate) evt.getSource(); + getModel().setLongitude(source.toDecimal()); + } + }); + ui.getLongitudeDmd().addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + DmdCoordinate source = (DmdCoordinate) evt.getSource(); + getModel().setLongitude(source.toDecimal()); + } + }); + + ui.addPropertyChangeListener("longitudeDd", new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + Float source = (Float) evt.getNewValue(); + getModel().setLongitude(source); + } + }); + + useLatitudeDmsEditor(); + useLongitudeDmsEditor(); + } + + public void useLatitudeDmsEditor() { + ui.getLatitudeDmsEditor().setValue(DmsCoordinate.valueOf(getModel().getLatitude())); + ui.getLatitudeDmsEditor().setEnabled(true); + ui.getLatitudeDmdEditor().setEnabled(false); + ui.getLatitudeDdEditor().setEnabled(false); + } + + public void useLatitudeDmdEditor() { + ui.getLatitudeDmdEditor().setValue(DmdCoordinate.valueOf(getModel().getLatitude())); + ui.getLatitudeDmsEditor().setEnabled(false); + ui.getLatitudeDmdEditor().setEnabled(true); + ui.getLatitudeDdEditor().setEnabled(false); + } + + public void useLatitudeDdEditor() { + ui.getLatitudeDdEditor().setModel(getModel().getLatitude()); + ui.getLatitudeDmsEditor().setEnabled(false); + ui.getLatitudeDmdEditor().setEnabled(false); + ui.getLatitudeDdEditor().setEnabled(true); + } + + public void useLongitudeDmsEditor() { + ui.getLongitudeDmsEditor().setValue(DmsCoordinate.valueOf(getModel().getLongitude())); + ui.getLongitudeDmsEditor().setEnabled(true); + ui.getLongitudeDmdEditor().setEnabled(false); + ui.getLongitudeDdEditor().setEnabled(false); + } + + public void useLongitudeDmdEditor() { + ui.getLongitudeDmdEditor().setValue(DmdCoordinate.valueOf(getModel().getLongitude())); + ui.getLongitudeDmsEditor().setEnabled(false); + ui.getLongitudeDmdEditor().setEnabled(true); + ui.getLongitudeDdEditor().setEnabled(false); + } + + public void useLongitudeDdEditor() { + ui.getLongitudeDdEditor().setModel(getModel().getLongitude()); + ui.getLongitudeDmsEditor().setEnabled(false); + ui.getLongitudeDmdEditor().setEnabled(false); + ui.getLongitudeDdEditor().setEnabled(true); + } + + public String getLatitudeText(Float latitude) { + return t("jaxxdemo.coordinate.result.latitude", latitude); + } + + public String getLongitudeText(Float longitude) { + return t("jaxxdemo.coordinate.result.longitude", longitude); + } + + protected CoordinateDemoModel getModel() { + return ui.getModel(); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/gis/CoordinateDemoModel.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/gis/CoordinateDemoModel.java new file mode 100644 index 0000000..33dc68d --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/editor/gis/CoordinateDemoModel.java @@ -0,0 +1,64 @@ +package org.nuiton.jaxx.demo.component.jaxx.editor.gis; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.jdesktop.beans.AbstractSerializableBean; + +/** + * Created on 11/26/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class CoordinateDemoModel extends AbstractSerializableBean { + + public static final String PROPERTY_LONGITUDE = "longitude"; + + public static final String PROPERTY_LATITUDE = "latitude"; + + private static final long serialVersionUID = 1L; + + protected Float latitude; + + protected Float longitude; + + public Float getLongitude() { + return longitude; + } + + public void setLongitude(Float longitude) { + Object oldValue = getLongitude(); + this.longitude = longitude; + firePropertyChange(PROPERTY_LONGITUDE, oldValue, longitude); + } + + public Float getLatitude() { + return latitude; + } + + public void setLatitude(Float latitude) { + Object oldValue = getLatitude(); + this.latitude = latitude; + firePropertyChange(PROPERTY_LATITUDE, oldValue, latitude); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemo.jaxx new file mode 100644 index 0000000..2ade9cf --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemo.jaxx @@ -0,0 +1,76 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.widgets.datetime.DateTimeEditor + </import> + + <DateTimeEditorDemoModel id='model' initializer='getContextValue(DateTimeEditorDemoModel.class)'/> + + <JPanel layout='{new BorderLayout()}' constraints='BorderLayout.NORTH'> + <Table id="configPanel" constraints='BorderLayout.NORTH'> + <row> + <cell anchor='west'> + <JLabel id='labelConfigLabel'/> + </cell> + <cell fill='both' weightx='1'> + <JTextField id='labelConfig'/> + </cell> + </row> + <row> + <cell> + <JLabel id='formatConfigLabel'/> + </cell> + <cell fill='both' weightx='1'> + <JTextField id='formatConfig'/> + </cell> + </row> + <row> + <cell anchor='west' columns="2"> + <JCheckBox id='dateEditableButton'/> + </cell> + </row> + <row> + <cell anchor='west' columns="2"> + <JCheckBox id='timeEditableButton'/> + </cell> + </row> + <row> + <cell anchor='west' columns="2"> + <JCheckBox id='enableButton'/> + </cell> + </row> + </Table> + <DateTimeEditor id='editor' constructorParams='this' constraints='BorderLayout.CENTER'/> + </JPanel> + + <JPanel id='result' layout='{new GridLayout(0,2)}' constraints='BorderLayout.CENTER'> + <JLabel id='resultDateLabel'/> + <JTextField id='resultDate'/> + <JLabel id='resultDayDateLabel'/> + <JTextField id='resultDayDate'/> + <JLabel id='resultTimeDateLabel'/> + <JTextField id='resultTimeDate'/> + </JPanel> + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemoHandler.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemoHandler.java new file mode 100644 index 0000000..848337f --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemoHandler.java @@ -0,0 +1,80 @@ +package org.nuiton.jaxx.demo.component.jaxx.widgets.datetime; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.spi.UIHandler; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Created on 9/9/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.12 + */ +public class DateTimeEditorDemoHandler implements UIHandler<DateTimeEditorDemo> { + + protected final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + + protected final DateFormat dayDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + + protected final DateFormat timeDateFormat = new SimpleDateFormat("HH:mm"); + + @Override + public void beforeInit(DateTimeEditorDemo ui) { + + DateTimeEditorDemoModel model = new DateTimeEditorDemoModel(); + + Date now = new Date(); + + model.setDate(now); + model.setDayDate(now); + model.setTimeDate(now); + + ui.setContextValue(model); + + } + + @Override + public void afterInit(final DateTimeEditorDemo ui) { + + // init editor + ui.getEditor().init(); + + } + + public String getDate(Date date) { + return dateFormat.format(date); + } + + public String getDayDate(Date date) { + return dayDateFormat.format(date); + } + + public String getTimeDate(Date date) { + return timeDateFormat.format(date); + } + +} \ No newline at end of file diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemoModel.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemoModel.java new file mode 100644 index 0000000..04ba351 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/DateTimeEditorDemoModel.java @@ -0,0 +1,74 @@ +package org.nuiton.jaxx.demo.component.jaxx.widgets.datetime; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.jdesktop.beans.AbstractSerializableBean; + +import java.util.Date; + +/** + * Created on 9/10/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.12 + */ +public class DateTimeEditorDemoModel extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + protected Date date; + + protected Date dayDate; + + protected Date timeDate; + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + Date oldValue = getDate(); + this.date = date; + firePropertyChange("date", oldValue, date); + } + + public Date getDayDate() { + return dayDate; + } + + public void setDayDate(Date dayDate) { + Date oldValue = getDayDate(); + this.dayDate = dayDate; + firePropertyChange("dayDate", oldValue, dayDate); + } + + public Date getTimeDate() { + return timeDate; + } + + public void setTimeDate(Date timeDate) { + Date oldValue = getTimeDate(); + this.timeDate = timeDate; + firePropertyChange("timeDate", oldValue, timeDate); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemo.jaxx new file mode 100644 index 0000000..d6e30f8 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemo.jaxx @@ -0,0 +1,56 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.widgets.datetime.TimeEditor + </import> + + <org.nuiton.jaxx.demo.component.jaxx.widgets.datetime.TimeEditorDemoModel id='model' + initializer='getContextValue(TimeEditorDemoModel.class)'/> + + <JPanel layout='{new BorderLayout()}' constraints='BorderLayout.NORTH'> + <Table id="configPanel" constraints='BorderLayout.NORTH'> + <row> + <cell anchor='west'> + <JLabel id='labelConfigLabel'/> + </cell> + <cell fill='both' weightx='1'> + <JTextField id='labelConfig'/> + </cell> + </row> + <row> + <cell anchor='west' columns="2"> + <JCheckBox id='enableButton'/> + </cell> + </row> + </Table> + <org.nuiton.jaxx.widgets.datetime.TimeEditor id='editor' constructorParams='this' + constraints='BorderLayout.CENTER'/> + </JPanel> + + <JPanel id='result' layout='{new GridLayout(0,2)}' constraints='BorderLayout.CENTER'> + <JLabel id='resultTimeLabel'/> + <JTextField id='resultTime'/> + </JPanel> + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemoHandler.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemoHandler.java new file mode 100644 index 0000000..34080c2 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemoHandler.java @@ -0,0 +1,66 @@ +package org.nuiton.jaxx.demo.component.jaxx.widgets.datetime; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.spi.UIHandler; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Created on 11/30/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.18 + */ +public class TimeEditorDemoHandler implements UIHandler<TimeEditorDemo> { + + protected final DateFormat timeFormat = new SimpleDateFormat("HH:mm"); + + @Override + public void beforeInit(TimeEditorDemo ui) { + + TimeEditorDemoModel model = new TimeEditorDemoModel(); + + Date now = new Date(); + + model.setTime(now); + + ui.setContextValue(model); + + } + + @Override + public void afterInit(final TimeEditorDemo ui) { + + // init editor + ui.getEditor().init(); + + } + + public String getTime(Date date) { + return timeFormat.format(date); + } + +} \ No newline at end of file diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemoModel.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemoModel.java new file mode 100644 index 0000000..b5cadd7 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/datetime/TimeEditorDemoModel.java @@ -0,0 +1,50 @@ +package org.nuiton.jaxx.demo.component.jaxx.widgets.datetime; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.jdesktop.beans.AbstractSerializableBean; + +import java.util.Date; + +/** + * Created on 11/30/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.18 + */ +public class TimeEditorDemoModel extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + protected Date time; + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + Date oldValue = getTime(); + this.time = time; + firePropertyChange("time", oldValue, time); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemo.jaxx new file mode 100644 index 0000000..b32fc64 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemo.jaxx @@ -0,0 +1,55 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.widgets.gis.absolute.CoordinatesEditor + </import> + + <CoordinatesEditorDemoModel id='model' initializer='getContextValue(CoordinatesEditorDemoModel.class)'/> + + <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> + <row> + <cell> + <JPanel id='config' layout='{new GridLayout(0,1)}'> + <JCheckBox id='showReset'/> + <JCheckBox id='enableButton'/> + <JCheckBox id='displayZeroWhenNull'/> + </JPanel> + </cell> + </row> + <row> + <cell> + <CoordinatesEditor id='editor'/> + </cell> + </row> + <row> + <cell> + <JPanel id='result' layout='{new GridLayout(0,1)}'> + <JLabel id='resultQuadrant'/> + <JLabel id='resultLatitude'/> + <JLabel id='resultLongitude'/> + </JPanel> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemoHandler.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemoHandler.java new file mode 100644 index 0000000..a8ad7ed --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemoHandler.java @@ -0,0 +1,68 @@ +package org.nuiton.jaxx.demo.component.jaxx.widgets.gis; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.spi.UIHandler; + +import static org.nuiton.i18n.I18n.t; + +/** + * Created on 9/1/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.12 + */ +public class CoordinatesEditorDemoHandler implements UIHandler<CoordinatesEditorDemo> { + + @Override + public void beforeInit(CoordinatesEditorDemo ui) { + + CoordinatesEditorDemoModel model = new CoordinatesEditorDemoModel(); + model.setLatitude(-1.5261505f); + model.setLongitude(47.1963537f); + model.setQuadrant(1); + + ui.setContextValue(model); + + } + + @Override + public void afterInit(final CoordinatesEditorDemo ui) { + + ui.getEditor().init(); + + } + + public String getQuadrant(Integer quadrant) { + return t("jaxxdemo.coordinate.result.quadrant", quadrant); + } + + public String getLatitude(Float latitude) { + return t("jaxxdemo.coordinate.result.latitude", latitude); + } + + public String getLongitude(Float longitude) { + return t("jaxxdemo.coordinate.result.longitude", longitude); + } + +} \ No newline at end of file diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemoModel.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemoModel.java new file mode 100644 index 0000000..3585f32 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/gis/CoordinatesEditorDemoModel.java @@ -0,0 +1,72 @@ +package org.nuiton.jaxx.demo.component.jaxx.widgets.gis; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.jdesktop.beans.AbstractSerializableBean; + +/** + * Created on 9/3/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.12 + */ +public class CoordinatesEditorDemoModel extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + protected Integer quadrant; + + protected Float latitude; + + protected Float longitude; + + public Integer getQuadrant() { + return quadrant; + } + + public void setQuadrant(Integer quadrant) { + Object oldValue = getQuadrant(); + this.quadrant = quadrant; + firePropertyChange("quadrant", oldValue, quadrant); + } + + public Float getLatitude() { + return latitude; + } + + public void setLatitude(Float latitude) { + Object oldValue = getLatitude(); + this.latitude = latitude; + firePropertyChange("latitude", oldValue, latitude); + } + + public Float getLongitude() { + return longitude; + } + + public void setLongitude(Float longitude) { + Object oldValue = getLongitude(); + this.longitude = longitude; + firePropertyChange("longitude", oldValue, longitude); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemo.jaxx new file mode 100644 index 0000000..3cf9faf --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemo.jaxx @@ -0,0 +1,112 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.widgets.number.NumberEditor + + static org.nuiton.i18n.I18n.t + </import> + + <org.nuiton.jaxx.demo.component.jaxx.widgets.number.NumberEditorDemoModel id='model' + initializer="getContextValue(NumberEditorDemoModel.class)"/> + + <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> + <!-- config --> + <row> + <cell> + <Table id='numberEditorConfigurationPanel' insets='1' fill='both' weightx='1'> + <row> + <cell columns="3"> + <JCheckBox id='showPopupButton'/> + </cell> + </row> + <row> + <cell columns="3"> + <JCheckBox id='showResetButton'/> + </cell> + </row> + <row> + <cell columns="3"> + <JCheckBox id='autoPopupButton'/> + </cell> + </row> + <row> + <cell anchor="west"> + <JLabel id='integerNumberConfig'/> + </cell> + <cell weightx="1" fill="both"> + <JTextField id='integerNumberPattern' text='{"-?\\d{0,3}"}'/> + </cell> + <cell anchor="east"> + <JCheckBox id='integerNumberEnabled'/> + </cell> + </row> + <row> + <cell anchor="west"> + <JLabel id='floatNumberConfig'/> + </cell> + <cell weightx="1" fill="both"> + <JTextField id='floatNumberPattern' text='{"\\d{0,1}.\\d{0,2}"}'/> + </cell> + <cell anchor="east"> + <JCheckBox id='floatNumberEnabled'/> + </cell> + </row> + <row> + <cell anchor="west"> + <JLabel id='doubleNumberConfig'/> + </cell> + <cell weightx="1" fill="both"> + <JTextField id='doubleNumberPattern' text='{"-?\\d{0,4}.\\d{0,6}"}'/> + </cell> + <cell anchor="east"> + <JCheckBox id='doubleNumberEnabled'/> + </cell> + </row> + </Table> + </cell> + </row> + <!-- editors --> + <row> + <cell> + <JPanel layout="{new GridLayout()}"> + <org.nuiton.jaxx.widgets.number.NumberEditor id='integerEditor' constructorParams='this'/> + <org.nuiton.jaxx.widgets.number.NumberEditor id='floatEditor' constructorParams='this'/> + <org.nuiton.jaxx.widgets.number.NumberEditor id='doubleEditor' constructorParams='this'/> + </JPanel> + </cell> + </row> + <!-- result --> + <row> + <cell> + <JPanel id='resultPanel' layout='{new GridLayout(0,1)}'> + <JLabel id='resultInteger'/> + <JLabel id='resultFloat'/> + <JLabel id='resultDouble'/> + </JPanel> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> + diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemoHandler.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemoHandler.java new file mode 100644 index 0000000..4e2d022 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemoHandler.java @@ -0,0 +1,56 @@ +package org.nuiton.jaxx.demo.component.jaxx.widgets.number; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.spi.UIHandler; + +/** + * Created on 11/23/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since XXX + */ +public class NumberEditorDemoHandler implements UIHandler<NumberEditorDemo> { + + @Override + public void beforeInit(NumberEditorDemo ui) { + + NumberEditorDemoModel model = new NumberEditorDemoModel(); + model.setIntegerNumber(10); + model.setFloatNumber(-10.10f); + model.setDoubleNumber(-0.0001d); + + ui.setContextValue(model); + + } + + @Override + public void afterInit(NumberEditorDemo ui) { + + ui.integerEditor.init(); + ui.floatEditor.init(); + ui.doubleEditor.init(); + + } + +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemoModel.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemoModel.java new file mode 100644 index 0000000..86635aa --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/number/NumberEditorDemoModel.java @@ -0,0 +1,72 @@ +package org.nuiton.jaxx.demo.component.jaxx.widgets.number; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.jdesktop.beans.AbstractSerializableBean; + +/** + * Created on 11/23/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.17 + */ +public class NumberEditorDemoModel extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + protected Integer integerNumber; + + protected Float floatNumber; + + protected Double doubleNumber; + + public Integer getIntegerNumber() { + return integerNumber; + } + + public void setIntegerNumber(Integer integerNumber) { + Number oldValue = getIntegerNumber(); + this.integerNumber = integerNumber; + firePropertyChange("integerNumber", oldValue, integerNumber); + } + + public Float getFloatNumber() { + return floatNumber; + } + + public void setFloatNumber(Float floatNumber) { + Number oldValue = getFloatNumber(); + this.floatNumber = floatNumber; + firePropertyChange("floatNumber", oldValue, floatNumber); + } + + public Double getDoubleNumber() { + return doubleNumber; + } + + public void setDoubleNumber(Double doubleNumber) { + Number oldValue = getDoubleNumber(); + this.doubleNumber = doubleNumber; + firePropertyChange("doubleNumber", oldValue, doubleNumber); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemo.jaxx new file mode 100644 index 0000000..3c36b43 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemo.jaxx @@ -0,0 +1,55 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.demo.entities.People + org.nuiton.jaxx.widgets.select.FilterableDoubleList + </import> + + <FilterableDoubleListDemoModel id="model" initializer='getContextValue(FilterableDoubleListDemoModel.class)'/> + + <Table fill='both'> + <row> + <cell> + <JPanel id='configurationPanel' layout='{new GridLayout(0,1)}'> + <JCheckBox id='filterableButton'/> + <JCheckBox id='highlightFilterTextButton'/> + <JCheckBox id='showResetButton'/> + <JCheckBox id='showDecoratorButton'/> + <JCheckBox id='enableButton'/> + </JPanel> + </cell> + </row> + <row> + <cell weighty='0.5' weightx='1'> + <FilterableDoubleList id='doubleList' genericType='People'/> + </cell> + </row> + <row> + <cell weighty='0.5' weightx='1'> + <JTextPane id="result"/> + </cell> + </row> + </Table> + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemoHandler.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemoHandler.java new file mode 100644 index 0000000..b8a9a05 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemoHandler.java @@ -0,0 +1,98 @@ +package org.nuiton.jaxx.demo.component.jaxx.widgets.select; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.nuiton.decorator.JXPathDecorator; +import org.nuiton.jaxx.demo.entities.DemoDataProvider; +import org.nuiton.jaxx.demo.entities.DemoDecoratorProvider; +import org.nuiton.jaxx.demo.entities.People; +import org.nuiton.jaxx.widgets.select.FilterableDoubleList; + +import java.util.List; + +import static org.nuiton.i18n.I18n.t; + +/** + * Created on 11/28/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.18 + */ +public class FilterableDoubleListDemoHandler implements UIHandler<FilterableDoubleListDemo> { + + private JXPathDecorator<People> decorator; + + @Override + public void beforeInit(FilterableDoubleListDemo ui) { + + decorator = (JXPathDecorator<People>) new DemoDecoratorProvider().getDecoratorByType(People.class); + + FilterableDoubleListDemoModel model = new FilterableDoubleListDemoModel(); + ui.setContextValue(model); + + } + + @Override + public void afterInit(final FilterableDoubleListDemo ui) { + + FilterableDoubleList<People> doubleList = ui.getDoubleList(); + + DemoDataProvider demoDataProvider = new DemoDataProvider(); + + List<People> data = demoDataProvider.getPeoples(); + List<People> selected = data.subList(0, 1); + + doubleList.init(decorator, data, selected); + + } + + public String updateResultText(List<People> selected) { + + StringBuilder builder = new StringBuilder(); + if (selected == null || selected.isEmpty()) { + + builder.append(t("jaxxdemo.beandoublelistdemo.noselected")); + + } else { + + builder.append(t("jaxxdemo.beandoublelistdemo.selected")); + builder.append("<ul>"); + + for (People people : selected) { + + String peopleStr = decorator.toString(people); + builder.append("<li>"); + builder.append(peopleStr); + builder.append("</li>"); + + } + + builder.append("</ul>"); + + } + + return builder.toString(); + + } +} \ No newline at end of file diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemoModel.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemoModel.java new file mode 100644 index 0000000..80c8fdf --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/jaxx/widgets/select/FilterableDoubleListDemoModel.java @@ -0,0 +1,52 @@ +package org.nuiton.jaxx.demo.component.jaxx.widgets.select; + +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.jdesktop.beans.AbstractSerializableBean; +import org.nuiton.jaxx.demo.entities.People; + +import java.util.List; + +/** + * Created on 11/28/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.18 + */ +public class FilterableDoubleListDemoModel extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + public static final String PROPERTY_SELECTED = "selected"; + + List<People> selected; + + public List<People> getSelected() { + return selected; + } + + public void setSelected(List<People> selected) { + this.selected = selected; + firePropertyChange(PROPERTY_SELECTED, null, selected); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/HidorButtonDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/HidorButtonDemo.jaxx new file mode 100644 index 0000000..125573f --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/HidorButtonDemo.jaxx @@ -0,0 +1,42 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel layout='{new GridLayout(0,1)}'> + + <HBox horizontalAlignment='center' verticalAlignment='middle'> + + <org.nuiton.jaxx.runtime.swing.HidorButton target='{hidor1}' showText="show label1" + hideText='hide label1' + targetVisible='{true}'/> + + <JLabel id='hidor1' text='Label 1'/> + </HBox> + <HBox horizontalAlignment='center' verticalAlignment='middle'> + + <org.nuiton.jaxx.runtime.swing.HidorButton target='{hidor2}' showText="show label2" + hideText='hide label2' + targetVisible='{false}'/> + + <JLabel id='hidor2' text='Label 2'/> + </HBox> + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JButtonDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JButtonDemo.jaxx new file mode 100644 index 0000000..1337c0f --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JButtonDemo.jaxx @@ -0,0 +1,61 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel id='topDemoPanel' decorator='help'> + <style> + JButton.fancy { + foreground: blue; + font-face: Arial; + font-size: 18; + } + + JButton.fancy:mouseover { + foreground: red; + font-style: italic; + } + </style> + + <script> + public void buttonClicked(JButton button) { + JOptionPane.showMessageDialog(this, button.getText() + " clicked!", + "onActionPerformed", + JOptionPane.INFORMATION_MESSAGE); + } + </script> + + <import> + javax.swing.JOptionPane + java.awt.Color + </import> + + <String id='helpDefaultId' initializer='"ui.component.swing.buttons.JButtonDemo"'/> + + <javax.swing.ImageIcon id='pencil' + constructorParams='getClass().getResource("/org/nuiton/jaxx/demo/images/pencil_black.gif")'/> + + <VBox horizontalAlignment='center' verticalAlignment='middle'> + <JButton id='simpleButon' text='Simple Button' + onActionPerformed='buttonClicked((JButton) event.getSource())'/> + <JButton id='fancyButon' text='Fancy Button' styleClass='fancy' icon='{pencil}' + onActionPerformed='buttonClicked((JButton) event.getSource())'/> + </VBox> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JButtonDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JButtonDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/swing/JButtonDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JButtonDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JCheckBoxDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JCheckBoxDemo.jaxx new file mode 100644 index 0000000..f22293d --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JCheckBoxDemo.jaxx @@ -0,0 +1,62 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel> + <import> + java.awt.Font + </import> + <script><![CDATA[ + public String getText(boolean bold, boolean italic, boolean underline) { + String text ="Sample Text"; + if (bold) + text = "<b>" + text + "</b>"; + if (italic) + text = "<i>" + text + "</i>"; + if (underline) + text = "<u>" + text + "</u>"; + return "<html>" + text; + } + ]]></script> + <VBox horizontalAlignment='center' verticalAlignment='middle'> + <Table anchor='west'> + <row> + <cell> + <JCheckBox id='bold' text='Bold' mnemonic='B'/> + </cell> + <cell rows='3'> + <JLabel font='{new Font("Arial", 0, 18)}' + text='{getText(bold.isSelected(), italic.isSelected(), underline.isSelected())}'/> + </cell> + </row> + <row> + <cell> + <JCheckBox id='italic' text='Italic' mnemonic='I'/> + </cell> + </row> + <row> + <cell> + <JCheckBox id='underline' text='Underline' mnemonic='U'/> + </cell> + </row> + </Table> + </VBox> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JCheckBoxMenuItemDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JCheckBoxMenuItemDemo.jaxx similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/swing/JCheckBoxMenuItemDemo.jaxx rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JCheckBoxMenuItemDemo.jaxx diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JComboBoxDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JComboBoxDemo.jaxx new file mode 100644 index 0000000..d7ffc33 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JComboBoxDemo.jaxx @@ -0,0 +1,70 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<org.nuiton.jaxx.demo.DemoPanel> + <import> + javax.swing.DefaultComboBoxModel + static org.nuiton.i18n.I18n.n + </import> + + <script><![CDATA[ +private void $afterCompleteSetup() { + jaxxComboBox.setSelectedIndex(0); +} +]]> + </script> + <Table> + <row> + <cell> + <JLabel text='Button label:'/> + </cell> + + <cell> + <JAXXComboBox id='jaxxComboBox' editable='true'> + <item value='{t("OK")}' selected='true'/> + <item value='{t("Cancel")}'/> + <item value='{t("Help")}'/> + </JAXXComboBox> + </cell> + + <cell> + <JButton text='{String.valueOf(jaxxComboBox.getSelectedItem())}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Button label:'/> + </cell> + + <cell> + <JComboBox id='comboBox' + editable='true' + model='{new DefaultComboBoxModel(new Object[]{n("OK"),n("Cancel"),n("Help")})}'/> + </cell> + + <cell> + <JButton text='{comboBox.getSelectedItem()+""}'/> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JDialogDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JDialogDemo.jaxx new file mode 100644 index 0000000..59bf458 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JDialogDemo.jaxx @@ -0,0 +1,110 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel> + <import> + javax.swing.JRootPane + javax.swing.JComponent + javax.swing.KeyStroke + </import> + <script> + String username; + String password; + + private class OKAction extends javax.swing.AbstractAction { + public OKAction() { + putValue(NAME, "OK"); + } + + public void actionPerformed(ActionEvent e) { + username = usernameField.getText(); + password = new String(passwordField.getPassword()); + dialog.dispose(); + } + } + + + private class CancelAction extends javax.swing.AbstractAction { + public CancelAction() { + putValue(NAME, "Cancel"); + } + + + public void actionPerformed(ActionEvent e) { + dialog.dispose(); + } + } + { + JRootPane rootPane = dialog.getRootPane(); + rootPane.setDefaultButton(ok); + rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ESCAPE"), + "cancel"); + rootPane.getActionMap().put("cancel", new CancelAction()); + } + </script> + + <VBox horizontalAlignment='center' verticalAlignment='middle'> + <JButton text='Show password dialog' + onActionPerformed='dialog.setVisible(true)'/> + <VBox> + <JLabel text='{username != null ? "Username: " + username : ""}'/> + <JLabel text='{password != null ? "Password: " + password : ""}'/> + </VBox> + </VBox> + + <JDialog title='Sign on' id='dialog' modal='true' onWindowOpened='dialog.setLocationRelativeTo(JDialogDemo.this); + passwordField.setText("");'> + <Table> + <row> + <cell> + <JLabel text='Username:' displayedMnemonic='U' + labelFor='{usernameField}'/> + </cell> + + <cell> + <JTextField id='usernameField'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Password:' displayedMnemonic='P' + labelFor='{passwordField}'/> + </cell> + + <cell> + <JPasswordField id='passwordField'/> + </cell> + </row> + + <row> + <cell columns='2'> + <JPanel layout='{new GridLayout(1, 0, 6, 6)}'> + <JButton id='ok' text='OK' action='{new OKAction()}'/> + <JButton text='Cancel' action='{new CancelAction()}'/> + </JPanel> + </cell> + </row> + </Table> + </JDialog> + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JListDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JListDemo.jaxx new file mode 100644 index 0000000..ac8f51d --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JListDemo.jaxx @@ -0,0 +1,81 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel> + <Table> + <row> + <cell> + <JLabel text='Supported Swing components:'/> + </cell> + </row> + + <row> + <cell> + <JScrollPane> + <JAXXList> + <item value='JApplet'/> + <item value='JButton'/> + <item value='JCheckBox'/> + <item value='JCheckBoxMenuItem'/> + <item value='JColorChooser'/> + <item value='JComboBox'/> + <item value='JDesktopPane'/> + <item value='JDialog'/> + <item value='JEditorPane'/> + <item value='JFileChooser'/> + <item value='JFormattedTextField'/> + <item value='JFrame'/> + <item value='JInternalFrame'/> + <item value='JLabel'/> + <item value='JLayeredPane'/> + <item value='JList'/> + <item value='JMenu'/> + <item value='JMenuBar'/> + <item value='JMenuItem'/> + <item value='JOptionPane'/> + <item value='JPanel'/> + <item value='JPasswordField'/> + <item value='JPopupMenu'/> + <item value='JProgressBar'/> + <item value='JRadioButton'/> + <item value='JRadioButtonMenuItem'/> + <item value='JScrollBar'/> + <item value='JScrollPane'/> + <item value='JSeparator'/> + <item value='JSlider'/> + <item value='JSpinner'/> + <item value='JSplitPane'/> + <item value='JTabbedPane'/> + <item value='JTable'/> + <item value='JTextArea'/> + <item value='JTextField'/> + <item value='JTextPane'/> + <item value='JToggleButton'/> + <item value='JToolBar'/> + <item value='JTree'/> + <item value='JWindow'/> + </JAXXList> + </JScrollPane> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JMenuItemDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JMenuItemDemo.jaxx new file mode 100644 index 0000000..592b85f --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JMenuItemDemo.jaxx @@ -0,0 +1,49 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel> + <import> + javax.swing.JOptionPane + </import> + + <script> + void $afterCompleteSetup(){} + </script> + + <JDesktopPane width='350' height='400' background='{null}'> + <JInternalFrame title='JMenu demo' width='300' height='250' + resizable='true'> + <JMenuBar id='menuBar'> + <JMenu text='Demo'> + <JMenuItem text='Message Box' + onActionPerformed='JOptionPane.showMessageDialog(this, "Menu item clicked")'/> + </JMenu> + </JMenuBar> + + <JPanel id='framePanel'> + <JLabel text='JMenu demo' id='demoMessage' + horizontalAlignment='center'/> + </JPanel> + </JInternalFrame> + </JDesktopPane> + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JPasswordFieldDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JPasswordFieldDemo.jaxx new file mode 100644 index 0000000..84d018b --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JPasswordFieldDemo.jaxx @@ -0,0 +1,32 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel> + <VBox horizontalAlignment='center' verticalAlignment='middle'> + <HBox> + <JLabel text='Password:' displayedMnemonic='P' labelFor='{password}'/> + <JPasswordField id='password'/> + </HBox> + + <JLabel text='You entered: {new String(password.getPassword())}'/> + </VBox> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JProgressBarDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JProgressBarDemo.jaxx new file mode 100644 index 0000000..c62f8c0 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JProgressBarDemo.jaxx @@ -0,0 +1,120 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + <import> + java.awt.Color + javax.swing.Timer + javax.swing.UIManager + </import> + + <Integer id='red' javaBean='0'/> + <Integer id='green' javaBean='0'/> + <Integer id='blue' javaBean='0'/> + <Integer id='speed' initializer='2'/> + <Integer id='redDirection' initializer='1'/> + <Integer id='greenDirection' initializer='1'/> + <Integer id='blueDirection' initializer='1'/> + <Timer id='redTimer' constructorParams='5, null' + onActionPerformed='changeRedValue()'/> + <Timer id='greenTimer' constructorParams='50, null' + onActionPerformed='changeGreenValue()'/> + <Timer id='blueTimer' constructorParams='500, null' + onActionPerformed='changeBlueValue()'/> + + + <script><![CDATA[ +void startTimers() { + redTimer.start(); + greenTimer.start(); + blueTimer.start(); +} + +void stopTimers() { + redTimer.stop(); + greenTimer.stop(); + blueTimer.stop(); +} + +void $afterCompleteSetup() { + startTimers(); +} + +protected void changeRedValue() { + setRed(Math.max(0, Math.min(255, red + speed * redDirection))); + if (red == 0 || red == 255) { + redDirection = -redDirection; + } +} +protected void changeGreenValue() { + setGreen(Math.max(0, Math.min(255, green + speed * greenDirection))); + if (green == 0 || green == 255) { + greenDirection = -greenDirection; + } +} +protected void changeBlueValue() { + setBlue(Math.max(0, Math.min(255, blue + speed * blueDirection))); + if (blue == 0 || blue == 255) { + blueDirection = -blueDirection; + } +} + ]]></script> + + <Table insets='6' constraints='BorderLayout.CENTER'> + <row> + <cell columns='3'> + <JLabel text='Welcome to the JAXX framework!' + font='{UIManager.getFont("Label.font").deriveFont(18f)}' + foreground='{new Color(getRed(), getGreen(), getBlue())}'/> + </cell> + </row> + <row> + <cell columns='3' fill='horizontal'> + <JProgressBar id='redProgressBar' + foreground='{new Color(getRed(), 0, 0)}' + value='{getRed()}' maximum='255'/> + </cell> + </row> + <row> + <cell columns='3' fill='horizontal'> + <JProgressBar id='greenProgressBar' + foreground='{new Color(0, getGreen(), 0)}' + value='{getGreen()}' maximum='255'/> + </cell> + </row> + <row> + <cell columns='3' fill='horizontal'> + <JProgressBar id='blueProgressBar' + foreground='{new Color(0, 0, getBlue())}' + value='{getBlue()}' maximum='255'/> + </cell> + </row> + <row> + <cell weightx='1' anchor='east'> + <JButton text='Start' onActionPerformed='startTimers()'/> + </cell> + <cell> + <JButton text='Stop' onActionPerformed='stopTimers()'/> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JRadioButtonDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JRadioButtonDemo.jaxx new file mode 100644 index 0000000..d77bcea --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JRadioButtonDemo.jaxx @@ -0,0 +1,41 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel> + <import> + javax.swing.ImageIcon + </import> + + <HBox horizontalAlignment='center' verticalAlignment='middle'> + <VBox> + <JRadioButton text='Animal' value='Lynx.jpg' buttonGroup='radioButtons' + selected='true'/> + <JRadioButton text='Vegetable' buttonGroup='radioButtons' + value='Tomato.jpg'/> + <JRadioButton text='Mineral' buttonGroup='radioButtons' + value='Amethyst.jpg'/> + </VBox> + + <JLabel + icon='{new ImageIcon(getClass().getResource("/org/nuiton/jaxx/demo/images/" + radioButtons.getSelectedValue()))}'/> + </HBox> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/component/swing/JRadioButtonMenuItemDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JRadioButtonMenuItemDemo.jaxx similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/component/swing/JRadioButtonMenuItemDemo.jaxx rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JRadioButtonMenuItemDemo.jaxx diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JSliderDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JSliderDemo.jaxx new file mode 100644 index 0000000..ca2859d --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JSliderDemo.jaxx @@ -0,0 +1,39 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel> + <import> + java.awt.Color + </import> + + <HBox horizontalAlignment='center' verticalAlignment='middle'> + <VBox> + <JSlider id='red' maximum='255' value='200'/> + <JSlider id='green' maximum='255' value='180'/> + <JSlider id='blue' maximum='255' value='240'/> + </VBox> + + <JPanel border='{BorderFactory.createEtchedBorder()}' width='64' + height='64' + background='{new Color(red.getValue(), green.getValue(), blue.getValue())}'/> + </HBox> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JSpinnerDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JSpinnerDemo.jaxx new file mode 100644 index 0000000..0513863 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JSpinnerDemo.jaxx @@ -0,0 +1,34 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel> + + <JLabel text='Spacing:' displayedMnemonic='S' labelFor='{spinner}'/> + + <JSpinner minimum='0' maximum='50' id='spinner'/> + + <VBox spacing='{(Integer) spinner.getValue()}'> + <JLabel text='Use the spinner to'/> + <JLabel text='adjust the spacing'/> + <JLabel text='between these lines'/> + </VBox> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JSplitPaneDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JSplitPaneDemo.jaxx new file mode 100644 index 0000000..eee2371 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JSplitPaneDemo.jaxx @@ -0,0 +1,38 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel> + <import> + javax.swing.ImageIcon + </import> + <JSplitPane> + <JScrollPane> + <JLabel + icon='{new ImageIcon(getClass().getResource("/org/nuiton/jaxx/demo/images/Amethyst.jpg"))}'/> + </JScrollPane> + + <JScrollPane> + <JLabel + icon='{new ImageIcon(getClass().getResource("/org/nuiton/jaxx/demo/images/Lynx.jpg"))}'/> + </JScrollPane> + </JSplitPane> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JTextAreaDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JTextAreaDemo.jaxx new file mode 100644 index 0000000..b947632 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JTextAreaDemo.jaxx @@ -0,0 +1,51 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel> + <Table constraints='BorderLayout.CENTER'> + <row> + <cell> + <JLabel text='Normal text:' displayedMnemonic='N' + labelFor='{textArea}'/> + </cell> + + <cell weightx='1' fill='both' anchor='east'> + <JScrollPane> + <JTextArea id='textArea' text='Try typing some text here.'/> + </JScrollPane> + </cell> + </row> + + <row> + <cell> + <JLabel text='Upper case text:' labelFor='{upperTextArea}'/> + </cell> + + <cell weightx='1' fill='both'> + <JScrollPane> + <JTextArea id='upperTextArea' editable='false' background='{null}' + text='{textArea.getText().toUpperCase()}'/> + </JScrollPane> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JTextFieldDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JTextFieldDemo.jaxx new file mode 100644 index 0000000..519891c --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JTextFieldDemo.jaxx @@ -0,0 +1,45 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel> + <import> + javax.swing.JOptionPane + </import> + <Table> + <row> + <cell> + <JLabel text='Your name:' displayedMnemonic='n' labelFor='{textField}'/> + </cell> + + <cell> + <JTextField id='textField'/> + </cell> + </row> + + <row> + <cell columns='2'> + <JButton text='Greet' + onActionPerformed='JOptionPane.showMessageDialog(this, "Hello, " + textField.getText() + "!")'/> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JToggleButtonDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JToggleButtonDemo.jaxx new file mode 100644 index 0000000..8264f7f --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/component/swing/JToggleButtonDemo.jaxx @@ -0,0 +1,32 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel> + <HBox horizontalAlignment='center' verticalAlignment='middle'> + <JToggleButton text='1' id='one'/> + <JToggleButton text='2' id='two'/> + <JToggleButton text='3' id='three'/> + + <JLabel + text='Total: {(one.isSelected() ? 1 : 0) + (two.isSelected() ? 2 : 0) + (three.isSelected() ? 3 : 0)}'/> + </HBox> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/AbstractDemoBean.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/AbstractDemoBean.java new file mode 100644 index 0000000..bd561b6 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/AbstractDemoBean.java @@ -0,0 +1,79 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.demo.entities; + +import org.jdesktop.beans.AbstractSerializableBean; + +import static org.nuiton.i18n.I18n.n; + +/** + * Abstract demo bean. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.2 + */ +public abstract class AbstractDemoBean extends AbstractSerializableBean { + + static { + n("jaxxdemo.common.id"); + n("jaxxdemo.common.image"); + } + + public static final String PROPERTY_ID = "id"; + + public static final String PROPERTY_IMAGE = "image"; + + private static final long serialVersionUID = 1L; + + protected String id; + + protected String image; + + public AbstractDemoBean() { + } + + protected AbstractDemoBean(String id, String image) { + this.id = id; + this.image = image; + } + + public String getId() { + return id; + } + + public String getImage() { + return image; + } + + public void setId(String id) { + String old = this.id; + this.id = id; + firePropertyChange(PROPERTY_ID, old, id); + } + + + public void setImage(String image) { + Object oldValue = this.image; + this.image = image; + firePropertyChange(PROPERTY_IMAGE, oldValue, image); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/DemoDataProvider.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/DemoDataProvider.java new file mode 100644 index 0000000..3bf5456 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/DemoDataProvider.java @@ -0,0 +1,113 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.entities; + +import org.nuiton.jaxx.runtime.swing.nav.NavDataProvider; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Sylvain Lletellier + * @since 2.1 + */ +public class DemoDataProvider implements NavDataProvider { + + /** Logger */ + static private final Log log = LogFactory.getLog(DemoDataProvider.class); + + protected Map<String, Movie> movies; + + protected Map<String, People> peoples; + + public DemoDataProvider() { + + movies = new HashMap<String, Movie>(); + peoples = new HashMap<String, People>(); + + if (log.isDebugEnabled()) { + log.debug("for " + this); + } + People a = new People("0", "Jack", "Black", 35, "/org/nuiton/jaxx/demo/images/jack.jpg"); + People a2 = new People("1", "Héctor", "Jiménez", 28, "/org/nuiton/jaxx/demo/images/hector.jpg"); + People a3 = new People("2", "Ana", "de la Reguera", 34, "/org/nuiton/jaxx/demo/images/ana.jpg"); + People a4 = new People("3", "Jack", "Nicholson", 76, "/org/nuiton/jaxx/demo/images/joker.jpg"); + People a5 = new People("4", "Jim", "Parsons", 30, "/org/nuiton/jaxx/demo/images/jim.jpg"); + + Movie m = new Movie("0", "Nacho libre", 1996, "/org/nuiton/jaxx/demo/images/nacho.jpg"); + m.addActor(a); + m.addActor(a2); + m.addActor(a3); + + Movie m2 = new Movie("1", "Nacho 2", 2009, "/org/nuiton/jaxx/demo/images/nacho2.png"); + m2.addActor(a); + m2.addActor(a2); + + movies.put(m.getId(), m); + movies.put(m2.getId(), m2); + + peoples.put(a.getId(), a); + peoples.put(a2.getId(), a2); + peoples.put(a3.getId(), a3); + peoples.put(a4.getId(), a4); + peoples.put(a5.getId(), a5); + } + + @Override + public boolean isEnabled() { + return true; + } + + public Movie getMovie(String id) { + return movies.get(id); + } + + public People getPeople(String id) { + return peoples.get(id); + } + + public List<Movie> getMovies() { + return new ArrayList<Movie>(movies.values()); + } + + public List<People> getPeoples() { + return new ArrayList<People>(peoples.values()); + } + + public List<People> getPeoples(Movie m) { + return m.getActors(); + } + + public List<People> getPeoples(String moviesId) { + + if (log.isDebugEnabled()) { + log.debug("Get people for movie " + moviesId); + } + + return movies.get(moviesId).getActors(); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/DemoDecoratorProvider.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/DemoDecoratorProvider.java new file mode 100644 index 0000000..3fcc8b3 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/DemoDecoratorProvider.java @@ -0,0 +1,48 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.demo.entities; + +import org.nuiton.decorator.DecoratorProvider; + +/** + * Demo decorator provider. + * + * @author Tony Chemit - chemit@codelutin.com + * @see DecoratorProvider + * @since 2.2 + */ +public class DemoDecoratorProvider extends DecoratorProvider { + @Override + protected void loadDecorators() { + + // load movie decorator + registerMultiJXPathDecorator(Movie.class, + "${title}$s#${year}$s", "#", " - "); + + // load people decorator + registerMultiJXPathDecorator(People.class, + "${firstName}$s#${lastName}$s#${age}$s", + "#", + " - " + ); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/Identity.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/Identity.java new file mode 100644 index 0000000..96b7192 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/Identity.java @@ -0,0 +1,105 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.entities; + +import org.jdesktop.beans.AbstractSerializableBean; + +import java.io.File; + +public class Identity extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + protected String firstName = ""; + + protected String lastName = ""; + + protected String email = "dummy@codelutin.com"; + + protected int age = 51; + + protected File config = new File("/tmp"); + + protected File dir = new File("/tmp"); + + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public String getEmail() { + return email; + } + + public int getAge() { + return age; + } + + public File getConfig() { + return config; + } + + public File getDir() { + return dir; + } + + public void setFirstName(String firstName) { + String oldFirstName = this.firstName; + this.firstName = firstName; + firePropertyChange("firstName", oldFirstName, firstName); + } + + public void setLastName(String lastName) { + String oldLastName = this.lastName; + this.lastName = lastName; + firePropertyChange("lastName", oldLastName, lastName); + } + + public void setEmail(String email) { + String oldEmail = this.email; + this.email = email; + firePropertyChange("email", oldEmail, email); + } + + public void setAge(int age) { + int oldAge = this.age; + this.age = age; + firePropertyChange("age", oldAge, age); + } + + public void setConfig(File config) { + File oldConfig = this.config; + this.config = config; + firePropertyChange("config", oldConfig, config); + } + + public void setDir(File dir) { + File oldDir = this.dir; + this.dir = dir; + firePropertyChange("dir", oldDir, dir); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/Model.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/Model.java new file mode 100644 index 0000000..fdbe93e --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/Model.java @@ -0,0 +1,66 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.entities; + +import org.jdesktop.beans.AbstractSerializableBean; + +public class Model extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + protected String text = "text"; + + protected String text2 = "text2"; + + protected int ratio = 51; + + public String getText() { + return text; + } + + public String getText2() { + return text2; + } + + public int getRatio() { + return ratio; + } + + public void setText(String text) { + String oldText = this.text; + this.text = text; + firePropertyChange("text", oldText, text); + } + + public void setText2(String text2) { + String oldText2 = this.text2; + this.text2 = text2; + firePropertyChange("text2", oldText2, text2); + } + + public void setRatio(int ratio) { + int oldRatio = this.ratio; + this.ratio = ratio; + firePropertyChange("ratio", oldRatio, ratio); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/Movie.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/Movie.java new file mode 100644 index 0000000..7355700 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/Movie.java @@ -0,0 +1,138 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.entities; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.ArrayList; +import java.util.List; + +import static org.nuiton.i18n.I18n.n; + +/** + * @author Tony Chemit - chemit@codelutin.com + * @since 1.7.2 + */ +public class Movie extends AbstractDemoBean { + + static { + n("jaxxdemo.common.movie"); + n("jaxxdemo.common.title"); + n("jaxxdemo.common.year"); + n("jaxxdemo.common.actors"); + } + + protected String title; + + protected int year; + + protected List<People> actors; + + private static final long serialVersionUID = 1L; + + private static final String PROPERTY_ACTORS = "actors"; + + private static final String PROPERTY_TITLE = "title"; + + private static final String PROPERTY_YEAR = "year"; + + private static final String PROPERTY_IMAGE = "image"; + + public Movie(String id, String title, int year, String image) { + super(id, image); + this.title = title; + this.year = year; + actors = new ArrayList<People>(); + } + + public Movie() { + actors = new ArrayList<People>(); + } + + public List<People> getActors() { + return actors; + } + + public String getTitle() { + return title; + } + + public int getYear() { + return year; + } + + public void setActors(List<People> actors) { + Object oldValue = this.actors; + this.actors = actors; + firePropertyChange(PROPERTY_ACTORS, null, actors); + } + + public void setTitle(String title) { + Object oldValue = this.title; + this.title = title; + firePropertyChange(PROPERTY_TITLE, oldValue, title); + } + + public void setYear(int year) { + Object oldValue = this.year; + this.year = year; + firePropertyChange(PROPERTY_YEAR, oldValue, year); + } + + + public void addActor(People actor) { + actors.add(actor); + firePropertyChange(PROPERTY_ACTORS, null, actors); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Movie other = (Movie) obj; + return !(id == null ? other.id != null : !id.equals(other.id)); + } + + @Override + public int hashCode() { + int hash = 5; + hash = 41 * hash + (id != null ? id.hashCode() : 0); + return hash; + } + + @Override + public String toString() { + ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); + b.append(PROPERTY_ID, id); + b.append(PROPERTY_TITLE, title); + b.append(PROPERTY_IMAGE, image); + b.append(PROPERTY_YEAR, year); + b.append(PROPERTY_ACTORS, actors); + return b.toString(); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/People.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/People.java new file mode 100644 index 0000000..13dd011 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/entities/People.java @@ -0,0 +1,134 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.entities; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import static org.nuiton.i18n.I18n.n; + +/** + * @author Tony Chemit - chemit@codelutin.com + * @since 1.7.2 + */ +public class People extends AbstractDemoBean { + + static { + n("jaxxdemo.common.people"); + n("jaxxdemo.common.firstName"); + n("jaxxdemo.common.lastName"); + n("jaxxdemo.common.age"); + } + + public static final String PROPERTY_FIRST_NAME = "firstName"; + + public static final String PROPERTY_LAST_NAME = "lastName"; + + public static final String PROPERTY_AGE = "age"; + + protected String firstName; + + protected String lastName; + + protected int age; + + private static final long serialVersionUID = 1L; + + public People() { + } + + public People(String id, + String firstName, + String lastName, + int age, + String image) { + super(id, image); + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + } + + public int getAge() { + return age; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public String getImage() { + return image; + } + + public void setAge(int age) { + int old = this.age; + this.age = age; + firePropertyChange(PROPERTY_AGE, old, age); + } + + public void setFirstName(String firstName) { + String old = this.firstName; + this.firstName = firstName; + firePropertyChange(PROPERTY_FIRST_NAME, old, firstName); + } + + public void setLastName(String lastName) { + String old = this.lastName; + this.lastName = lastName; + firePropertyChange(PROPERTY_LAST_NAME, old, lastName); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + People other = (People) obj; + return !(id == null ? other.id != null : !id.equals(other.id)); + } + + @Override + public int hashCode() { + int hash = 7; + hash = 97 * hash + (id != null ? id.hashCode() : 0); + return hash; + } + + @Override + public String toString() { + ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); + b.append(PROPERTY_ID, id); + b.append(PROPERTY_FIRST_NAME, firstName); + b.append(PROPERTY_LAST_NAME, lastName); + b.append(PROPERTY_IMAGE, image); + b.append(PROPERTY_AGE, age); + return b.toString(); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/databinding/BaseBeanDataBinding.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/databinding/BaseBeanDataBinding.jaxx new file mode 100644 index 0000000..bf9ff67 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/databinding/BaseBeanDataBinding.jaxx @@ -0,0 +1,48 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel> + + <!-- a full java bean property of the class --> + <Boolean id='editing' javaBean='false'/> + + <!-- not full java bean property (must add script...) --> + <Boolean id='editing2' constructorParams='false'/> + + <String id='contentMessage' javaBean='"message..."'/> + + <script> + void $afterCompleteSetup(){ + } + + public Boolean isEditing2() { + return editing2; + } + + public void setEditing2(Boolean editing2) { + Boolean oldValue = this.editing2; + this.editing2 = editing2; + firePropertyChange("editing2", oldValue, editing2); + } + </script> + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BeanDataBindingDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/databinding/BeanDataBindingDemo.jaxx similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BeanDataBindingDemo.jaxx rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/databinding/BeanDataBindingDemo.jaxx diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/databinding/BindingExtremeDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/databinding/BindingExtremeDemo.jaxx new file mode 100644 index 0000000..c74b404 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/databinding/BindingExtremeDemo.jaxx @@ -0,0 +1,290 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<org.nuiton.jaxx.demo.DemoPanel id='mainFrame' implements='DemoUIModel' + layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.runtime.JAXXBinding + org.nuiton.jaxx.runtime.FileChooserUtil + java.awt.Color + javax.swing.border.TitledBorder + javax.swing.DefaultListModel + javax.swing.SwingUtilities + </import> + <style> + JTextArea { editable:false; } + + JCheckBox { enabled:false; } + + .nobinding { background:{Color.GRAY}; } + </style> + + <script><![CDATA[ +public JToggleButton getT3() { return t0; } + +private void $afterCompleteSetup() { + for (Object o : $objectMap.values()) { + if (o instanceof JCheckBox) { + JCheckBox c = (JCheckBox) o; + c.setBackground($bindings.containsKey(c.getName() + ".selected") ? Color.WHITE : Color.RED); + } + } + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + DefaultListModel m = (DefaultListModel) bindings.getModel(); + for (JAXXBinding b : getDataBindings()) { + m.addElement(b.getId()); + } + } + }); +} +@Override +protected String[] getSources() { + return addDefaultSources( "DemoUIModel.java", "DefaultDemoUIModel.java" ); +} + ]]> + </script> + + <Boolean id='f0' javaBean='Boolean.FALSE'/> + <Boolean id='f1' javaBean='Boolean.FALSE'/> + <java.io.File id='file' javaBean='new java.io.File(".")'/> + + <DefaultDemoUIModel id='model0' initializer='new DefaultDemoUIModel()'/> + + <DemoUIModel id='model1' javaBean='new DefaultDemoUIModel()'/> + + + <Table fill="both" constraints='BorderLayout.CENTER'> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JCheckBox id='cf0' selected='{isF0()}' text='isF0()'/> + <JCheckBox id='cf1' selected='{isF1()}' text='isF1()'/> + <JCheckBox id='cf0O1' selected='{isF0() || isF1()}' + text='isF0() || isF1()'/> + <JCheckBox id='cf0A1' selected='{isF0() && isF1()}' + text='isF0() && isF1()'/> + </JPanel> + </cell> + </row> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JCheckBox id='ct0' selected='{t0.isSelected()}' + text='t0.isSelected()'/> + <JCheckBox id='ct1' selected='{t1.isSelected()}' + text='t1.isSelected()'/> + <JCheckBox id='ct0O1' selected='{t0.isSelected() || t1.isSelected()}' + text='t0.isSelected() || t1.isSelected()'/> + <JCheckBox id='ct0A1' + selected='{t0.isSelected() && t1.isSelected()}' + text='t0.isSelected() && t1.isSelected()'/> + </JPanel> + </cell> + </row> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JCheckBox id='cgett0' selected='{getT0().isSelected()}' + text='getT0().isSelected()'/> + <JCheckBox id='cgett1' selected='{getT1().isSelected()}' + text='getT1().isSelected()'/> + <JCheckBox id='cgett0O1' + selected='{getT0().isSelected() || getT1().isSelected()}' + text='getT0().isSelected() || getT1().isSelected()'/> + <JCheckBox id='cgett0A1' + selected='{getT0().isSelected() && getT1().isSelected()}' + text='getT0().isSelected() && getT1().isSelected()'/> + </JPanel> + </cell> + </row> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JTextArea id='cfile' + border='{new TitledBorder("file.getAbsolutePath()")}' + text='{file.getAbsolutePath()}' + visible='{!$bindings.containsKey("cfile.text")}' + styleClass="nobinding"/> + <JTextArea id='cgetfile' + border='{new TitledBorder("getFile().getAbsolutePath()")}' + text='{getFile().getAbsolutePath()}' + visible='{$bindings.containsKey("cgetfile.text")}'/> + </JPanel> + </cell> + </row> + <row weightx='1'> + <cell> + <JToggleButton id='t0' text='f0' onActionPerformed='setF0(!f0)'/> + </cell> + <cell> + <JToggleButton id='t1' text='f1' onActionPerformed='setF1(!f1)' + javaBean='new JToggleButton()'/> + </cell> + <cell> + <JButton text="file..." + onActionPerformed='setFile(FileChooserUtil.getFile(this, new String[0]))'/> + </cell> + </row> + + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JCheckBox id='cmt0' selected='{model0.isF0()}' text='model0.isF0()'/> + <JCheckBox id='cmt1' selected='{model0.isF1()}' text='model0.isF1()'/> + <JCheckBox id='cmt0O1' selected='{model0.isF0() || model0.isF1()}' + text='model0.isF0() || model0.isF1()'/> + <JCheckBox id='cmt0A1' + selected='{model0.isF0() && model0.isF1()}' + text='model0.isF0() && model0.isF1()'/> + </JPanel> + </cell> + </row> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JCheckBox id='cmgett0' selected='{getModel0().isF0()}' + text='getModel0().isF0()'/> + <JCheckBox id='cmgett1' selected='{getModel0().isF1()}' + text='getModel0().isF1()'/> + <JCheckBox id='cmgett0O1' + selected='{getModel0().isF0() || getModel0().isF1()}' + text='getModel0().isF0() || getModel0().isF1()'/> + <JCheckBox id='cmgett0A1' + selected='{getModel0().isF0() && getModel0().isF1()}' + text='getModel0().isF0() && getModel0().isF1()'/> + </JPanel> + </cell> + </row> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JTextArea id='cMfile' + border='{new TitledBorder("model0.getFile().getAbsolutePath()")}' + text='{model0.getFile().getAbsolutePath()}' + visible='{$bindings.containsKey("cMfile.text")}'/> + <JTextArea id='cMgetfile' + border='{new TitledBorder("getModel0().getFile().getAbsolutePath()")}' + text='{getModel0().getFile().getAbsolutePath()}' + visible='{$bindings.containsKey("cMgetfile.text")}'/> + </JPanel> + </cell> + </row> + <row> + <cell> + <JToggleButton id='Mt0' text='model0.f0' + onActionPerformed='model0.setF0(!model0.isF0())'/> + </cell> + <cell> + <JToggleButton id='Mt1' text='model0.f1' + onActionPerformed='model0.setF1(!model0.isF1())' + javaBean='new JToggleButton()'/> + </cell> + <cell> + <JButton text="model0.file..." + onActionPerformed='model0.setFile(FileChooserUtil.getFile(this,new String[0]))'/> + </cell> + </row> + + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JCheckBox id='cit0' selected='{((DemoUIModel)model1).isF0()}' + text='model1.isF0()'/> + <JCheckBox id='cit1' selected='{((DemoUIModel)model1).isF1()}' + text='model1.isF1()'/> + <JCheckBox id='cit0O1' + selected='{((DemoUIModel)model1).isF0() || ((DemoUIModel)model1).isF1()}' + text='model1.isF0() || model1.isF1()'/> + <JCheckBox id='cit0A1' + selected='{((DemoUIModel)model1).isF0() && ((DemoUIModel)model1).isF1()}' + text='model1.isF0() && model1.isF1()'/> + </JPanel> + </cell> + </row> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JCheckBox id='cigett0' selected='{getModel1().isF0()}' + text='getModel1().isF0()'/> + <JCheckBox id='cigett1' selected='{getModel1().isF1()}' + text='getModel1().isF1()'/> + <JCheckBox id='cigett0O1' + selected='{getModel1().isF0() || getModel1().isF1()}' + text='getModel1().isF0() || getModel1().isF1()'/> + <JCheckBox id='cigett0A1' + selected='{getModel1().isF0() && getModel1().isF1()}' + text='getModel1().isF0() && getModel1().isF1()'/> + </JPanel> + </cell> + </row> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JTextArea id='cIfile' + border='{new TitledBorder("model1.getFile().getAbsolutePath()")}' + text='{model1.getFile().getAbsolutePath()}' + visible='{$bindings.containsKey("cIfile.text")}'/> + <JTextArea id='cIgetfile' + border='{new TitledBorder("getModel1().getFile().getAbsolutePath()")}' + text='{getModel1().getFile().getAbsolutePath()}' + visible='{$bindings.containsKey("cIgetfile.text")}'/> + </JPanel> + </cell> + </row> + <row> + <cell> + <JToggleButton id='It0' text='model1.f0' + onActionPerformed='model1.setF0(!model1.isF0())'/> + </cell> + <cell> + <JToggleButton id='It1' text='model1.f1' + onActionPerformed='model1.setF1(!model1.isF1())' + javaBean='new JToggleButton()'/> + </cell> + <cell> + <JButton text="model1.file..." + onActionPerformed='model1.setFile(FileChooserUtil.getFile(this,new String[0]))'/> + </cell> + </row> + + <row weighty="1"> + <cell columns="3"> + <JPanel layout="{new BorderLayout()}"> + <JTextArea id="bindingsLabel" editable='false' + text='{$bindings.size() + " bindings."}'/> + <JScrollPane constraints='BorderLayout.CENTER' + columnHeaderView='{bindingsLabel}'> + <JList id="bindings" model='{new DefaultListModel()}' + font-size='10'/> + </JScrollPane> + </JPanel> + </cell> + </row> + </Table> + + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/databinding/DefaultDemoUIModel.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/databinding/DefaultDemoUIModel.java new file mode 100644 index 0000000..2fe4039 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/databinding/DefaultDemoUIModel.java @@ -0,0 +1,137 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.demo.feature.databinding; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.beans.AbstractSerializableBean; + +import javax.swing.JToggleButton; +import java.io.File; + +/** + * Created: 3 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + */ +public class DefaultDemoUIModel extends AbstractSerializableBean implements DemoUIModel { + + + private static final long serialVersionUID = 1L; + + protected File file; + + protected File file1; + + protected Boolean f1 = false; + + protected Boolean f0 = false; + + protected JToggleButton t1; + + protected JToggleButton t0; + + public static final String PROPERTY_T1 = "t1"; + + public static final String PROPERTY_F1 = "f1"; + + public static final String PROPERTY_F0 = "f0"; + + public static final String PROPERTY_FILE = "file"; + + protected static final Log log = LogFactory.getLog(DefaultDemoUIModel.class); + + /*---------------------------------------------------------------------------------*/ + /*-- public acessor methods -------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + public Boolean getF0() { + return f0; + } + + public Boolean getF1() { + return f1; + } + + @Override + public File getFile() { + return file; + } + + public File getFile1() { + return file1; + } + + @Override + public JToggleButton getT0() { + return t0; + } + + @Override + public JToggleButton getT1() { + return t1; + } + + @Override + public Boolean isF0() { + return f0 != null && f0; + } + + @Override + public Boolean isF1() { + return f1 != null && f1; + } + + /*---------------------------------------------------------------------------------*/ + /*-- public mutator methods -------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + @Override + public void setF0(Boolean newValue) { + Boolean oldValue = f0; + f0 = newValue; + firePropertyChange(PROPERTY_F0, oldValue, newValue); + } + + @Override + public void setF1(Boolean newValue) { + Boolean oldValue = f1; + f1 = newValue; + firePropertyChange(PROPERTY_F1, oldValue, newValue); + } + + @Override + public void setFile(File newValue) { + File oldValue = file; + file = newValue; + firePropertyChange(PROPERTY_FILE, oldValue, newValue); + } + + + public void setT1(JToggleButton newValue) { + JToggleButton oldValue = t1; + t1 = newValue; + firePropertyChange(PROPERTY_T1, oldValue, newValue); + } + +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/databinding/DemoUIModel.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/databinding/DemoUIModel.java new file mode 100644 index 0000000..123d059 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/databinding/DemoUIModel.java @@ -0,0 +1,96 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.demo.feature.databinding; + +import javax.swing.JToggleButton; +import java.beans.PropertyChangeListener; +import java.io.File; + +/** + * Created: 2 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + * + * Mise a jour: $Date$ par : + * $Author$ + */ +public interface DemoUIModel { + + Boolean isF0(); + + Boolean isF1(); + + void setF0(Boolean b); + + void setF1(Boolean b); + + JToggleButton getT0(); + + JToggleButton getT1(); + + File getFile(); + + void setFile(File newValue); + +// /** +// * All <code>JAXXObject</code> implements are capable of broadcasting <code>PropertyChangeEvent</code>, and +// * furthermore (for technical reasons) must allow code in outside packages, specifically the JAXX runtime, +// * to trigger these events. +// * +// * @param name the name of the property which changed +// * @param oldValue the old value of the property +// * @param newValue the new value of the property +// */ +// void firePropertyChange(String name, Object oldValue, Object newValue); + + /** + * Register a general {@link PropertyChangeListener}. + * + * @param listener the listener to register + */ + void addPropertyChangeListener(PropertyChangeListener listener); + + /** + * Register a {@link PropertyChangeListener}. for the given {@code propertyName}. + * + * @param property the property name to listen + * @param listener the listener to register + */ + void addPropertyChangeListener(String property, PropertyChangeListener listener); + + /** + * Unregister a general {@link PropertyChangeListener}. + * + * @param listener the listener to unregister + */ + void removePropertyChangeListener(PropertyChangeListener listener); + + /** + * Unregister a {@link PropertyChangeListener}. for the given {@code propertyName}. + * + * @param property the property name to listen + * @param listener the listener to unregister + */ + void removePropertyChangeListener(String property, PropertyChangeListener listener); + +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/NavDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/NavDemo.jaxx new file mode 100644 index 0000000..c296805 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/NavDemo.jaxx @@ -0,0 +1,98 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.jaxx.demo.feature.nav.tree.NavDemoTreeHelper + org.nuiton.jaxx.demo.feature.nav.treetable.NavDemoTreeTableHelper + org.jdesktop.swingx.JXTreeTable + org.nuiton.jaxx.demo.entities.DemoDataProvider + </import> + + <CardLayout2 id='contentLayout'/> + + <DemoDataProvider id='dataProvider'/> + + <NavDemoTreeHelper id='treeHelper' constructorParams='getDataProvider()'/> + + <NavDemoTreeTableHelper id='treeTableHelper' + constructorParams='getDataProvider()'/> + + <script><![CDATA[ + +@Override +protected String[] getSources() { + return addDefaultSources( + "tree/NavDemoTreeNode.java", + "tree/NavDemoTreeHelper.java", + "tree/NavDemoTreeCellRenderer.java", + "tree/ActorsTreeNodeLoador.java", + "tree/MoviesTreeNodeLoador.java", + "treetable/NavDemoTreeTableNode.java", + "treetable/NavDemoTreeTableHelper.java", + "treetable/ActorsTreeTableNodeLoador.java", + "treetable/MoviesTreeTableNodeLoador.java" + ); +} + ]]> + </script> + + <JSplitPane id='splitPane' + constraints='BorderLayout.CENTER' + oneTouchExpandable='true'> + + <JTabbedPane> + <tab title='jaxxdemo.tree.tabtitle'> + <JScrollPane border='{null}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_NEVER}'> + + <JTree id="navigationTree" + font-size='11' + rootVisible='false' + showsRootHandles='false' + model='{treeHelper.createModel()}'/> + + </JScrollPane> + </tab> + <tab title='jaxxdemo.treeTable.tabtitle'> + <JScrollPane border='{null}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_NEVER}'> + + <JXTreeTable id="navigationTreeTable" + font-size='11' + rootVisible='false' + showsRootHandles='false' + columnControlVisible='true' + treeTableModel='{treeTableHelper.createModel()}'/> + + </JScrollPane> + </tab> + </JTabbedPane> + + <JPanel id="content" layout="{contentLayout}"/> + + </JSplitPane> + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/NavDemoHandler.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/NavDemoHandler.java new file mode 100644 index 0000000..d9c86b5 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/NavDemoHandler.java @@ -0,0 +1,298 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.demo.feature.nav; + +import org.nuiton.jaxx.runtime.JAXXContext; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.swing.CardLayout2; +import org.nuiton.jaxx.runtime.swing.ErrorDialogUI; +import org.nuiton.jaxx.runtime.swing.nav.NavNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTreeTable; +import org.nuiton.decorator.DecoratorProvider; +import org.nuiton.decorator.JXPathDecorator; +import org.nuiton.jaxx.demo.entities.AbstractDemoBean; +import org.nuiton.jaxx.demo.entities.DemoDataProvider; +import org.nuiton.jaxx.demo.entities.Movie; +import org.nuiton.jaxx.demo.entities.People; +import org.nuiton.jaxx.demo.feature.nav.content.AbstractContentUI; +import org.nuiton.jaxx.demo.feature.nav.content.ActorContentUI; +import org.nuiton.jaxx.demo.feature.nav.content.ActorsContentUI; +import org.nuiton.jaxx.demo.feature.nav.content.MovieContentUI; +import org.nuiton.jaxx.demo.feature.nav.content.MoviesContentUI; +import org.nuiton.jaxx.demo.feature.nav.tree.NavDemoTreeCellRenderer; +import org.nuiton.jaxx.demo.feature.nav.tree.NavDemoTreeNode; +import org.nuiton.jaxx.demo.feature.nav.treetable.NavDemoTreeTableNode; + +import javax.swing.ImageIcon; +import javax.swing.JPanel; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.TreePath; +import java.awt.Component; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.List; + +import static org.nuiton.i18n.I18n.n; + +/** + * Handler of all uis in the Nave demo. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.2 + */ +public class NavDemoHandler implements UIHandler<NavDemo> { + + private static final Log log = LogFactory.getLog(NavDemoHandler.class); + + protected NavDemo ui; + + public static String MOVIES_CATEGORY_NODE = n("jaxxdemo.common.movies"); + + public static String ACTORS_CATEGORY_NODE = n("jaxxdemo.common.actors"); + + @Override + public void beforeInit(NavDemo ui) { + this.ui = ui; + } + + @Override + public void afterInit(final NavDemo ui) { + // share in context + + ui.setContextValue(this); + ui.setContextValue(ui.getTreeHelper(), "treeHelper"); + ui.setContextValue(ui.getTreeTableHelper(), "treeTableHelper"); + + // Creation of selection listener to open ui when tree selection change + TreeSelectionListener treeSelectionListener = new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent event) { + TreePath path = event.getPath(); + NavDemoTreeNode demoNode = + (NavDemoTreeNode) path.getLastPathComponent(); + + if (log.isDebugEnabled()) { + log.debug("Select demoNode " + demoNode); + } + + // Do nothing for root + if (demoNode.isRoot()) { + return; + } + openUI(demoNode); + } + }; + + // Creation of selection listener to open ui when tree selection change + TreeSelectionListener treeTableSelectionListener = new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent event) { + TreePath path = event.getPath(); + NavDemoTreeTableNode demoNode = + (NavDemoTreeTableNode) path.getLastPathComponent(); + + if (log.isDebugEnabled()) { + log.debug("Select demoNode " + demoNode); + } + + // Do nothing for root + if (demoNode.isRoot()) { + return; + } + openUI(demoNode); + } + }; + + final JTree tree = ui.getNavigationTree(); + JXTreeTable table = ui.getNavigationTreeTable(); + + // Attach renderer + NavDemoTreeCellRenderer renderer = new NavDemoTreeCellRenderer( + ui.getContextValue(DecoratorProvider.class), + ui.getDataProvider() + ); + tree.setCellRenderer(renderer); + + // Register tree + ui.getTreeHelper().setUI(tree, true, treeSelectionListener); + + // Register tree table + ui.getTreeTableHelper().setUI(table, true, treeTableSelectionListener); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + tree.setSelectionInterval(0, 0); + ui.getSplitPane().resetToPreferredSizes(); + } + }); + + // expand the tree + SwingUtil.expandTree(tree); + SwingUtil.expandTreeTable(table); + + // auto-expand demoNode when selected + SwingUtil.addExpandOnClickListener(tree); + SwingUtil.addExpandOnClickListener(table); + } + + public void initUI(MoviesContentUI contentUI) { + DecoratorProvider provider = + contentUI.getContextValue(DecoratorProvider.class); + JXPathDecorator<Movie> decorator = + (JXPathDecorator<Movie>) provider.getDecoratorByType(Movie.class); + contentUI.getListHeader().init(decorator, new ArrayList<Movie>()); + } + + public void initUI(ActorsContentUI contentUI) { + DecoratorProvider provider = + contentUI.getContextValue(DecoratorProvider.class); + JXPathDecorator<People> decorator = + (JXPathDecorator<People>) provider.getDecoratorByType(People.class); + contentUI.getListHeader().init(decorator, new ArrayList<People>()); + } + + public void selectChild(AbstractContentUI<?> contentUI, + AbstractDemoBean selected) { + contentUI.getTreeHelper().selectNode(selected.getId()); + contentUI.getTreeTableHelper().selectNode(selected.getId()); + } + + public String getContent(AbstractDemoBean data) { + if (data == null) { + return "no content"; + } + StringBuilder buffer = new StringBuilder(); + buffer.append(data); + return buffer.toString(); + } + + public ImageIcon getImage(AbstractDemoBean data) { + return data == null ? null : SwingUtil.createIcon(data.getImage()); + } + + protected void openUI(NavNode<?, ?> demoNode) { + + // Get demoNode type + Class<?> editType = demoNode.getInternalClass(); + String id = demoNode.getId(); + + // If it's category demoNode + DemoDataProvider provider = ui.getDataProvider(); + if (editType.equals(String.class)) { + + // Actors categorie demoNode + if (ACTORS_CATEGORY_NODE.equals(id)) { + + List<People> peoples = provider.getPeoples(); + showUI(peoples, ActorsContentUI.class); + + // Movies categorie demoNode + } else if (MOVIES_CATEGORY_NODE.equals(id)) { + + List<Movie> movies = provider.getMovies(); + showUI(movies, MoviesContentUI.class); + } + + // People demoNode + } else if (editType.equals(People.class)) { + People people = provider.getPeople(id); + showUI(people, ActorContentUI.class); + + // Movie demoNode + } else if (editType.equals(Movie.class)) { + Movie movie = provider.getMovie(id); + showUI(movie, MovieContentUI.class); + } + } + + // Create by introspection content ui + + protected <B> void showUI(B bean, + Class<? extends AbstractContentUI<B>> uiClass) { + + // Verify if instance is existing + AbstractContentUI<B> ui = getContentIfExist(uiClass); + + // Get layout identifier + String contentName = uiClass.getName(); + + JPanel content = this.ui.getContent(); + if (ui == null) { + try { + // Get constructor + Constructor<? extends AbstractContentUI<B>> constructor = + uiClass.getConstructor(JAXXContext.class); + + // Invoke instance creation + ui = constructor.newInstance(this.ui); + } catch (Exception eee) { + log.error("Could not create ui of type " + uiClass, eee); + ErrorDialogUI.showError(eee); + return; + } + + // Add to content panel + content.add(ui, contentName); + } + + // Attach bean + ui.setData(bean); + + // show ui + this.ui.getContentLayout().show(content, contentName); + + // revalidate container + SwingUtilities.invokeLater(revalidateContent); + + } + + // Get content if exist in content, else return null + + protected <E extends Component> E getContentIfExist(Class<E> uiClass) { + String contentName = uiClass.getName(); + if (log.isDebugEnabled()) { + log.debug("Get content if exist " + contentName); + } + CardLayout2 layout2 = ui.getContentLayout(); + if (!layout2.contains(contentName)) { + return null; + } + return (E) layout2.getComponent(ui.getContent(), contentName); + } + + private final Runnable revalidateContent = new Runnable() { + + @Override + public void run() { + ui.revalidate(); + } + }; + +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/AbstractContentUI.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/AbstractContentUI.jaxx new file mode 100644 index 0000000..7a2f4fe --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/AbstractContentUI.jaxx @@ -0,0 +1,46 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JPanel abstract='true' layout='{new BorderLayout()}' genericType='B'> + + <import> + org.nuiton.jaxx.demo.feature.nav.NavDemoHandler + org.nuiton.jaxx.demo.feature.nav.tree.NavDemoTreeHelper + org.nuiton.jaxx.demo.feature.nav.treetable.NavDemoTreeTableHelper + </import> + + <NavDemoTreeHelper id='treeHelper' + initializer='getContextValue(NavDemoTreeHelper.class,"treeHelper")'/> + + <NavDemoTreeTableHelper id='treeTableHelper' + initializer='getContextValue(NavDemoTreeTableHelper.class,"treeTableHelper")'/> + + <NavDemoHandler id='handler' + initializer='getContextValue(NavDemoHandler.class)'/> + <script><![CDATA[ + +public abstract B getData(); + +public abstract void setData(B data); + ]]> + </script> +</JPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/ActorContentUI.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/ActorContentUI.jaxx new file mode 100644 index 0000000..ada70cb --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/ActorContentUI.jaxx @@ -0,0 +1,56 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<AbstractContentUI superGenericType='People'> + + <import> + org.nuiton.jaxx.demo.entities.People + static org.nuiton.i18n.I18n.t + </import> + + <People id='data' javaBean='null'/> + + <JSplitPane id='splitPane' orientation='{JSplitPane.VERTICAL_SPLIT}' + resizeWeight='0.5' constraints='BorderLayout.CENTER' + oneTouchExpandable='true'> + + <JScrollPane border='{null}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> + + <JTextPane editable='false' font-size='11' + border='{new TitledBorder(t("jaxxdemo.navigation.actor.title"))}' + text='{getHandler().getContent(getData())}'/> + </JScrollPane> + + <JScrollPane border='{new TitledBorder("Picture")}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}' + minimumSize='{SwingUtil.newMinDimension()}'> + + <JLabel horizontalAlignment='center' + icon='{getHandler().getImage(getData())}'/> + + </JScrollPane> + + </JSplitPane> +</AbstractContentUI> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/ActorsContentUI.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/ActorsContentUI.jaxx new file mode 100644 index 0000000..3d101b5 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/ActorsContentUI.jaxx @@ -0,0 +1,81 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<AbstractContentUI superGenericType='List<People>'> + + <import> + java.util.List + org.nuiton.jaxx.demo.entities.People + org.nuiton.jaxx.runtime.swing.editor.bean.BeanListHeader + org.nuiton.jaxx.runtime.swing.renderer.DecoratorProviderListCellRenderer + + static org.nuiton.i18n.I18n.t + </import> + + <java.util.List id='data' genericType='People' javaBean='null'/> + + <script><![CDATA[ +private void $afterCompleteSetup() { + getHandler().initUI(this); +} + ]]></script> + + <JPanel layout='{new BorderLayout()}'> + + <JScrollPane + border='{new TitledBorder(t("jaxxdemo.navigation.actors.title"))}' + constraints='BorderLayout.CENTER' + columnHeaderView='{toolbar}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> + + <!-- list of actors --> + <JList id='list' + cellRenderer='{getContextValue(DecoratorProviderListCellRenderer.class)}'/> + + <!-- list header --> + <JToolBar id='toolbar' floatable='false' layout='{new BorderLayout()}'> + <JPanel layout='{new GridLayout(1,0)}' + constraints='BorderLayout.CENTER'> + + <!-- to show the selected actor --> + <JButton text='jaxxdemo.action.show' + enabled='{list.getSelectedIndex()!=-1}' + onActionPerformed='getHandler().selectChild(this, (People) list.getSelectedValue())'/> + + <!-- to show a new actor --> + <JButton text='jaxxdemo.action.add'/> + + <!-- to delete the selected actor --> + <JButton text='jaxxdemo.action.remove' + enabled='{list.getSelectedIndex()!=-1}'/> + </JPanel> + + <BeanListHeader id='listHeader' constraints='BorderLayout.EAST' + i18nPrefix='jaxxdemo.common.' genericType='People' + data='{getData()}' list='{list}' showReset='true'/> + </JToolBar> + + </JScrollPane> + + </JPanel> +</AbstractContentUI> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/MovieContentUI.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/MovieContentUI.jaxx new file mode 100644 index 0000000..978b68c --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/MovieContentUI.jaxx @@ -0,0 +1,57 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<AbstractContentUI superGenericType='Movie'> + + <import> + org.nuiton.jaxx.demo.entities.Movie + static org.nuiton.i18n.I18n.t + </import> + + <Movie id='data' javaBean='null'/> + + <JSplitPane id='splitPane' orientation='{JSplitPane.VERTICAL_SPLIT}' + resizeWeight='0.5' constraints='BorderLayout.CENTER' + oneTouchExpandable='true'> + + <JScrollPane border='{null}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> + + <JTextPane + border='{new TitledBorder(t("jaxxdemo.navigation.movie.title"))}' + editable='false' font-size='11' + text='{getHandler().getContent(getData())}'/> + </JScrollPane> + + <JScrollPane border='{new TitledBorder("Picture")}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}' + minimumSize='{SwingUtil.newMinDimension()}'> + + <JLabel horizontalAlignment='center' + icon='{getHandler().getImage(getData())}'/> + + </JScrollPane> + + </JSplitPane> +</AbstractContentUI> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/MoviesContentUI.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/MoviesContentUI.jaxx new file mode 100644 index 0000000..5bb0f04 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/content/MoviesContentUI.jaxx @@ -0,0 +1,81 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<AbstractContentUI superGenericType='List<Movie>'> + + <import> + java.util.List + org.nuiton.jaxx.demo.entities.Movie + org.nuiton.jaxx.runtime.swing.editor.bean.BeanListHeader + org.nuiton.jaxx.runtime.swing.renderer.DecoratorProviderListCellRenderer + + static org.nuiton.i18n.I18n.t + </import> + <script><![CDATA[ + +private void $afterCompleteSetup() { + getHandler().initUI(this); +} + ]]></script> + + <java.util.List id='data' genericType='Movie' javaBean='null'/> + + <JPanel layout='{new BorderLayout()}'> + + <JScrollPane + border='{new TitledBorder(t("jaxxdemo.navigation.movies.title"))}' + constraints='BorderLayout.CENTER' + columnHeaderView='{toolbar}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> + + <!-- list of movies --> + <JList id='list' + cellRenderer='{getContextValue(DecoratorProviderListCellRenderer.class)}'/> + + <!-- list header --> + <JToolBar id='toolbar' floatable='false' layout='{new BorderLayout()}'> + <JPanel layout='{new GridLayout(1,0)}' + constraints='BorderLayout.CENTER'> + + <!-- to show the selected actor --> + <JButton text='jaxxdemo.action.show' + enabled='{list.getSelectedIndex()!=-1}' + onActionPerformed='getHandler().selectChild(this, (Movie) list.getSelectedValue())'/> + + <!-- to show a new actor --> + <JButton text='jaxxdemo.action.add'/> + + <!-- to delete the selected actor --> + <JButton text='jaxxdemo.action.remove' + enabled='{list.getSelectedIndex()!=-1}'/> + </JPanel> + + <BeanListHeader id='listHeader' constraints='BorderLayout.EAST' + i18nPrefix='jaxxdemo.common.' + data='{getData()}' genericType='Movie' + list='{list}' showReset='true'/> + </JToolBar> + </JScrollPane> + + </JPanel> +</AbstractContentUI> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/ActorsTreeNodeLoador.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/ActorsTreeNodeLoador.java new file mode 100644 index 0000000..78aae84 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/ActorsTreeNodeLoador.java @@ -0,0 +1,78 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.feature.nav.tree; + +import org.nuiton.jaxx.runtime.swing.nav.NavDataProvider; +import org.nuiton.jaxx.runtime.swing.nav.tree.NavTreeNodeChildLoador; +import org.nuiton.jaxx.demo.entities.DemoDataProvider; +import org.nuiton.jaxx.demo.entities.People; + +import java.util.List; + +/** + * @author Sylvain Lletellier + * @since 2.1 + */ +public class ActorsTreeNodeLoador extends NavTreeNodeChildLoador<People, People, NavDemoTreeNode> { + + private static final long serialVersionUID = 1L; + + public ActorsTreeNodeLoador() { + super(People.class); + } + + @Override + public List<People> getData(Class<?> parentClass, + String moviesId, + NavDataProvider dataProvider) throws Exception { + + // Get people for parentId + DemoDataProvider provider = (DemoDataProvider) dataProvider; + + // If its not root + if (moviesId != null) { + + // Return peoples for movies id + return provider.getPeoples(moviesId); + } + + // Return all peoples + return provider.getPeoples(); + } + + @Override + public NavDemoTreeNode createNode(People data, NavDataProvider dataProvider) { + + NavDemoTreeNode actorNode; + + // Create actor static nodes + actorNode = new NavDemoTreeNode( + getBeanType(), + data.getId(), + null, + null + ); + + return actorNode; + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/MoviesTreeNodeLoador.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/MoviesTreeNodeLoador.java new file mode 100644 index 0000000..928910a --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/MoviesTreeNodeLoador.java @@ -0,0 +1,93 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.feature.nav.tree; + +import org.nuiton.jaxx.runtime.swing.nav.NavDataProvider; +import org.nuiton.jaxx.runtime.swing.nav.NavHelper; +import org.nuiton.jaxx.runtime.swing.nav.tree.NavTreeNodeChildLoador; +import org.nuiton.jaxx.demo.entities.DemoDataProvider; +import org.nuiton.jaxx.demo.entities.Movie; +import org.nuiton.jaxx.demo.feature.nav.NavDemoHandler; + +import java.util.List; + +import static org.nuiton.i18n.I18n.n; + +/** + * @author Sylvain Lletellier + * @since 2.1 + */ +public class MoviesTreeNodeLoador extends NavTreeNodeChildLoador<Movie, Movie, NavDemoTreeNode> { + + private static final long serialVersionUID = 1L; + + protected boolean isTreeTable; + + public MoviesTreeNodeLoador() { + this(false); + } + + public MoviesTreeNodeLoador(boolean isTreeTable) { + super(Movie.class); + this.isTreeTable = isTreeTable; + } + + @Override + public List<Movie> getData(Class<?> parentClass, + String parentId, + NavDataProvider dataProvider) throws Exception { + + DemoDataProvider provider = (DemoDataProvider) dataProvider; + + // Return all movies + return provider.getMovies(); + } + + @Override + public NavDemoTreeNode createNode(Movie data, NavDataProvider dataProvider) { + + NavDemoTreeNode moviesNode; + NavDemoTreeNode actorsCategoryNode; + + // Create movies static nodes + moviesNode = new NavDemoTreeNode( + getBeanType(), + data.getId(), + null, + null + ); + + // Create clients category node + actorsCategoryNode = new NavDemoTreeNode( + String.class, + n(NavDemoHandler.ACTORS_CATEGORY_NODE), + null, + NavHelper.getChildLoador(ActorsTreeNodeLoador.class) + ); + + // Add actors nodes to movies node + moviesNode.add(actorsCategoryNode); + + return moviesNode; + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/NavDemoTreeCellRenderer.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/NavDemoTreeCellRenderer.java new file mode 100644 index 0000000..b474434 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/NavDemoTreeCellRenderer.java @@ -0,0 +1,115 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.feature.nav.tree; + +import org.nuiton.jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.decorator.Decorator; +import org.nuiton.decorator.DecoratorProvider; +import org.nuiton.jaxx.demo.entities.DemoDataProvider; +import org.nuiton.jaxx.demo.entities.Movie; +import org.nuiton.jaxx.demo.entities.People; + +import javax.swing.JTree; +import javax.swing.tree.DefaultTreeModel; +import java.awt.Component; + +/** + * @author Sylvain Lletellier + * @since 2.1 + */ +public class NavDemoTreeCellRenderer extends AbstractNavTreeCellRenderer<DefaultTreeModel, NavDemoTreeNode> { + + /** Logger */ + protected static final Log log = + LogFactory.getLog(NavDemoTreeCellRenderer.class); + + protected DecoratorProvider decoratorProvider; + + public NavDemoTreeCellRenderer(DecoratorProvider decoratorProvider, + DemoDataProvider provider) { + setDataProvider(provider); + this.decoratorProvider = decoratorProvider; + } + + @Override + public DemoDataProvider getDataProvider() { + return (DemoDataProvider) super.getDataProvider(); + } + + @Override + protected String computeNodeText(NavDemoTreeNode node) { + + // Get node type + Class<?> editType = node.getInternalClass(); + String id = node.getId(); + + // get decorator + Decorator<?> decorator = decoratorProvider.getDecoratorByType(editType); + + Object toDecorate = null; + + // People node + if (editType.equals(People.class)) { + toDecorate = getDataProvider().getPeople(id); + + // Movie node + } else if (editType.equals(Movie.class)) { + toDecorate = getDataProvider().getMovie(id); + } + + // Get decorated value + String decorated = decorator.toString(toDecorate); + + if (log.isDebugEnabled()) { + log.debug("Compute text for node " + + node + " return " + + decorated); + } + + return decorated; + } + + @Override + public Component getTreeCellRendererComponent(JTree tree, + Object value, + boolean sel, + boolean expanded, + boolean leaf, int row, + boolean hasFocus) { + + if (!(value instanceof NavDemoTreeNode)) { + return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + } + + // get node + NavDemoTreeNode node = (NavDemoTreeNode) value; + + // get text for node + String text = getNodeText(node); + + // Render node + return super.getTreeCellRendererComponent(tree, text, sel, expanded, leaf, row, hasFocus); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/NavDemoTreeHelper.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/NavDemoTreeHelper.java new file mode 100644 index 0000000..9f7530c --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/NavDemoTreeHelper.java @@ -0,0 +1,85 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.feature.nav.tree; + +import org.nuiton.jaxx.runtime.swing.nav.tree.NavTreeHelper; +import org.nuiton.jaxx.demo.entities.DemoDataProvider; +import org.nuiton.jaxx.demo.feature.nav.NavDemoHandler; + +import javax.swing.tree.DefaultTreeModel; + +/** + * @author Sylvain Lletellier + * @since 2.1 + */ +public class NavDemoTreeHelper extends NavTreeHelper<NavDemoTreeNode> { + + public NavDemoTreeHelper(DemoDataProvider provider) { + setDataProvider(provider); + } + + @Override + public DemoDataProvider getDataProvider() { + return (DemoDataProvider) super.getDataProvider(); + } + + public DefaultTreeModel createModel() { + + // Create root static node + NavDemoTreeNode root = new NavDemoTreeNode( + String.class, + "Root node", + null, + null + ); + + // Create movies category node + NavDemoTreeNode moviesCategoryNode = new NavDemoTreeNode( + String.class, + NavDemoHandler.MOVIES_CATEGORY_NODE, + null, + getChildLoador(MoviesTreeNodeLoador.class) + ); + + // Create peoples category node + NavDemoTreeNode peoplesCategoryNode = new NavDemoTreeNode( + String.class, + NavDemoHandler.ACTORS_CATEGORY_NODE, + null, + getChildLoador(ActorsTreeNodeLoador.class) + ); + + // Add to root + root.add(moviesCategoryNode); + root.add(peoplesCategoryNode); + + // Create model + DefaultTreeModel model = createModel(root); + + // Populate childs nodes + root.populateChilds(getBridge(), getDataProvider()); + + return model; + } + +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/NavDemoTreeNode.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/NavDemoTreeNode.java new file mode 100644 index 0000000..55e123b --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/tree/NavDemoTreeNode.java @@ -0,0 +1,46 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.feature.nav.tree; + +import org.nuiton.jaxx.runtime.swing.nav.tree.NavTreeNode; +import org.nuiton.jaxx.runtime.swing.nav.tree.NavTreeNodeChildLoador; + +/** + * @author Sylvain Lletellier + * @since 2.1 + */ +public class NavDemoTreeNode extends NavTreeNode<NavDemoTreeNode> { + + private static final long serialVersionUID = 1L; + + public NavDemoTreeNode(String id) { + super(id); + } + + public NavDemoTreeNode(Class<?> internalClass, + String id, + String context, + NavTreeNodeChildLoador<?, ?, NavDemoTreeNode> loador) { + super(internalClass, id, context, loador); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/ActorsTreeTableNodeLoador.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/ActorsTreeTableNodeLoador.java new file mode 100644 index 0000000..d0bae12 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/ActorsTreeTableNodeLoador.java @@ -0,0 +1,79 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.feature.nav.treetable; + +import org.nuiton.jaxx.runtime.swing.nav.NavDataProvider; +import org.nuiton.jaxx.runtime.swing.nav.treetable.NavTreeTableNodeChildLoador; +import org.nuiton.jaxx.demo.entities.DemoDataProvider; +import org.nuiton.jaxx.demo.entities.People; + +import java.util.List; + +/** + * @author Sylvain Lletellier + * @since 2.1 + */ +public class ActorsTreeTableNodeLoador extends NavTreeTableNodeChildLoador<People, People, NavDemoTreeTableNode> { + + private static final long serialVersionUID = 1L; + + public ActorsTreeTableNodeLoador() { + super(People.class); + } + + @Override + public List<People> getData(Class<?> parentClass, + String moviesId, + NavDataProvider dataProvider) throws Exception { + + // Get people for parentId + DemoDataProvider provider = (DemoDataProvider) dataProvider; + + // If its not root + if (moviesId != null) { + + // Return peoples for movies id + return provider.getPeoples(moviesId); + } + + // Return all peoples + return provider.getPeoples(); + } + + @Override + public NavDemoTreeTableNode createNode(People data, NavDataProvider dataProvider) { + + NavDemoTreeTableNode actorNode; + + // Create actor static nodes + + actorNode = new NavDemoTreeTableNode( + getBeanType(), + data.getId(), + null, + null + ); + + return actorNode; + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/MoviesTreeTableNodeLoador.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/MoviesTreeTableNodeLoador.java new file mode 100644 index 0000000..68c660c --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/MoviesTreeTableNodeLoador.java @@ -0,0 +1,94 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.feature.nav.treetable; + +import org.nuiton.jaxx.runtime.swing.nav.NavDataProvider; +import org.nuiton.jaxx.runtime.swing.nav.NavHelper; +import org.nuiton.jaxx.runtime.swing.nav.treetable.NavTreeTableNodeChildLoador; +import org.nuiton.jaxx.demo.entities.DemoDataProvider; +import org.nuiton.jaxx.demo.entities.Movie; +import org.nuiton.jaxx.demo.feature.nav.NavDemoHandler; + +import java.util.List; + +import static org.nuiton.i18n.I18n.n; + +/** + * @author Sylvain Lletellier + * @since 2.1 + */ +public class MoviesTreeTableNodeLoador extends NavTreeTableNodeChildLoador<Movie, Movie, NavDemoTreeTableNode> { + + private static final long serialVersionUID = 1L; + + protected boolean isTreeTable; + + public MoviesTreeTableNodeLoador() { + this(false); + } + + public MoviesTreeTableNodeLoador(boolean isTreeTable) { + super(Movie.class); + this.isTreeTable = isTreeTable; + } + + @Override + public List<Movie> getData(Class<?> parentClass, + String parentId, + NavDataProvider dataProvider) throws Exception { + + DemoDataProvider provider = (DemoDataProvider) dataProvider; + + // Return all movies + return provider.getMovies(); + } + + @Override + public NavDemoTreeTableNode createNode(Movie data, + NavDataProvider dataProvider) { + + NavDemoTreeTableNode moviesNode; + NavDemoTreeTableNode actorsCategoryNode; + + // Create movies static nodes + moviesNode = new NavDemoTreeTableNode( + getBeanType(), + data.getId(), + null, + null + ); + + // Create clients category node + actorsCategoryNode = new NavDemoTreeTableNode( + String.class, + n(NavDemoHandler.ACTORS_CATEGORY_NODE), + null, + NavHelper.getChildLoador(ActorsTreeTableNodeLoador.class) + ); + + // Add actors nodes to movies node + moviesNode.add(actorsCategoryNode); + + return moviesNode; + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/NavDemoTreeTableHelper.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/NavDemoTreeTableHelper.java new file mode 100644 index 0000000..d4ea20d --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/NavDemoTreeTableHelper.java @@ -0,0 +1,85 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.feature.nav.treetable; + +import org.nuiton.jaxx.runtime.swing.nav.treetable.NavTreeTableHelper; +import org.nuiton.jaxx.runtime.swing.nav.treetable.NavTreeTableModel; +import org.nuiton.jaxx.demo.entities.DemoDataProvider; +import org.nuiton.jaxx.demo.feature.nav.NavDemoHandler; + +/** + * @author Sylvain Lletellier + * @since 2.1 + */ +public class NavDemoTreeTableHelper extends NavTreeTableHelper<NavDemoTreeTableNode> { + + public NavDemoTreeTableHelper(DemoDataProvider provider) { + setDataProvider(provider); + } + + @Override + public DemoDataProvider getDataProvider() { + return (DemoDataProvider) super.getDataProvider(); + } + + + public NavTreeTableModel createModel() { + + // Create root static node + NavDemoTreeTableNode root = new NavDemoTreeTableNode( + String.class, + "Root node", + null, + null + ); + + // Create movies category node + NavDemoTreeTableNode moviesCategoryNode = new NavDemoTreeTableNode( + String.class, + NavDemoHandler.MOVIES_CATEGORY_NODE, + null, + getChildLoador(MoviesTreeTableNodeLoador.class) + ); + + // Create peoples category node + NavDemoTreeTableNode peoplesCategoryNode = new NavDemoTreeTableNode( + String.class, + NavDemoHandler.ACTORS_CATEGORY_NODE, + null, + getChildLoador(ActorsTreeTableNodeLoador.class) + ); + + // Add to root + root.add(moviesCategoryNode); + root.add(peoplesCategoryNode); + + // Create model + NavDemoTreeTableModel delegate = new NavDemoTreeTableModel(getDataProvider()); + NavTreeTableModel model = createModel(root, delegate); + + // Populate childs nodes + root.populateChilds(getBridge(), getDataProvider()); + + return model; + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/NavDemoTreeTableModel.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/NavDemoTreeTableModel.java new file mode 100644 index 0000000..f507018 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/NavDemoTreeTableModel.java @@ -0,0 +1,116 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.demo.feature.nav.treetable; + +import org.nuiton.jaxx.runtime.swing.nav.NavNode; +import org.nuiton.jaxx.runtime.swing.nav.treetable.NavTreeTableModel; +import org.nuiton.jaxx.demo.entities.DemoDataProvider; +import org.nuiton.jaxx.demo.entities.Movie; +import org.nuiton.jaxx.demo.entities.People; + +import static org.nuiton.i18n.I18n.t; + +/** + * @author Sylvain Lletellier + * @since 2.1 + */ +public class NavDemoTreeTableModel extends NavTreeTableModel.MyDefaultTreeTableModel { + + protected DemoDataProvider dataProvider; + + public NavDemoTreeTableModel(DemoDataProvider dataProvider) { + this.dataProvider = dataProvider; + } + + @Override + public Object getValueAt(Object o, int i) { + NavNode node = (NavNode) o; + + // Get node type + Class<?> editType = node.getInternalClass(); + String id = node.getId(); + + // If it's category node + if (node.isStringNode()) { + if (i == 0) { + return t(id); + } + return ""; + + // People node + } else if (editType.equals(People.class)) { + People people = dataProvider.getPeople(id); + return getPeopleColumn(people, i); + + // Movie node + } else if (editType.equals(Movie.class)) { + Movie movie = dataProvider.getMovie(id); + return getMovieColumn(movie, i); + } + + // This never append + return "not found"; + } + + private String getMovieColumn(Movie movie, int i) { + String result = ""; + + switch (i) { + case 0: + result = movie.getTitle(); + break; + case 2: + result = String.valueOf(movie.getYear()); + break; + } + return result; + } + + protected String getPeopleColumn(People people, int i) { + String result = ""; + + switch (i) { + case 0: + result = people.getFirstName(); + break; + case 1: + result = people.getLastName(); + break; + case 2: + result = String.valueOf(people.getAge()); + break; + } + return result; + } + + @Override + public String[] getColumnsNames() { + return new String[]{t("jaxxdemo.common.firstName"), + t("jaxxdemo.common.lastName"), + t("jaxxdemo.common.age")}; + } + + @Override + public boolean isCellEditable(Object node, int column) { + return false; + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/NavDemoTreeTableNode.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/NavDemoTreeTableNode.java new file mode 100644 index 0000000..c7bf9cd --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/nav/treetable/NavDemoTreeTableNode.java @@ -0,0 +1,44 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.demo.feature.nav.treetable; + +import org.nuiton.jaxx.runtime.swing.nav.treetable.NavTreeTableNode; +import org.nuiton.jaxx.runtime.swing.nav.treetable.NavTreeTableNodeChildLoador; + +/** + * @author Sylvain Lletellier + * @since 2.1 + */ +public class NavDemoTreeTableNode extends NavTreeTableNode<NavDemoTreeTableNode> { + private static final long serialVersionUID = 1L; + + protected NavDemoTreeTableNode(String id) { + super(id); + } + + public NavDemoTreeTableNode(Class<?> internalClass, + String id, + String context, + NavTreeTableNodeChildLoador<?, ?, NavDemoTreeTableNode> childLoador) { + super(internalClass, id, context, childLoador); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/list/ListBeanValidationDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/list/ListBeanValidationDemo.jaxx new file mode 100644 index 0000000..f15bb25 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/list/ListBeanValidationDemo.jaxx @@ -0,0 +1,103 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.jdesktop.swingx.JXTable + javax.swing.JOptionPane + static org.nuiton.i18n.I18n.n + org.nuiton.jaxx.demo.entities.People + org.nuiton.validator.bean.list.BeanListValidator + org.nuiton.jaxx.validator.swing.SwingListValidatorMessageTableModel + + java.io.File + </import> + + <script><![CDATA[ +@Override +protected String[] getSources() { + return addDefaultSources( + "ListBeanValidationDemo.css", + "/org.nuiton.jaxx.demo.entities.People.java", + "/org.nuiton.jaxx.demo.entities.People-error-validation.xml", + "/org.nuiton.jaxx.demo.entities.People-info-validation.xml", + "/org.nuiton.jaxx.demo.entities.People-warning-validation.xml", + "ListBeanValidationDemoHandler.java", + "PeopleTableModel.java" + ); +} +]]></script> + + <!-- model --> + <PeopleTableModel id='model'/> + + <!-- validator --> + <BeanListValidator id='validator' genericType='People' + initializer='BeanListValidator.newValidator(People.class, null)'/> + + <!-- errors model --> + <SwingListValidatorMessageTableModel id='errorTableModel' + onTableChanged='handler.updateOkEnabled()'/> + + <Table fill='both' constraints='BorderLayout.CENTER'> + <row> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Form")}' + layout='{new GridLayout()}' width='250' height='120'> + <JScrollPane id='dataTableScrollePane' constraints='BorderLayout.CENTER'> + <JXTable id='dataTable' model='{model}' autoCreateRowSorter='true'/> + </JScrollPane> + </JPanel> + </cell> + </row> + <row> + <cell fill="both"> + <JPanel layout='{new GridLayout(1,3,0,0)}'> + <JButton id='addIdentity' text='jaxx.demo.action.add' + onActionPerformed='handler.addPeople()'/> + <JButton id='removeIdentity' text='jaxx.demo.action.remove' + onActionPerformed='handler.removePeople()'/> + <JButton id='ok' text='jaxx.demo.action.ok' + onActionPerformed='JOptionPane.showMessageDialog(this, ok.getText() + " clicked!", "onActionPerformed", JOptionPane.INFORMATION_MESSAGE);'/> + + </JPanel> + </cell> + </row> + <row> + <cell fill="both"> + <JPanel border='{BorderFactory.createTitledBorder("Messages")}' + layout='{new GridLayout()}' height='200' + width='500'> + <JScrollPane columnHeaderView='{errorTable.getTableHeader()}'> + <JTable id='errorTable' model='{errorTableModel}' + rowSelectionAllowed='true' + autoCreateRowSorter='true' + autoResizeMode='2' cellSelectionEnabled='false' + selectionMode='0'/> + </JScrollPane> + </JPanel> + </cell> + </row> + </Table> + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/validation/list/ListBeanValidationDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/list/ListBeanValidationDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/feature/validation/list/ListBeanValidationDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/list/ListBeanValidationDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/list/ListBeanValidationDemoHandler.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/list/ListBeanValidationDemoHandler.java new file mode 100644 index 0000000..5f5fc5f --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/list/ListBeanValidationDemoHandler.java @@ -0,0 +1,187 @@ +package org.nuiton.jaxx.demo.feature.validation.list; +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.apache.commons.lang3.tuple.Pair; +import org.jdesktop.swingx.JXTable; +import org.nuiton.decorator.Decorator; +import org.nuiton.jaxx.demo.entities.DemoDecoratorProvider; +import org.nuiton.jaxx.demo.entities.People; +import org.nuiton.jaxx.validator.swing.SwingListValidatorDataLocator; +import org.nuiton.jaxx.validator.swing.SwingListValidatorMessageTableRenderer; +import org.nuiton.jaxx.validator.swing.SwingValidatorUtil; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.list.BeanListValidator; + +import javax.swing.JTable; +import javax.swing.RowSorter; +import javax.swing.SortOrder; +import javax.swing.table.TableModel; +import java.util.Arrays; +import java.util.UUID; + +import static org.nuiton.i18n.I18n.n; + +/** + * Handler of UI {@link ListBeanValidationDemo}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.3 + */ +public class ListBeanValidationDemoHandler implements UIHandler<ListBeanValidationDemo> { + + private ListBeanValidationDemo ui; + + @Override + public void beforeInit(ListBeanValidationDemo ui) { + this.ui = ui; + } + + @Override + public void afterInit(ListBeanValidationDemo ui) { + + // customize data table + + JXTable dataTable = ui.getDataTable(); + + dataTable.getRowSorter().setSortKeys( + Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); + SwingUtil.setI18nTableHeaderRenderer( + dataTable, + n("jaxx.demo.label.id"), + n("jaxx.demo.label.id.tip"), + n("jaxx.demo.label.firstName"), + n("jaxx.demo.label.firstName.tip"), + n("jaxx.demo.label.lastName"), + n("jaxx.demo.label.lastName.tip"), + n("jaxx.demo.label.age"), + n("jaxx.demo.label.age.tip")); + + SwingUtil.fixTableColumnWidth(dataTable, 3, 35); + + // register validator + BeanListValidator<People> validator = ui.getValidator(); + + // customize error table + + JTable errorTable = ui.getErrorTable(); + + PeopleValidatorDataLocator dataLocator = new PeopleValidatorDataLocator(); + + SwingValidatorUtil.installUI(errorTable, + new SwingListValidatorMessageTableRenderer() { + + private static final long serialVersionUID = 1L; + + Decorator<People> decorator + = new DemoDecoratorProvider().getDecoratorByType(People.class); + + @Override + protected String decorateBean(Object bean) { + return decorator.toString(bean); + } + }); + + SwingValidatorUtil.registerListValidator( + validator, + ui.getErrorTableModel(), + dataTable, + errorTable, + dataLocator); + + SwingValidatorUtil.addHightLighterOnEditor( + validator, dataTable, dataLocator, + NuitonValidatorScope.ERROR, + NuitonValidatorScope.WARNING); + + // add some datas in model + + People a = new People("0", "Jack", "Black", 12, "/org/nuiton/jaxx/demo/images/jack.jpg"); + People a2 = new People("1", "Héctor", "Jiménez", 28, "/org/nuiton/jaxx/demo/images/hector.jpg"); + People a3 = new People("2", "Ana", "de la Reguera", 34, "/org/nuiton/jaxx/demo/images/ana.jpg"); + + addPeople(a); + addPeople(a2); + addPeople(a3); + } + + public void addPeople() { + People bean = new People(); + bean.setId(UUID.randomUUID().toString()); + addPeople(bean); + } + + + public void addPeople(People bean) { + PeopleTableModel model = ui.getModel(); + model.addBean(bean); + } + + public void removePeople() { + int selectedRow = ui.getDataTable().getSelectedRow(); + PeopleTableModel model = ui.getModel(); + model.removeBean(selectedRow); + } + + public void updateOkEnabled() { + BeanListValidator<People> validator = ui.getValidator(); + boolean valid = !validator.hasErrors(); + ui.getOk().setEnabled(valid); + } + + private static class PeopleValidatorDataLocator implements SwingListValidatorDataLocator<People> { + + @Override + public boolean acceptType(Class<?> beanType) { + return People.class.isAssignableFrom(beanType); + } + + @Override + public Pair<Integer, Integer> locateDataCell(TableModel tableModel, + People bean, + String fieldName) { + PeopleTableModel model = (PeopleTableModel) tableModel; + + Pair<Integer, Integer> cell = + model.getCell(bean, fieldName); + return cell; + } + + @Override + public int locateBeanRowIndex(TableModel tableModel, People bean) { + PeopleTableModel model = (PeopleTableModel) tableModel; + return model.getBeanIndex(bean); + } + + @Override + public People locateBean(TableModel tableModel, int rowIndex) { + PeopleTableModel model = + (PeopleTableModel) tableModel; + return model.getBean(rowIndex); + } + } + +} + + diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/list/PeopleTableModel.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/list/PeopleTableModel.java new file mode 100644 index 0000000..423d688 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/list/PeopleTableModel.java @@ -0,0 +1,150 @@ +package org.nuiton.jaxx.demo.feature.validation.list; +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.Lists; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.apache.commons.lang3.tuple.Pair; +import org.nuiton.jaxx.demo.entities.Identity; +import org.nuiton.jaxx.demo.entities.People; + +import javax.swing.table.AbstractTableModel; +import java.util.Arrays; +import java.util.List; + +/** + * Table model of {@link Identity}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.3 + */ +public class PeopleTableModel extends AbstractTableModel { + + private static final long serialVersionUID = 1L; + + public static final List<String> columnNames = + Arrays.asList(People.PROPERTY_ID, + People.PROPERTY_FIRST_NAME, + People.PROPERTY_LAST_NAME, + People.PROPERTY_AGE); + + public static final Class<?>[] columnClasses = + {String.class, String.class, Integer.class}; + + private final List<People> data = Lists.newArrayList(); + + @Override + public int getRowCount() { + return data.size(); + } + + @Override + public String getColumnName(int column) { + SwingUtil.ensureColumnIndex(this, column); + return columnNames.get(column); + } + + @Override + public int getColumnCount() { + return columnNames.size(); + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return columnIndex > 0; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + + SwingUtil.ensureColumnIndex(this, columnIndex); + SwingUtil.ensureRowIndex(this, rowIndex); + + People row = data.get(rowIndex); + if (columnIndex == 0) { + return row.getId(); + } + if (columnIndex == 1) { + return row.getFirstName(); + } + if (columnIndex == 2) { + return row.getLastName(); + } + if (columnIndex == 3) { + return row.getAge(); + } + + // should never come here + return null; + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + SwingUtil.ensureColumnIndex(this, columnIndex); + SwingUtil.ensureRowIndex(this, rowIndex); + + People row = data.get(rowIndex); + + if (columnIndex == 0) { + row.setId(String.valueOf(aValue)); + } else if (columnIndex == 1) { + row.setFirstName(String.valueOf(aValue)); + } else if (columnIndex == 2) { + row.setLastName(String.valueOf(aValue)); + } else if (columnIndex == 3) { + row.setAge(Integer.valueOf(aValue.toString())); + } + } + + + public int getBeanIndex(People bean) { + int row = data.indexOf(bean); + return row; + } + + public People getBean(int row) { + SwingUtil.ensureRowIndex(this, row); + People bean = data.get(row); + return bean; + } + + public Pair<Integer, Integer> getCell(People bean, String fieldName) { + + int row = getBeanIndex(bean); + int col = columnNames.indexOf(fieldName); + + Pair<Integer, Integer> cell = Pair.of(row, col); + return cell; + } + + public void removeBean(int selectedRow) { + SwingUtil.ensureRowIndex(this, selectedRow); + data.remove(selectedRow); + fireTableRowsDeleted(selectedRow, selectedRow); + } + + public void addBean(People bean) { + data.add(bean); + int newrowIndex = data.size() - 1; + fireTableRowsInserted(newrowIndex, newrowIndex); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/simple/SimpleBeanValidationByListDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/simple/SimpleBeanValidationByListDemo.jaxx new file mode 100644 index 0000000..379166a --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/simple/SimpleBeanValidationByListDemo.jaxx @@ -0,0 +1,372 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + <style source="Validation.jcss"/> + + <import> + javax.swing.JOptionPane + static org.nuiton.i18n.I18n.n + org.nuiton.jaxx.demo.entities.Identity + org.nuiton.jaxx.demo.entities.Model + org.nuiton.jaxx.validator.swing.SwingValidatorMessageListRenderer + org.nuiton.jaxx.validator.swing.SwingValidatorMessageListModel + + java.io.File + </import> + + <script><![CDATA[ +@Override +protected String[] getSources() { + return addDefaultSources( + "Validation.css", + "/org.nuiton.jaxx.demo.entities.Identity.java", + "/org.nuiton.jaxx.demo.entities.Identity-error-validation.xml", + "/org.nuiton.jaxx.demo.entities.Identity-info-validation.xml", + "/org.nuiton.jaxx.demo.entities.Identity-warning-validation.xml", + "/org.nuiton.jaxx.demo.entities.Model.java", + "/org.nuiton.jaxx.demo.entities.Model-error-validation.xml", + "/org.nuiton.jaxx.demo.entities.Model-info-validation.xml", + "/org.nuiton.jaxx.demo.entities.Model-warning-validation.xml" + ); +} +]]> + </script> + <!-- models --> + <Model id='model1'/> + <Model id='model2'/> + <Identity id='identity'/> + + <!-- errors model --> + <SwingValidatorMessageListModel id='errorListModel' + onContentsChanged='ok.setEnabled(errorListModel.isEmpty())'/> + + <!-- validators --> + <BeanValidator id='validator' bean='model1' + uiClass="org.nuiton.jaxx.validator.swing.ui.ImageValidationUI"> + <field name="text"/> + <field name="text2"/> + <field name="ratio"/> + </BeanValidator> + <BeanValidator id='validator2' bean='model2' + uiClass="org.nuiton.jaxx.validator.swing.ui.IconValidationUI"> + <field name="text" component="_text"/> + <field name="text2" component="_text2"/> + <field name="ratio" component="_ratio"/> + </BeanValidator> + <BeanValidator id='validator3' autoField='true' bean='identity' + uiClass="org.nuiton.jaxx.validator.swing.ui.TranslucentValidationUI"> + <field name="email" component="email2"/> + </BeanValidator> + + <Table fill='both' constraints='BorderLayout.CENTER'> + <row> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Form")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JTextField id='text' text='{model1.getText()}' + _validatorLabel='{n("form.text")}' + onKeyReleased='model1.setText(text.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JTextField id='text2' text='{model1.getText2()}' + _validatorLabel='{n("form.text2")}' + onKeyReleased='model1.setText2(text2.getText())'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JSlider id='ratio' minimum='0' maximum='100' + value='{model1.getRatio()}' + _validatorLabel='{n("form.ratio")}' + onStateChanged='model1.setRatio(ratio.getValue())'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Model")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model1.getText()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model1.getText2()}'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JLabel text='{model1.getRatio()+""}'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + </row> + <row> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Form2")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JTextField id='_text' text='{model2.getText()}' + _validatorLabel='{n("form2.text")}' + onKeyReleased='model2.setText(_text.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JTextField id='_text2' text='{model2.getText2()}' + _validatorLabel='{n("form2.text2")}' + onKeyReleased='model2.setText2(_text2.getText())'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JSlider id='_ratio' minimum='0' maximum='100' + value='{model2.getRatio()}' + _validatorLabel='{n("form2.ratio")}' + onStateChanged='model2.setRatio(_ratio.getValue())'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Model2")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model2.getText()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model2.getText2()}'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JLabel text='{model2.getRatio()+""}'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + </row> + <row> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Identify Form")}' + layout='{new GridLayout()}' width='250' height='180'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='FirstName:'/> + </cell> + <cell weightx='1'> + <JTextField id='firstName' text='{identity.getFirstName()}' + onKeyReleased='identity.setFirstName(firstName.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='LastName:'/> + </cell> + <cell weightx='1'> + <JTextField id='lastName' text='{identity.getLastName()}' + onKeyReleased='identity.setLastName(lastName.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Email:'/> + </cell> + <cell weightx='1'> + <JTextField id='email2' text='{identity.getEmail()}' + onKeyReleased='identity.setEmail(email2.getText())'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Age:'/> + </cell> + <cell> + <JSlider id='age' minimum='0' maximum='100' + value='{identity.getAge()}' + onStateChanged='identity.setAge(age.getValue())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Config file :'/> + </cell> + <cell> + <JTextField id='config' text='{identity.getConfig()+""}' + onKeyReleased='identity.setConfig(new File(config.getText()))'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Working directory:'/> + </cell> + <cell> + <JTextField id='dir' text='{identity.getDir()+""}' + onKeyReleased='identity.setDir(new File(dir.getText()))'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Identity Model")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='FirstName:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getFirstName()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='LastName:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getLastName()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Email:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getEmail()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Age:'/> + </cell> + <cell> + <JLabel text='{identity.getAge()+""}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Config file:'/> + </cell> + <cell> + <JLabel text='{identity.getConfig()+""}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Directory file:'/> + </cell> + <cell> + <JLabel text='{identity.getDir()+""}'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + </row> + <row> + <cell columns='2' fill="both"> + <JPanel border='{BorderFactory.createTitledBorder("Messages")}' + layout='{new GridLayout()}' height='200' + width='500'> + <JScrollPane> + <JList id='errorList' model='{errorListModel}' + cellRenderer='{new SwingValidatorMessageListRenderer()}'/> + </JScrollPane> + </JPanel> + </cell> + </row> + <row> + <cell columns='2' fill="both"> + <JPanel layout='{new GridLayout(1,2,0,0)}'> + <JButton id='cancel' text='cancel' + onActionPerformed='JOptionPane.showMessageDialog(this, cancel.getText() + " clicked!", "onActionPerformed", JOptionPane.INFORMATION_MESSAGE);'/> + <JButton id='ok' text='valid' + onActionPerformed='JOptionPane.showMessageDialog(this, ok.getText() + " clicked!", "onActionPerformed", JOptionPane.INFORMATION_MESSAGE);'/> + </JPanel> + </cell> + </row> + </Table> + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/simple/SimpleBeanValidationByTableDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/simple/SimpleBeanValidationByTableDemo.jaxx new file mode 100644 index 0000000..5d085ad --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/simple/SimpleBeanValidationByTableDemo.jaxx @@ -0,0 +1,381 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + <style source="Validation.jcss"/> + + <import> + javax.swing.JOptionPane + static org.nuiton.i18n.I18n.n + org.nuiton.jaxx.demo.entities.Identity + org.nuiton.jaxx.demo.entities.Model + org.nuiton.jaxx.validator.swing.SwingValidatorUtil + org.nuiton.jaxx.validator.swing.SwingValidatorMessageTableRenderer + org.nuiton.jaxx.validator.swing.SwingValidatorMessageTableModel + + java.io.File + </import> + + <script><![CDATA[ +void $afterCompleteSetup() { + SwingValidatorUtil.installUI(errorTable, new SwingValidatorMessageTableRenderer()); +} + +@Override +protected String[] getSources() { + return addDefaultSources ( + "Validation.css", + "/org.nuiton.jaxx.demo.entities.Identity.java", + "/org.nuiton.jaxx.demo.entities.Identity-error-validation.xml", + "/org.nuiton.jaxx.demo.entities.Identity-info-validation.xml", + "/org.nuiton.jaxx.demo.entities.Identity-warning-validation.xml", + "/org.nuiton.jaxx.demo.entities.Model.java", + "/org.nuiton.jaxx.demo.entities.Model-error-validation.xml", + "/org.nuiton.jaxx.demo.entities.Model-info-validation.xml", + "/org.nuiton.jaxx.demo.entities.Model-warning-validation.xml" + ); +} +]]></script> + + <!-- models --> + <Model id='model1'/> + <Model id='model2'/> + <Identity id='identity'/> + + <!-- errors model --> + <SwingValidatorMessageTableModel id='errorTableModel' + onTableChanged='ok.setEnabled(errorTableModel.getRowCount()==0)'/> + + <!-- validators --> + <BeanValidator id='validator' bean='model1' + uiClass="org.nuiton.jaxx.validator.swing.ui.ImageValidationUI"> + <field name="text"/> + <field name="text2"/> + <field name="ratio"/> + </BeanValidator> + <BeanValidator id='validator2' bean='model2' + uiClass="org.nuiton.jaxx.validator.swing.ui.IconValidationUI"> + <field name="text" component="_text"/> + <field name="text2" component="_text2"/> + <field name="ratio" component="_ratio"/> + </BeanValidator> + <BeanValidator id='validator3' autoField='true' bean='identity' + uiClass="org.nuiton.jaxx.validator.swing.ui.TranslucentValidationUI"> + <field name="email" component="email2"/> + </BeanValidator> + + <Table fill='both' constraints='BorderLayout.CENTER'> + <row> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Form")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JTextField id='text' text='{model1.getText()}' + onKeyReleased='model1.setText(text.getText())' + _validatorLabel='{n("form.text")}' + /> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JTextField id='text2' text='{model1.getText2()}' + onKeyReleased='model1.setText2(text2.getText())' + _validatorLabel='{n("form.text2")}' + /> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JSlider id='ratio' minimum='0' maximum='100' + value='{model1.getRatio()}' + _validatorLabel='{n("form.ratio")}' + onStateChanged='model1.setRatio(ratio.getValue())'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Model")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model1.getText()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model1.getText2()}'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JLabel text='{model1.getRatio()+""}'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + </row> + <row> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Form2")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JTextField id='_text' text='{model2.getText()}' + _validatorLabel='{n("form2.text")}' + onKeyReleased='model2.setText(_text.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JTextField id='_text2' text='{model2.getText2()}' + _validatorLabel='{n("form2.text2")}' + onKeyReleased='model2.setText2(_text2.getText())'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JSlider id='_ratio' minimum='0' maximum='100' + value='{model2.getRatio()}' + _validatorLabel='{n("form2.ratio")}' + onStateChanged='model2.setRatio(_ratio.getValue())'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Model2")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model2.getText()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model2.getText2()}'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JLabel text='{model2.getRatio()+""}'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + </row> + <row> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Identify Form")}' + layout='{new GridLayout()}' width='250' height='180'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='FirstName:'/> + </cell> + <cell weightx='1'> + <JTextField id='firstName' text='{identity.getFirstName()}' + onKeyReleased='identity.setFirstName(firstName.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='LastName:'/> + </cell> + <cell weightx='1'> + <JTextField id='lastName' text='{identity.getLastName()}' + onKeyReleased='identity.setLastName(lastName.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Email:'/> + </cell> + <cell weightx='1'> + <JTextField id='email2' text='{identity.getEmail()}' + onKeyReleased='identity.setEmail(email2.getText())'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Age:'/> + </cell> + <cell> + <JSlider id='age' minimum='0' maximum='100' + value='{identity.getAge()}' + onStateChanged='identity.setAge(age.getValue())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Config file :'/> + </cell> + <cell> + <JTextField id='config' text='{identity.getConfig()+""}' + onKeyReleased='identity.setConfig(new File(config.getText()))'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Working directory:'/> + </cell> + <cell> + <JTextField id='dir' text='{identity.getDir()+""}' + onKeyReleased='identity.setDir(new File(dir.getText()))'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Identity Model")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='FirstName:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getFirstName()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='LastName:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getLastName()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Email:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getEmail()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Age:'/> + </cell> + <cell> + <JLabel text='{identity.getAge()+""}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Config file:'/> + </cell> + <cell> + <JLabel text='{identity.getConfig()+""}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Directory file:'/> + </cell> + <cell> + <JLabel text='{identity.getDir()+""}'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + </row> + <row> + <cell columns='2' fill="both"> + <JPanel border='{BorderFactory.createTitledBorder("Messages")}' + layout='{new GridLayout()}' height='200' + width='500'> + <JScrollPane columnHeaderView='{errorTable.getTableHeader()}'> + <JTable id='errorTable' model='{errorTableModel}' rowSelectionAllowed='true' + autoCreateRowSorter='true' + autoResizeMode='2' cellSelectionEnabled='false' + selectionMode='0'/> + </JScrollPane> + </JPanel> + </cell> + </row> + <row> + <cell columns='2' fill="both"> + <JPanel layout='{new GridLayout(1,2,0,0)}'> + <JButton id='cancel' text='cancel' + onActionPerformed='JOptionPane.showMessageDialog(this, cancel.getText() + " clicked!", "onActionPerformed", JOptionPane.INFORMATION_MESSAGE);'/> + <JButton id='ok' text='valid' + onActionPerformed='JOptionPane.showMessageDialog(this, ok.getText() + " clicked!", "onActionPerformed", JOptionPane.INFORMATION_MESSAGE);'/> + </JPanel> + </cell> + </row> + </Table> + +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/feature/validation/simple/Validation.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/simple/Validation.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/feature/validation/simple/Validation.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/feature/validation/simple/Validation.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/CalculatorDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/CalculatorDemo.jaxx new file mode 100644 index 0000000..ed26806 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/CalculatorDemo.jaxx @@ -0,0 +1,143 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + java.awt.Color + javax.swing.BorderFactory + javax.swing.border.BevelBorder + </import> + + <!--<style source='CalculatorDemo.jcss'/>--> + <script><![CDATA[ + plus.setText("+"); + sign.setText("+/-"); + +@Override +protected String[] getSources() { + return addDefaultSources( "CalculatorEngine.java" ); +} +]]> + </script> + <!-- use fully-qualified name just in case this is compiled into a different package --> + <CalculatorEngine id='engine'/> + + <Table fill='both'> + <row> + <cell columns='4'> + <JLabel id='display' text='{engine.getDisplayText()}'/> + </cell> + </row> + + <row> + <cell columns='2'> + <JButton id='c' text='C' onActionPerformed='engine.clear()' + styleClass='clear'/> + </cell> + <cell> + <JButton id='ce' text='CE' onActionPerformed='engine.clearEntry()' + styleClass='clear'/> + </cell> + <cell> + <JButton id='equals' text='=' onActionPerformed='engine.equal()' + styleClass='operator'/> + </cell> + </row> + + <row> + <cell> + <JButton id='d7' text='7' onActionPerformed='engine.digit(7)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='d8' text='8' onActionPerformed='engine.digit(8)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='d9' text='9' onActionPerformed='engine.digit(9)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='plus' onActionPerformed='engine.add()' + styleClass='operator'/> + </cell> + </row> + + <row> + <cell> + <JButton id='d4' text='4' onActionPerformed='engine.digit(4)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='d5' text='5' onActionPerformed='engine.digit(5)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='d6' text='6' onActionPerformed='engine.digit(6)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='subtract' text='-' onActionPerformed='engine.subtract()' + styleClass='operator'/> + </cell> + </row> + + <row> + <cell> + <JButton id='d1' text='1' onActionPerformed='engine.digit(1)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='d2' text='2' onActionPerformed='engine.digit(2)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='d3' text='3' onActionPerformed='engine.digit(3)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='multiply' text='x' onActionPerformed='engine.multiply()' + styleClass='operator'/> + </cell> + </row> + + <row> + <cell> + <JButton id='d0' text='0' onActionPerformed='engine.digit(0)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='sign' onActionPerformed='engine.toggleSign()' + styleClass='operator'/> + </cell> + <cell> + <JButton id='dot' text='.' onActionPerformed='engine.dot()' + styleClass='digit'/> + </cell> + <cell> + <JButton id='divide' text='÷' onActionPerformed='engine.divide()' + styleClass='operator'/> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/CalculatorDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/CalculatorDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/CalculatorEngine.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/CalculatorEngine.java new file mode 100644 index 0000000..cc903a6 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/CalculatorEngine.java @@ -0,0 +1,208 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.fun; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.math.BigDecimal; + +public class CalculatorEngine { + public static final String DISPLAY_TEXT_PROPERTY = "displayText"; + + public static final int ADD = 0; + + public static final int SUBTRACT = 1; + + public static final int MULTIPLY = 2; + + public static final int DIVIDE = 3; + + public static final int RESULT = 4; + + private int operation = -1; + + private boolean clear = true; // true to clear on next key + + private String displayText = "0"; + + private BigDecimal value; + + private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); + + + public String getDisplayText() { + return displayText; + } + + + public void setDisplayText(String displayText) { + String oldDisplayText = this.displayText; + this.displayText = displayText; + firePropertyChange(DISPLAY_TEXT_PROPERTY, oldDisplayText, displayText); + } + + + public void clear() { + clearEntry(); + value = new BigDecimal(0); + operation = -1; + } + + + public void clearEntry() { + setDisplayText("0"); + clear = true; + } + + + private void checkClear() { + if (clear) { + setDisplayText(""); + clear = false; + } + } + + + public void digit(int digit) { + checkClear(); + setDisplayText(getDisplayText() + String.valueOf(digit)); + } + + + public void dot() { + checkClear(); + if (getDisplayText().indexOf('.') == -1) { + if (getDisplayText().length() == 0) { + setDisplayText("0."); + } else { + setDisplayText(getDisplayText() + '.'); + } + } + } + + + public void toggleSign() { + String text = getDisplayText(); + if (text.startsWith("-")) { + text = text.substring(1); + } else if (!text.equals("0")) { + text = '-' + text; + } + setDisplayText(text); + } + + + public void equal() { + BigDecimal displayValue = new BigDecimal(getDisplayText()); + BigDecimal newValue = displayValue; + switch (operation) { + case ADD: + newValue = value.add(displayValue); + break; + case SUBTRACT: + newValue = value.subtract(displayValue); + break; + case MULTIPLY: + newValue = value.multiply(displayValue); + break; + case DIVIDE: + newValue = value.divide(displayValue, 8, BigDecimal.ROUND_HALF_UP); + break; + } + value = newValue; + setDisplayText(toString(newValue)); + clear = true; + operation = -1; + } + + + public static String toString(BigDecimal decimal) { + // can't use stripTrailingZeros, as it wasn't introduced until 1.5 + String result = decimal.toString(); + if (result.indexOf("") != -1) { + while (result.endsWith("0")) { + result = result.substring(0, result.length() - 1); + } + if (result.endsWith("")) { + result = result.substring(0, result.length() - 1); + } + } + return result; + } + + + public void operation(int operation) { + if (this.operation != -1) { + equal(); + } else { + value = new BigDecimal(getDisplayText()); + clear = true; + } + this.operation = operation; + } + + + public void add() { + operation(ADD); + } + + + public void subtract() { + operation(SUBTRACT); + } + + + public void multiply() { + operation(MULTIPLY); + } + + + public void divide() { + operation(DIVIDE); + } + + + public void addPropertyChangeListener(PropertyChangeListener listener) { + propertyChangeSupport.addPropertyChangeListener(listener); + } + + + public void addPropertyChangeListener(String property, PropertyChangeListener listener) { + propertyChangeSupport.addPropertyChangeListener(property, listener); + } + + + public void removePropertyChangeListener(PropertyChangeListener listener) { + propertyChangeSupport.removePropertyChangeListener(listener); + } + + + public void removePropertyChangeListener(String property, PropertyChangeListener listener) { + propertyChangeSupport.removePropertyChangeListener(property, listener); + } + + + protected void firePropertyChange(String property, Object oldValue, Object newValue) { + propertyChangeSupport.firePropertyChange(property, oldValue, newValue); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/CounterDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/CounterDemo.jaxx new file mode 100644 index 0000000..b45a97f --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/CounterDemo.jaxx @@ -0,0 +1,31 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel> + <script>int count;</script> + <JTextField text='{count+""}' constraints='BorderLayout.NORTH'/> + <HBox constraints='BorderLayout.SOUTH'> + <JButton text='Dec (-)' onActionPerformed='count--'/> + <JButton text='Reset' onActionPerformed='count = 0'/> + <JButton text='Inc (+)' onActionPerformed='count++'/> + </HBox> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/LabelStyleDemo.jaxx b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/LabelStyleDemo.jaxx new file mode 100644 index 0000000..57d9f7f --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/LabelStyleDemo.jaxx @@ -0,0 +1,121 @@ +<!-- + #%L + JAXX :: Demo + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<org.nuiton.jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + java.awt.Color + javax.swing.BorderFactory + </import> + + <Table id='demoPanel' anchor='north' fill='both'> + <row> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JTextField id='text' text='Data Binding'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Red:'/> + </cell> + <cell> + <JSlider id='red' value='128' maximum='255' styleClass='color'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Green:'/> + </cell> + <cell> + <JSlider id='green' value='0' maximum='255' styleClass='color'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Blue:'/> + </cell> + <cell> + <JSlider id='blue' value='255' maximum='255' styleClass='color'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Size:'/> + </cell> + <cell> + <JSlider id='dummySize' value='36' minimum='6' maximum='60'/> + </cell> + </row> + + <row> + <cell columns='2' fill='both' weighty='1'> + <JPanel border='{BorderFactory.createTitledBorder("Preview")}' + height='90' + layout='{new BorderLayout()}'> + <VBox + background='{(Color)( backgroundCheckbox.isSelected() ? backgroundColor.getSelectedValue() : null)}' + margin='0' + horizontalAlignment='center' + verticalAlignment='middle'> + <JLabel text='{text.getText()}' + font-size='{dummySize.getValue()}' + foreground='{new Color(red.getValue(), green.getValue(), blue.getValue())}'/> + </VBox> + </JPanel> + </cell> + </row> + </Table> + </cell> + + <cell> + <VBox spacing='0' + border='{BorderFactory.createTitledBorder("Background")}'> + <JCheckBox id='backgroundCheckbox' text='Show Background'/> + <JRadioButton text='Red' buttonGroup='backgroundColor' + value='{Color.RED}' selected='true'/> + <JRadioButton text='Orange' buttonGroup='backgroundColor' + value='{Color.ORANGE}'/> + <JRadioButton text='Yellow' buttonGroup='backgroundColor' + value='{Color.YELLOW}'/> + <JRadioButton text='Green' buttonGroup='backgroundColor' + value='{Color.GREEN}'/> + <JRadioButton text='Cyan' buttonGroup='backgroundColor' + value='{Color.CYAN}'/> + <JRadioButton text='Blue' buttonGroup='backgroundColor' + value='{Color.BLUE}'/> + <JRadioButton text='Purple' buttonGroup='backgroundColor' + value='{new Color(160, 30, 255)}'/> + </VBox> + </cell> + </row> + </Table> +</org.nuiton.jaxx.demo.DemoPanel> diff --git a/jaxx-demo/src/main/java/jaxx/demo/fun/LabelStyleDemo.jcss b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/LabelStyleDemo.jcss similarity index 100% rename from jaxx-demo/src/main/java/jaxx/demo/fun/LabelStyleDemo.jcss rename to jaxx-demo/src/main/java/org/nuiton/jaxx/demo/fun/LabelStyleDemo.jcss diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoCellRenderer.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoCellRenderer.java new file mode 100644 index 0000000..a388b2c --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoCellRenderer.java @@ -0,0 +1,106 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.tree; + +import org.nuiton.jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JTree; +import javax.swing.tree.DefaultTreeModel; +import java.awt.Component; + +import static org.nuiton.i18n.I18n.t; + +/** + * @author Sylvain Lletellier + * @since 2.1 + */ +public class DemoCellRenderer extends AbstractNavTreeCellRenderer<DefaultTreeModel, DemoNode> { + + /** Logger */ + protected static final Log log = + LogFactory.getLog(DemoCellRenderer.class); + + + public DemoCellRenderer(org.nuiton.jaxx.demo.tree.DemoDataProvider provider) { + setDataProvider(provider); + } + + @Override + public org.nuiton.jaxx.demo.entities.DemoDataProvider getDataProvider() { + return (org.nuiton.jaxx.demo.entities.DemoDataProvider) super.getDataProvider(); + } + + @Override + protected String computeNodeText(DemoNode node) { + + if (node == null) { + return ""; + } + + + String toDecorate; + + String id = node.getId(); + + if (node.isStringNode()) { + + // String node + toDecorate = t(id); + } else { + + // Demo node + toDecorate = id; + } + + if (log.isDebugEnabled()) { + log.debug("Compute text for node " + node + + " (" + node.getInternalClass() + ") = " + toDecorate); + } + + return toDecorate; + } + + @Override + public Component getTreeCellRendererComponent(JTree tree, + Object value, + boolean sel, + boolean expanded, + boolean leaf, int row, + boolean hasFocus) { + + if (!(value instanceof DemoNode)) { + return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + } + + // get node + DemoNode node = (DemoNode) value; + + // get text for node + String text = getNodeText(node); + + // Render node + return super.getTreeCellRendererComponent(tree, text, sel, expanded, leaf, row, hasFocus); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoDataProvider.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoDataProvider.java new file mode 100644 index 0000000..cf18879 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoDataProvider.java @@ -0,0 +1,253 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.tree; + +import org.nuiton.jaxx.runtime.swing.nav.NavDataProvider; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.jaxx.demo.component.jaxx.BoxedDecoratorDemo; +import org.nuiton.jaxx.demo.component.jaxx.StatusMessagePanelDemo; +import org.nuiton.jaxx.demo.component.jaxx.editor.BeanComboBoxDemo; +import org.nuiton.jaxx.demo.component.jaxx.editor.BeanDoubleListDemo; +import org.nuiton.jaxx.demo.component.jaxx.editor.BeanFilterableComboBoxDemo; +import org.nuiton.jaxx.demo.component.jaxx.editor.ComboEditorDemo; +import org.nuiton.jaxx.demo.component.jaxx.editor.DatePickerDemo; +import org.nuiton.jaxx.demo.component.jaxx.editor.FileEditorDemo; +import org.nuiton.jaxx.demo.component.jaxx.editor.I18nEditorDemo; +import org.nuiton.jaxx.demo.component.jaxx.editor.ListSelectorDemo; +import org.nuiton.jaxx.demo.component.jaxx.editor.SimpleTimeEditorDemo; +import org.nuiton.jaxx.demo.component.jaxx.editor.gis.CoordinateDemo; +import org.nuiton.jaxx.demo.component.jaxx.widgets.datetime.DateTimeEditorDemo; +import org.nuiton.jaxx.demo.component.jaxx.widgets.datetime.TimeEditorDemo; +import org.nuiton.jaxx.demo.component.jaxx.widgets.gis.CoordinatesEditorDemo; +import org.nuiton.jaxx.demo.component.jaxx.widgets.number.NumberEditorDemo; +import org.nuiton.jaxx.demo.component.jaxx.widgets.select.FilterableDoubleListDemo; +import org.nuiton.jaxx.demo.component.swing.HidorButtonDemo; +import org.nuiton.jaxx.demo.component.swing.JButtonDemo; +import org.nuiton.jaxx.demo.component.swing.JCheckBoxDemo; +import org.nuiton.jaxx.demo.component.swing.JCheckBoxMenuItemDemo; +import org.nuiton.jaxx.demo.component.swing.JComboBoxDemo; +import org.nuiton.jaxx.demo.component.swing.JDialogDemo; +import org.nuiton.jaxx.demo.component.swing.JListDemo; +import org.nuiton.jaxx.demo.component.swing.JMenuItemDemo; +import org.nuiton.jaxx.demo.component.swing.JPasswordFieldDemo; +import org.nuiton.jaxx.demo.component.swing.JProgressBarDemo; +import org.nuiton.jaxx.demo.component.swing.JRadioButtonDemo; +import org.nuiton.jaxx.demo.component.swing.JRadioButtonMenuItemDemo; +import org.nuiton.jaxx.demo.component.swing.JSliderDemo; +import org.nuiton.jaxx.demo.component.swing.JSpinnerDemo; +import org.nuiton.jaxx.demo.component.swing.JSplitPaneDemo; +import org.nuiton.jaxx.demo.component.swing.JTextAreaDemo; +import org.nuiton.jaxx.demo.component.swing.JTextFieldDemo; +import org.nuiton.jaxx.demo.component.swing.JToggleButtonDemo; +import org.nuiton.jaxx.demo.feature.databinding.BeanDataBindingDemo; +import org.nuiton.jaxx.demo.feature.databinding.BindingExtremeDemo; +import org.nuiton.jaxx.demo.feature.nav.NavDemo; +import org.nuiton.jaxx.demo.feature.validation.list.ListBeanValidationDemo; +import org.nuiton.jaxx.demo.feature.validation.simple.SimpleBeanValidationByListDemo; +import org.nuiton.jaxx.demo.feature.validation.simple.SimpleBeanValidationByTableDemo; +import org.nuiton.jaxx.demo.fun.CalculatorDemo; +import org.nuiton.jaxx.demo.fun.CounterDemo; +import org.nuiton.jaxx.demo.fun.LabelStyleDemo; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.nuiton.i18n.I18n.n; + +/** + * Data provider of the navigation tree. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public class DemoDataProvider implements NavDataProvider { + + /** Logger */ + static private final Log log = LogFactory.getLog(DemoDataProvider.class); + + /** mapping of demo per package */ + protected Map<String, List<Object>> mapping; + + public DemoDataProvider() { + + mapping = new HashMap<String, List<Object>>(); + + if (log.isDebugEnabled()) { + log.debug("for " + this); + } + + addMapping("jaxxdemo.tree", + n("jaxxdemo.component.swing"), + n("jaxxdemo.component.jaxx"), + n("jaxxdemo.feature"), + n("jaxxdemo.fun") + ); + + addMapping(n("jaxxdemo.component.swing"), + n("jaxxdemo.component.swing.buttons"), + n("jaxxdemo.component.swing.form"), + n("jaxxdemo.component.swing.layout"), + n("jaxxdemo.component.swing.menu"), + n("jaxxdemo.component.swing.window"), + JProgressBarDemo.class + ); + + addMapping(n("jaxxdemo.component.swing.buttons"), + JButtonDemo.class, + JCheckBoxDemo.class, + JRadioButtonDemo.class, + JToggleButtonDemo.class + ); + + addMapping(n("jaxxdemo.component.swing.form"), + n("jaxxdemo.component.swing.form.text"), + JComboBoxDemo.class, + JListDemo.class, + JSliderDemo.class, + JSpinnerDemo.class + ); + + addMapping(n("jaxxdemo.component.swing.form.text"), + JPasswordFieldDemo.class, + JTextFieldDemo.class, + JTextAreaDemo.class + ); + + addMapping(n("jaxxdemo.component.swing.layout"), + JSplitPaneDemo.class + ); + + addMapping(n("jaxxdemo.component.swing.menu"), + JMenuItemDemo.class, + JCheckBoxMenuItemDemo.class, + JRadioButtonMenuItemDemo.class + ); + + addMapping(n("jaxxdemo.component.swing.window"), + JDialogDemo.class + ); + + addMapping(n("jaxxdemo.component.jaxx"), + HidorButtonDemo.class, + n("jaxxdemo.component.jaxx.widgets"), + n("jaxxdemo.component.jaxx.editor"), + StatusMessagePanelDemo.class, + BoxedDecoratorDemo.class + ); + + addMapping(n("jaxxdemo.component.jaxx.widgets"), + n("jaxxdemo.component.jaxx.widgets.number"), + n("jaxxdemo.component.jaxx.widgets.select"), + n("jaxxdemo.component.jaxx.widgets.gis"), + n("jaxxdemo.component.jaxx.widgets.datetime") + ); + + addMapping(n("jaxxdemo.component.jaxx.widgets.number"), + NumberEditorDemo.class + ); + + addMapping(n("jaxxdemo.component.jaxx.widgets.select"), + FilterableDoubleListDemo.class + ); + + addMapping(n("jaxxdemo.component.jaxx.widgets.gis"), + CoordinatesEditorDemo.class + ); + + addMapping(n("jaxxdemo.component.jaxx.widgets.datetime"), + DateTimeEditorDemo.class, + TimeEditorDemo.class + ); + + addMapping(n("jaxxdemo.component.jaxx.editor"), + org.nuiton.jaxx.demo.component.jaxx.editor.TimeEditorDemo.class, + SimpleTimeEditorDemo.class, + org.nuiton.jaxx.demo.component.jaxx.editor.NumberEditorDemo.class, + ComboEditorDemo.class, + I18nEditorDemo.class, + DatePickerDemo.class, + FileEditorDemo.class, + ListSelectorDemo.class, + BeanComboBoxDemo.class, + BeanFilterableComboBoxDemo.class, + BeanDoubleListDemo.class, + CoordinateDemo.class + ); + + addMapping(n("jaxxdemo.feature"), + n("jaxxdemo.feature.databinding"), + n("jaxxdemo.feature.validation"), + n("jaxxdemo.feature.nav") + ); + + addMapping(n("jaxxdemo.feature.databinding"), + BindingExtremeDemo.class, + BeanDataBindingDemo.class + ); + + addMapping(n("jaxxdemo.feature.validation"), + n("jaxxdemo.feature.simple.validation"), + n("jaxxdemo.feature.list.validation") + ); + + addMapping(n("jaxxdemo.feature.simple.validation"), + SimpleBeanValidationByListDemo.class, + SimpleBeanValidationByTableDemo.class + ); + + addMapping(n("jaxxdemo.feature.list.validation"), + ListBeanValidationDemo.class + ); + addMapping(n("jaxxdemo.feature.nav"), + NavDemo.class + ); + + addMapping(n("jaxxdemo.fun"), + LabelStyleDemo.class, + CounterDemo.class, + CalculatorDemo.class + ); + } + + protected void addMapping(String packageName, Object... classes) { + List<Object> list = Arrays.asList(classes); + if (log.isDebugEnabled()) { + log.debug("Adding mapping [" + packageName + "] : " + list); + } + mapping.put(packageName, list); + } + + @Override + public boolean isEnabled() { + return true; + } + + public List<Object> getImplementations(String packageName) { + return mapping.get(packageName); + } + + +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoNode.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoNode.java new file mode 100644 index 0000000..1f550b6 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoNode.java @@ -0,0 +1,66 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.tree; + +import org.nuiton.jaxx.runtime.swing.nav.tree.NavTreeNode; + +/** + * Basic node of the demo. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public class DemoNode extends NavTreeNode<DemoNode> { + + private static final long serialVersionUID = 1L; + + public DemoNode(String id) { + super(String.class, + id, + null, + DemoTreeHelper.getChildLoador(DemoNodeLoador.class) + ); + } + + @Override + public DemoNode getContainerNode() { + if (isStringNode()) { + // on est sur un noeud de type String, donc on regarde sur le parent + return this; + } + + // fallback (should never comme here since root is Stringnode) + if (isRoot()) { + // si on arrive sur le root, quelque chose ne va pas, + // on bloque par null, a defaut de declancher une exception + return null; + } + + // cas final : sur un noeud de donnee + classe interne de donnee + return getParent().getContainerNode(); + } + + public DemoNode(Class<?> internalClass) { + super(internalClass, internalClass.getSimpleName(), null, null); + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoNodeLoador.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoNodeLoador.java new file mode 100644 index 0000000..ee3cf3d --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoNodeLoador.java @@ -0,0 +1,84 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.tree; + +import org.nuiton.jaxx.runtime.swing.nav.NavDataProvider; +import org.nuiton.jaxx.runtime.swing.nav.NavNodeChildLoador; +import org.nuiton.jaxx.runtime.swing.nav.tree.NavTreeNodeChildLoador; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.List; + +/** + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public class DemoNodeLoador extends NavTreeNodeChildLoador<Object, Object, DemoNode> { + + private static final long serialVersionUID = 1L; + + /** Logger */ + static private final Log log = LogFactory.getLog(NavNodeChildLoador.class); + + public DemoNodeLoador() { + super(Object.class); + } + + @Override + public List<Object> getData(Class<?> parentClass, + String packageName, + NavDataProvider dataProvider) throws Exception { + + DemoDataProvider provider = (DemoDataProvider) dataProvider; + List<Object> implementations = provider.getImplementations(packageName); + return implementations; + } + + @Override + public DemoNode createNode(Object data, NavDataProvider dataProvider) { + + if (log.isDebugEnabled()) { + log.debug("Creating node for object : " + data); + } + + DemoNode node = null; + + if (data instanceof String) { + // package node + node = new DemoNode((String) data); + } + + if (data instanceof Class<?>) { + // demo node + node = new DemoNode((Class<?>) data); + } + + if (node == null) { + throw new IllegalArgumentException("Data [" + data + "] can not be use to build a node"); + } + + + return node; + } +} diff --git a/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoTreeHelper.java b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoTreeHelper.java new file mode 100644 index 0000000..2ed3cc1 --- /dev/null +++ b/jaxx-demo/src/main/java/org/nuiton/jaxx/demo/tree/DemoTreeHelper.java @@ -0,0 +1,58 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo.tree; + +import org.nuiton.jaxx.runtime.swing.nav.tree.NavTreeHelper; + +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeModel; + +/** + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public class DemoTreeHelper extends NavTreeHelper<DemoNode> { + + public DemoTreeHelper(DemoDataProvider provider) { + setDataProvider(provider); + } + + @Override + public DemoDataProvider getDataProvider() { + return (DemoDataProvider) super.getDataProvider(); + } + + public TreeModel createModel() { + + // Create root static node + DemoNode root = new DemoNode("jaxxdemo.tree"); + + // Create model + DefaultTreeModel model = createModel(root); + + // load all nodes of model + loadAllNodes(root, getDataProvider()); + + return model; + } +} diff --git a/jaxx-demo/src/main/resources/log4j.properties b/jaxx-demo/src/main/resources/log4j.properties index a793374..259ff8a 100644 --- a/jaxx-demo/src/main/resources/log4j.properties +++ b/jaxx-demo/src/main/resources/log4j.properties @@ -26,14 +26,5 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) %M - %m%n -log4j.logger.jaxx=INFO -#log4j.logger.jaxx.demo=INFO -#log4j.logger.jaxx.demo.tree=DEBUG -#log4j.logger.jaxx.runtime.swing.tree=DEBUG -#log4j.logger.jaxx.demo.component.jaxx.tree=DEBUG -#log4j.logger.jaxx.demo.config.DemoConfig=DEBUG -#log4j.logger.jaxx.runtime.swing.editor.config=INFO -#log4j.logger.jaxx.runtime.swing.editor.config.model.ConfigUIModelBuilder=DEBUG log4j.logger.org.nuiton=WARN log4j.logger.org.nuiton.jaxx=INFO -#log4j.logger.jaxx.runtime.swing.help=DEBUG diff --git a/jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-error-validation.xml b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/Identity-error-validation.xml similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-error-validation.xml rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/Identity-error-validation.xml diff --git a/jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-info-validation.xml b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/Identity-info-validation.xml similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-info-validation.xml rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/Identity-info-validation.xml diff --git a/jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-warning-validation.xml b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/Identity-warning-validation.xml similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-warning-validation.xml rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/Identity-warning-validation.xml diff --git a/jaxx-demo/src/main/resources/jaxx/demo/entities/Model-error-validation.xml b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/Model-error-validation.xml similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/entities/Model-error-validation.xml rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/Model-error-validation.xml diff --git a/jaxx-demo/src/main/resources/jaxx/demo/entities/Model-info-validation.xml b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/Model-info-validation.xml similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/entities/Model-info-validation.xml rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/Model-info-validation.xml diff --git a/jaxx-demo/src/main/resources/jaxx/demo/entities/Model-warning-validation.xml b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/Model-warning-validation.xml similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/entities/Model-warning-validation.xml rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/Model-warning-validation.xml diff --git a/jaxx-demo/src/main/resources/jaxx/demo/entities/People-error-validation.xml b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/People-error-validation.xml similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/entities/People-error-validation.xml rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/People-error-validation.xml diff --git a/jaxx-demo/src/main/resources/jaxx/demo/entities/People-info-validation.xml b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/People-info-validation.xml similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/entities/People-info-validation.xml rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/People-info-validation.xml diff --git a/jaxx-demo/src/main/resources/jaxx/demo/entities/People-warning-validation.xml b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/People-warning-validation.xml similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/entities/People-warning-validation.xml rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/entities/People-warning-validation.xml diff --git a/jaxx-demo/src/main/resources/jaxx/demo/images/Amethyst.jpg b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/Amethyst.jpg similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/images/Amethyst.jpg rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/Amethyst.jpg diff --git a/jaxx-demo/src/main/resources/jaxx/demo/images/Lynx.jpg b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/Lynx.jpg similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/images/Lynx.jpg rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/Lynx.jpg diff --git a/jaxx-demo/src/main/resources/jaxx/demo/images/Tomato.jpg b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/Tomato.jpg similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/images/Tomato.jpg rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/Tomato.jpg diff --git a/jaxx-demo/src/main/resources/jaxx/demo/images/ana.jpg b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/ana.jpg similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/images/ana.jpg rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/ana.jpg diff --git a/jaxx-demo/src/main/resources/jaxx/demo/images/hector.jpg b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/hector.jpg similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/images/hector.jpg rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/hector.jpg diff --git a/jaxx-demo/src/main/resources/jaxx/demo/images/jack.jpg b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/jack.jpg similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/images/jack.jpg rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/jack.jpg diff --git a/jaxx-demo/src/main/resources/jaxx/demo/images/jim.jpg b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/jim.jpg similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/images/jim.jpg rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/jim.jpg diff --git a/jaxx-demo/src/main/resources/jaxx/demo/images/joe.jpg b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/joe.jpg similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/images/joe.jpg rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/joe.jpg diff --git a/jaxx-demo/src/main/resources/jaxx/demo/images/joker.jpg b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/joker.jpg similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/images/joker.jpg rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/joker.jpg diff --git a/jaxx-demo/src/main/resources/jaxx/demo/images/nacho.jpg b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/nacho.jpg similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/images/nacho.jpg rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/nacho.jpg diff --git a/jaxx-demo/src/main/resources/jaxx/demo/images/nacho2.png b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/nacho2.png similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/images/nacho2.png rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/nacho2.png diff --git a/jaxx-demo/src/main/resources/jaxx/demo/images/pencil_black.gif b/jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/pencil_black.gif similarity index 100% rename from jaxx-demo/src/main/resources/jaxx/demo/images/pencil_black.gif rename to jaxx-demo/src/main/resources/org/nuiton/jaxx/demo/images/pencil_black.gif diff --git a/jaxx-demo/src/test/java/jaxx/demo/BeanValidatorDetectorTest.java b/jaxx-demo/src/test/java/jaxx/demo/BeanValidatorDetectorTest.java deleted file mode 100644 index 7d65eb8..0000000 --- a/jaxx-demo/src/test/java/jaxx/demo/BeanValidatorDetectorTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * #%L - * JAXX :: Demo - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.demo; - -import jaxx.demo.entities.Identity; -import jaxx.demo.entities.Model; -import jaxx.demo.entities.People; -import org.junit.Assert; -import org.junit.Test; -import org.nuiton.validator.AbstractValidatorDetectorTest; -import org.nuiton.validator.NuitonValidator; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.xwork2.XWork2NuitonValidatorProvider; - -import java.io.File; -import java.util.Iterator; -import java.util.SortedSet; - -/** @author Tony Chemit - chemit@codelutin.com */ -public class BeanValidatorDetectorTest extends AbstractValidatorDetectorTest { - - public BeanValidatorDetectorTest() { - // prefer do tests on target copy instead of original files - super(XWork2NuitonValidatorProvider.PROVIDER_NAME); - } - - @Test - public void detectAllValidators() { - SortedSet<NuitonValidator<?>> result; - NuitonValidator<?> validator; - Iterator<NuitonValidator<?>> iterator; - - // test with all context and all scopes - - result = detectValidators(Identity.class, Model.class, People.class); - - Assert.assertNotNull(result); - Assert.assertEquals(3, result.size()); - - - iterator = result.iterator(); - validator = iterator.next(); - - assertValidatorModel(validator, null, Identity.class, NuitonValidatorScope.values()); - assertValidatorEffectiveScopes(validator, NuitonValidatorScope.ERROR, NuitonValidatorScope.WARNING, NuitonValidatorScope.INFO); -// ValidatorTestHelper.assertValidatorEffectiveFields(validator, NuitonValidatorScope.ERROR, Person.PROPERTY_NAME, Person.PROPERTY_FIRSTNAME); -// ValidatorTestHelper.assertValidatorEffectiveFields(validator, NuitonValidatorScope.WARNING, Person.PROPERTY_PET); - - validator = iterator.next(); - assertValidatorModel(validator, null, Model.class, NuitonValidatorScope.values()); - assertValidatorEffectiveScopes(validator, NuitonValidatorScope.ERROR, NuitonValidatorScope.WARNING, NuitonValidatorScope.INFO); -// ValidatorTestHelper.assertValidatorEffectiveFields(validator, NuitonValidatorScope.ERROR, Pet.PROPERTY_NAME); - - validator = iterator.next(); - assertValidatorModel(validator, null, People.class, NuitonValidatorScope.values()); - assertValidatorEffectiveScopes(validator, NuitonValidatorScope.ERROR, NuitonValidatorScope.WARNING, NuitonValidatorScope.INFO); - - } - - @Override - protected File getRootDirectory(File basedir) { - return new File(basedir, "target" + File.separator + "classes"); - } -} diff --git a/jaxx-demo/src/test/java/org/nuiton/jaxx/demo/BeanValidatorDetectorTest.java b/jaxx-demo/src/test/java/org/nuiton/jaxx/demo/BeanValidatorDetectorTest.java new file mode 100644 index 0000000..a64a258 --- /dev/null +++ b/jaxx-demo/src/test/java/org/nuiton/jaxx/demo/BeanValidatorDetectorTest.java @@ -0,0 +1,84 @@ +/* + * #%L + * JAXX :: Demo + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.demo; + +import org.nuiton.jaxx.demo.entities.Identity; +import org.nuiton.jaxx.demo.entities.Model; +import org.nuiton.jaxx.demo.entities.People; +import org.junit.Assert; +import org.junit.Test; +import org.nuiton.validator.AbstractValidatorDetectorTest; +import org.nuiton.validator.NuitonValidator; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.xwork2.XWork2NuitonValidatorProvider; + +import java.io.File; +import java.util.Iterator; +import java.util.SortedSet; + +/** @author Tony Chemit - chemit@codelutin.com */ +public class BeanValidatorDetectorTest extends AbstractValidatorDetectorTest { + + public BeanValidatorDetectorTest() { + // prefer do tests on target copy instead of original files + super(XWork2NuitonValidatorProvider.PROVIDER_NAME); + } + + @Test + public void detectAllValidators() { + SortedSet<NuitonValidator<?>> result; + NuitonValidator<?> validator; + Iterator<NuitonValidator<?>> iterator; + + // test with all context and all scopes + + result = detectValidators(Identity.class, Model.class, People.class); + + Assert.assertNotNull(result); + Assert.assertEquals(3, result.size()); + + + iterator = result.iterator(); + validator = iterator.next(); + + assertValidatorModel(validator, null, Identity.class, NuitonValidatorScope.values()); + assertValidatorEffectiveScopes(validator, NuitonValidatorScope.ERROR, NuitonValidatorScope.WARNING, NuitonValidatorScope.INFO); +// ValidatorTestHelper.assertValidatorEffectiveFields(validator, NuitonValidatorScope.ERROR, Person.PROPERTY_NAME, Person.PROPERTY_FIRSTNAME); +// ValidatorTestHelper.assertValidatorEffectiveFields(validator, NuitonValidatorScope.WARNING, Person.PROPERTY_PET); + + validator = iterator.next(); + assertValidatorModel(validator, null, Model.class, NuitonValidatorScope.values()); + assertValidatorEffectiveScopes(validator, NuitonValidatorScope.ERROR, NuitonValidatorScope.WARNING, NuitonValidatorScope.INFO); +// ValidatorTestHelper.assertValidatorEffectiveFields(validator, NuitonValidatorScope.ERROR, Pet.PROPERTY_NAME); + + validator = iterator.next(); + assertValidatorModel(validator, null, People.class, NuitonValidatorScope.values()); + assertValidatorEffectiveScopes(validator, NuitonValidatorScope.ERROR, NuitonValidatorScope.WARNING, NuitonValidatorScope.INFO); + + } + + @Override + protected File getRootDirectory(File basedir) { + return new File(basedir, "target" + File.separator + "classes"); + } +} diff --git a/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpIdsMojo.java b/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpIdsMojo.java index 4f71664..3c12297 100644 --- a/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpIdsMojo.java +++ b/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpIdsMojo.java @@ -24,7 +24,7 @@ package org.nuiton.jaxx.plugin; import com.google.common.base.Charsets; import com.google.common.io.Closeables; import com.google.common.io.Files; -import jaxx.compiler.decorators.HelpRootCompiledObjectDecorator; +import org.nuiton.jaxx.compiler.decorators.HelpRootCompiledObjectDecorator; import org.apache.commons.lang3.StringUtils; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.LifecyclePhase; diff --git a/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateMojo.java b/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateMojo.java index 632a058..731d1af 100644 --- a/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateMojo.java +++ b/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateMojo.java @@ -22,22 +22,22 @@ package org.nuiton.jaxx.plugin; -import jaxx.compiler.CompiledObjectDecorator; -import jaxx.compiler.CompilerConfiguration; -import jaxx.compiler.I18nHelper; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXEngine; -import jaxx.compiler.JAXXFactory; -import jaxx.compiler.beans.BeanInfoUtil; -import jaxx.compiler.binding.DataBindingHelper; -import jaxx.compiler.finalizers.JAXXCompilerFinalizer; -import jaxx.compiler.spi.DefaultInitializer; -import jaxx.compiler.spi.Initializer; -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.spi.UIHandler; -import jaxx.runtime.swing.help.JAXXHelpBroker; -import jaxx.runtime.validator.swing.SwingValidator; +import org.nuiton.jaxx.compiler.CompiledObjectDecorator; +import org.nuiton.jaxx.compiler.CompilerConfiguration; +import org.nuiton.jaxx.compiler.I18nHelper; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXEngine; +import org.nuiton.jaxx.compiler.JAXXFactory; +import org.nuiton.jaxx.compiler.beans.BeanInfoUtil; +import org.nuiton.jaxx.compiler.binding.DataBindingHelper; +import org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import org.nuiton.jaxx.compiler.spi.DefaultInitializer; +import org.nuiton.jaxx.compiler.spi.Initializer; +import org.nuiton.jaxx.runtime.JAXXContext; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.swing.help.JAXXHelpBroker; +import org.nuiton.jaxx.validator.swing.SwingValidator; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.maven.plugin.MojoExecutionException; @@ -96,7 +96,7 @@ public class GenerateMojo extends AbstractJaxxMojo implements CompilerConfigurat /** * FQN of compiler to use (by default swing one). */ - @Parameter(property = "jaxx.compilerFQN", defaultValue = "jaxx.compiler.JAXXCompiler", required = true) + @Parameter(property = "jaxx.compilerFQN", defaultValue = "org.nuiton.jaxx.compiler.JAXXCompiler", required = true) protected String compilerFQN; /** @@ -104,7 +104,7 @@ public class GenerateMojo extends AbstractJaxxMojo implements CompilerConfigurat * * Must not be abstract. */ - @Parameter(property = "jaxx.jaxxContextFQN", defaultValue = "jaxx.runtime.context.DefaultJAXXContext", required = true) + @Parameter(property = "jaxx.jaxxContextFQN", defaultValue = "org.nuiton.jaxx.runtime.context.DefaultJAXXContext", required = true) protected String jaxxContextFQN; /** @@ -122,7 +122,7 @@ public class GenerateMojo extends AbstractJaxxMojo implements CompilerConfigurat * * @see CompiledObjectDecorator */ - @Parameter(property = "jaxx.defaultDecoratorFQN", defaultValue = "jaxx.compiler.decorators.DefaultCompiledObjectDecorator") + @Parameter(property = "jaxx.defaultDecoratorFQN", defaultValue = "org.nuiton.jaxx.compiler.decorators.DefaultCompiledObjectDecorator") protected String defaultDecoratorFQN; /** @@ -266,7 +266,7 @@ public class GenerateMojo extends AbstractJaxxMojo implements CompilerConfigurat * * @since 1.3 */ - @Parameter(property = "jaxx.helpBrokerFQN", defaultValue = "jaxx.runtime.swing.help.JAXXHelpBroker") + @Parameter(property = "jaxx.helpBrokerFQN", defaultValue = "org.nuiton.jaxx.runtime.swing.help.JAXXHelpBroker") protected String helpBrokerFQN; /** @@ -276,7 +276,7 @@ public class GenerateMojo extends AbstractJaxxMojo implements CompilerConfigurat * * @since 2.6 */ - @Parameter(property = "jaxx.validatorFactoryFQN", defaultValue = "jaxx.runtime.validator.swing.SwingValidator") + @Parameter(property = "jaxx.validatorFactoryFQN", defaultValue = "org.nuiton.jaxx.validator.swing.SwingValidator") protected String validatorFactoryFQN; /** diff --git a/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1124Test.java b/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1124Test.java index 9277367..4361dc3 100644 --- a/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1124Test.java +++ b/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1124Test.java @@ -21,8 +21,7 @@ */ package org.nuiton.jaxx.plugin; -import jaxx.compiler.I18nHelper; -import jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.JAXXUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.Assert; diff --git a/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1404Test.java b/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1404Test.java index 58ff931..70b3d9c 100644 --- a/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1404Test.java +++ b/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1404Test.java @@ -38,7 +38,7 @@ public class Bug1404Test extends JaxxBaseTest { mojo.execute(); assertNumberJaxxFiles(3); - checkPattern(mojo, "import jaxx.runtime.SwingUtil;", true); - checkPattern(mojo, "import jaxx.runtime.JAXXUtil;", true); + checkPattern(mojo, "import org.nuiton.jaxx.runtime.SwingUtil;", true); + checkPattern(mojo, "import org.nuiton.jaxx.runtime.JAXXUtil;", true); } } diff --git a/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1750Test.java b/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1750Test.java index 62f307f..c93dec3 100644 --- a/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1750Test.java +++ b/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1750Test.java @@ -22,10 +22,10 @@ package org.nuiton.jaxx.plugin; -import jaxx.runtime.Base64Coder; -import jaxx.compiler.JAXXCompiler; -import jaxx.runtime.JAXXObjectDescriptor; -import jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.Base64Coder; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.runtime.JAXXObjectDescriptor; +import org.nuiton.jaxx.runtime.JAXXUtil; import org.junit.Test; import static org.junit.Assert.*; diff --git a/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/CompilerTest.java b/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/CompilerTest.java index 4592867..537d041 100644 --- a/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/CompilerTest.java +++ b/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/CompilerTest.java @@ -22,7 +22,7 @@ package org.nuiton.jaxx.plugin; -import jaxx.runtime.context.DefaultJAXXContext; +import org.nuiton.jaxx.runtime.context.DefaultJAXXContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.maven.plugin.MojoExecutionException; diff --git a/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/JaxxBaseTest.java b/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/JaxxBaseTest.java index 599734d..26a38a0 100644 --- a/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/JaxxBaseTest.java +++ b/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/JaxxBaseTest.java @@ -22,12 +22,12 @@ package org.nuiton.jaxx.plugin; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JAXXCompilerFile; -import jaxx.compiler.JAXXEngine; -import jaxx.compiler.decorators.DefaultCompiledObjectDecorator; -import jaxx.runtime.context.DefaultJAXXContext; -import jaxx.runtime.validator.swing.SwingValidator; +import org.nuiton.jaxx.compiler.JAXXCompiler; +import org.nuiton.jaxx.compiler.JAXXCompilerFile; +import org.nuiton.jaxx.compiler.JAXXEngine; +import org.nuiton.jaxx.compiler.decorators.DefaultCompiledObjectDecorator; +import org.nuiton.jaxx.runtime.context.DefaultJAXXContext; +import org.nuiton.jaxx.validator.swing.SwingValidator; import org.apache.commons.io.FileUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/jaxx-maven-plugin/src/test/resources/log4j.properties b/jaxx-maven-plugin/src/test/resources/log4j.properties index f17426c..b48ebf0 100644 --- a/jaxx-maven-plugin/src/test/resources/log4j.properties +++ b/jaxx-maven-plugin/src/test/resources/log4j.properties @@ -29,4 +29,4 @@ log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) %M - %m%n log4j.logger.org.nuiton.plugin.AbstractMojoTest=INFO log4j.logger.org.nuiton.jaxx=INFO log4j.logger.jaxx.compiler=INFO -#log4j.logger.jaxx.compiler.binding=DEBUG +#log4j.logger.org.nuiton.jaxx.compiler.binding=DEBUG diff --git a/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/Validation.jaxx b/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/Validation.jaxx index e0a1869..3b256e2 100644 --- a/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/Validation.jaxx +++ b/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/Validation.jaxx @@ -37,13 +37,13 @@ <field name="ratio"/> </BeanValidator> <BeanValidator id='validator2' bean='model2' errorListModel='errors' - uiClass="jaxx.runtime.validator.swing.ui.IconValidationUI"> + uiClass="org.nuiton.jaxx.validator.swing.ui.IconValidationUI"> <field name="text" component="_text"/> <field name="text2" component="_text2"/> <field name="ratio" component="_ratio"/> </BeanValidator> <BeanValidator id='validator3' autoField='true' bean='identity' errorListModel='errors' - uiClass="jaxx.runtime.validator.swing.ui.TranslucentValidationUI"> + uiClass="org.nuiton.jaxx.validator.swing.ui.TranslucentValidationUI"> <field name="email" component="email2"/> </BeanValidator> diff --git a/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/lambdaTest/LambdaHandler.java b/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/lambdaTest/LambdaHandler.java index a45686b..49b3d6e 100644 --- a/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/lambdaTest/LambdaHandler.java +++ b/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/lambdaTest/LambdaHandler.java @@ -22,8 +22,8 @@ package org.nuiton.jaxx.plugin.lambdaTest; * #L% */ -import jaxx.runtime.JAXXObject; -import jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.spi.UIHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/Base64Coder.java b/jaxx-runtime/src/main/java/jaxx/runtime/Base64Coder.java deleted file mode 100644 index 20f9da4..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/Base64Coder.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -/** - * A Base64 Encoder/Decoder. - * - * - * This class is used to encode and decode data in Base64 format as described in RFC 1521. - * - * - * This is "Open Source" software and released under the <a href="http://www.gnu.org/licenses/lgpl.html">GNU/LGPL</a> license.<br> - * It is provided "as is" without warranty of any kind.<br> - * Copyright 2003: Christian d'Heureuse, Inventec Informatik AG, Switzerland.<br> - * Home page: <a href="http://www.source-code.biz">www.source-code.biz</a><br> - * - * - * Version history:<br> - * 2003-07-22 Christian d'Heureuse (chdh): Module created.<br> - * 2005-08-11 chdh: Lincense changed from GPL to LGPL.<br> - * 2006-11-21 chdh:<br> - * Method encode(String) renamed to encodeString(String).<br> - * Method decode(String) renamed to decodeString(String).<br> - * New method encode(byte[],int) added.<br> - * New method decode(String) added.<br> - */ - -public class Base64Coder { - - // Mapping table from 6-bit nibbles to Base64 characters. - - private static char[] map1 = new char[64]; - - static { - int i = 0; - for (char c = 'A'; c <= 'Z'; c++) { - map1[i++] = c; - } - for (char c = 'a'; c <= 'z'; c++) { - map1[i++] = c; - } - for (char c = '0'; c <= '9'; c++) { - map1[i++] = c; - } - map1[i++] = '+'; - map1[i] = '/'; - } - - // Mapping table from Base64 characters to 6-bit nibbles. - - private static byte[] map2 = new byte[128]; - - static { - for (int i = 0; i < map2.length; i++) { - map2[i] = -1; - } - for (int i = 0; i < 64; i++) { - map2[map1[i]] = (byte) i; - } - } - - /** - * Read the object from Base64 string. - * - * @param s the string representation of serialized object. - * @param gzip if gzip stream - * @return the deserialize object - * @throws java.io.IOException if any io pb - * @throws ClassNotFoundException if class not found ? - */ - public static Object deserialize(String s, boolean gzip) throws IOException, - ClassNotFoundException { - byte[] data = Base64Coder.decode(s); - InputStream stream = new ByteArrayInputStream(data); - if (gzip) { - stream = new GZIPInputStream(stream); - } - ObjectInputStream ois = new ObjectInputStream(stream); - Object o = ois.readObject(); - ois.close(); - return o; - } - - /** - * Write the object to a Base64 string. - * - * @param o the object to serialize - * @param gzip if gzip stream - * @return the string representation - * @throws java.io.IOException if any io pb - */ - public static String serialize(Object o, boolean gzip) throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - ObjectOutputStream oos; - if (gzip) { - oos = new ObjectOutputStream(new GZIPOutputStream(stream)); - } else { - oos = new ObjectOutputStream(stream); - } - oos.writeObject(o); - oos.close(); - return new String(Base64Coder.encode(stream.toByteArray())); - } - - /** - * Encodes a string into Base64 format. - * No blanks or line breaks are inserted. - * - * @param s a String to be encoded. - * @return A String with the Base64 encoded data. - */ - public static String encodeString(String s) { - return new String(encode(s.getBytes())); - } - - /** - * Encodes a byte array into Base64 format. - * No blanks or line breaks are inserted. - * - * @param in an array containing the data bytes to be encoded. - * @return A character array with the Base64 encoded data. - */ - public static char[] encode(byte[] in) { - return encode(in, in.length); - } - - /** - * Encodes a byte array into Base64 format. - * No blanks or line breaks are inserted. - * - * @param in an array containing the data bytes to be encoded. - * @param iLen number of bytes to process in <code>in</code>. - * @return A character array with the Base64 encoded data. - */ - public static char[] encode(byte[] in, int iLen) { - int oDataLen = (iLen * 4 + 2) / 3; // output length without padding - int oLen = ((iLen + 2) / 3) * 4; // output length including padding - char[] out = new char[oLen]; - int ip = 0; - int op = 0; - while (ip < iLen) { - int i0 = in[ip++] & 0xff; - int i1 = ip < iLen ? in[ip++] & 0xff : 0; - int i2 = ip < iLen ? in[ip++] & 0xff : 0; - int o0 = i0 >>> 2; - int o1 = ((i0 & 3) << 4) | (i1 >>> 4); - int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); - int o3 = i2 & 0x3F; - out[op++] = map1[o0]; - out[op++] = map1[o1]; - out[op] = op < oDataLen ? map1[o2] : '='; - op++; - out[op] = op < oDataLen ? map1[o3] : '='; - op++; - } - return out; - } - - /** - * Decodes a string from Base64 format. - * - * @param s a Base64 String to be decoded. - * @return A String containing the decoded data. - * @throws IllegalArgumentException if the input is not valid Base64 encoded data. - */ - public static String decodeString(String s) { - return new String(decode(s)); - } - - /** - * Decodes a byte array from Base64 format. - * - * @param s a Base64 String to be decoded. - * @return An array containing the decoded data bytes. - * @throws IllegalArgumentException if the input is not valid Base64 encoded data. - */ - public static byte[] decode(String s) { - return decode(s.toCharArray()); - } - - /** - * Decodes a byte array from Base64 format. - * No blanks or line breaks are allowed within the Base64 encoded data. - * - * @param in a character array containing the Base64 encoded data. - * @return An array containing the decoded data bytes. - * @throws IllegalArgumentException if the input is not valid Base64 encoded data. - */ - public static byte[] decode(char[] in) { - int iLen = in.length; - if (iLen % 4 != 0) { - throw new IllegalArgumentException("Length of Base64 encoded input string is not a multiple of 4."); - } - while (iLen > 0 && in[iLen - 1] == '=') { - iLen--; - } - int oLen = (iLen * 3) / 4; - byte[] out = new byte[oLen]; - int ip = 0; - int op = 0; - while (ip < iLen) { - int i0 = in[ip++]; - int i1 = in[ip++]; - int i2 = ip < iLen ? in[ip++] : 'A'; - int i3 = ip < iLen ? in[ip++] : 'A'; - if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) { - throw new IllegalArgumentException("Illegal character in Base64 encoded data."); - } - int b0 = map2[i0]; - int b1 = map2[i1]; - int b2 = map2[i2]; - int b3 = map2[i3]; - if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) { - throw new IllegalArgumentException("Illegal character in Base64 encoded data."); - } - int o0 = (b0 << 2) | (b1 >>> 4); - int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2); - int o2 = ((b2 & 3) << 6) | b3; - out[op++] = (byte) o0; - if (op < oLen) { - out[op++] = (byte) o1; - } - if (op < oLen) { - out[op++] = (byte) o2; - } - } - return out; - } - - // Dummy constructor. - - private Base64Coder() { - } - -} // end class Base64Coder - diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/ComponentDescriptor.java b/jaxx-runtime/src/main/java/jaxx/runtime/ComponentDescriptor.java deleted file mode 100644 index 9c41116..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/ComponentDescriptor.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime; - -import java.io.Serializable; - -public class ComponentDescriptor implements Serializable { - String id; - - String javaClassName; - - String styleClass; - - ComponentDescriptor parent; - - private static final long serialVersionUID = 1L; - - - public ComponentDescriptor(String id, String javaClassName, String styleClass, ComponentDescriptor parent) { - this.id = id; - this.javaClassName = javaClassName; - this.styleClass = styleClass; - this.parent = parent; - } - - - public String getId() { - return id; - } - - - public String getJavaClassName() { - return javaClassName; - } - - - public String getStyleClass() { - return styleClass; - } - - - public ComponentDescriptor getParent() { - return parent; - } - - - @Override - public String toString() { - return "ComponentDescriptor[" + id + ", " + javaClassName + ", " + styleClass + "]"; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/DataBindingListener.java b/jaxx-runtime/src/main/java/jaxx/runtime/DataBindingListener.java deleted file mode 100644 index d0e5066..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/DataBindingListener.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - - -/** - * A <code>PropertyChangeListener</code> which processes a data binding when it receives a - * <code>PropertyChangeEvent</code>. - */ -public class DataBindingListener implements PropertyChangeListener { - private JAXXObject object; - - private String dest; - - /** - * Creates a new <code>DataBindingListener</code> which will run the given data binding - * when it receives a <code>PropertyChangeEvent</code>. - * - * @param object the object in which the data binding exists - * @param dest the name of the data binding to run - */ - public DataBindingListener(JAXXObject object, String dest) { - this.object = object; - this.dest = dest; - } - - - /** - * Processes the data binding in response to a <code>PropertyChangeEvent</code>. - * - * @param e the event which triggered the binding - */ - @Override - public void propertyChange(PropertyChangeEvent e) { - object.processDataBinding(dest); - - // for now, handle dependency changes by always removing & reapplying - // the binding. We should be more efficient and only do this when it's - // actually necessary - object.removeDataBinding(dest); - object.applyDataBinding(dest); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/DataBindingUpdateListener.java b/jaxx-runtime/src/main/java/jaxx/runtime/DataBindingUpdateListener.java deleted file mode 100644 index 3f44e6f..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/DataBindingUpdateListener.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - - -/** - * A <code>PropertyChangeListener</code> which removes and re-applies a data binding - * when it receives a <code>PropertyChangeEvent</code>. - */ -public class DataBindingUpdateListener implements PropertyChangeListener { - private JAXXObject object; - - private String dest; - - /** - * Creates a new <code>DataBindingUpdateListener</code> which will remove and re-apply a - * data binding when it receives a <code>PropertyChangeEvent</code>. - * - * @param object the object in which the data binding exists - * @param dest the name of the data binding to reapply - */ - public DataBindingUpdateListener(JAXXObject object, String dest) { - this.object = object; - this.dest = dest; - } - - - public String getBindingName() { - return dest; - } - - - /** - * Updates the data binding in response to a <code>PropertyChangeEvent</code>. - * - * @param e the event which triggered the binding - */ - @Override - public void propertyChange(PropertyChangeEvent e) { - object.removeDataBinding(dest); - object.applyDataBinding(dest); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil.java b/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil.java deleted file mode 100644 index d61b2e2..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil.java +++ /dev/null @@ -1,359 +0,0 @@ -package jaxx.runtime; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.jaxx.runtime.JaxxFileChooser; -import org.nuiton.util.FileUtil; - -import javax.swing.JFileChooser; -import java.awt.Component; -import java.io.File; - -/** - * To help choosing a file / directory. - * - * Was previously in {@code org.nuiton.util.FileUtil} from - * {@code nuiton-utils} project. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.16 - * @deprecated since 2.15, prefer use {@link JaxxFileChooser}. - */ -public class FileChooserUtil { - - /** Logger. */ - private static final Log log = LogFactory.getLog(FileChooserUtil.class); - - public static final File DEFAULT_CURRENT_DIRECTORY_FILE = new File("."); - - protected static File currentDirectory = DEFAULT_CURRENT_DIRECTORY_FILE; - - public static void setCurrentDirectory(File dir) { - JaxxFileChooser.setCurrentDirectory(currentDirectory ); - } - - public static File getCurrentDirectory() { - return JaxxFileChooser.getCurrentDirectory(); - } - - public static boolean isCurrentDirectoryDefault() { - return JaxxFileChooser.isCurrentDirectoryDefault(); - } - - protected FileChooserUtil() { - // no instance please - } - - - public static class PatternChooserFilter extends javax.swing.filechooser.FileFilter { - protected String pattern; - - protected String description; - - public PatternChooserFilter(String pattern, String description) { - this.pattern = pattern; - this.description = description; - } - - @Override - public boolean accept(File f) { - return f.isDirectory() || f.getAbsolutePath().matches(pattern); - } - - @Override - public String getDescription() { - return description; - } - - } - - - /** - * Retourne le nom du fichier entre dans la boite de dialogue. - * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. - * - * @param patternOrDescriptionFilters les filtres a utiliser, les chaines doivent etre données - * par deux, le pattern du filtre + la description du filtre - * @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé - * @see #getFile(javax.swing.filechooser.FileFilter...) - */ - public static File getFile(String... patternOrDescriptionFilters) { - File result; - result = getFile(null, patternOrDescriptionFilters); - return result; - } - - /** - * Retourne le nom du fichier entre dans la boite de dialogue. - * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. - * - * @param filters les filtres a ajouter - * @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé - */ - public static File getFile(javax.swing.filechooser.FileFilter... filters) { - return getFile(null, filters); - } - - /** - * Retourne le nom du fichier entre dans la boite de dialogue. - * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. - * - * @param parent le component parent du dialog - * @param patternOrDescriptionFilters les filtres a utiliser, les chaines doivent etre données - * par deux, le pattern du filtre + la description du filtre - * @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé - * @see #getFile(javax.swing.filechooser.FileFilter...) - */ - public static File getFile(Component parent, - String... patternOrDescriptionFilters) { - File result; - result = getFile("Ok", "Ok", parent, patternOrDescriptionFilters); - return result; - } - - /** - * Retourne le nom du fichier entre dans la boite de dialogue. - * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. - * - * @param title le titre de la boite de dialogue - * @param approvalText le label du boutton d'acceptation - * @param parent le component parent du dialog - * @param patternOrDescriptionFilters les filtres a utiliser, les chaines doivent etre données - * par deux, le pattern du filtre + la description du filtre - * @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé - * @see #getFile(javax.swing.filechooser.FileFilter...) - */ - public static File getFile(String title, - String approvalText, - Component parent, - String... patternOrDescriptionFilters) { - - if (patternOrDescriptionFilters.length % 2 != 0) { - throw new IllegalArgumentException( - "Arguments must be (pattern, description) couple"); - } - javax.swing.filechooser.FileFilter[] filters = - new javax.swing.filechooser.FileFilter[ - patternOrDescriptionFilters.length / 2]; - for (int i = 0; i < filters.length; i++) { - String pattern = patternOrDescriptionFilters[i * 2]; - String description = patternOrDescriptionFilters[i * 2 + 1]; - filters[i] = new PatternChooserFilter(pattern, description); - } - File result; - result = getFile(title, approvalText, parent, filters); - return result; - } - - - /** - * Retourne le nom du fichier entre dans la boite de dialogue. - * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. - * - * @param parent le component parent du dialog - * @param filters les filtres a ajouter - * @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé - */ - public static File getFile(Component parent, - javax.swing.filechooser.FileFilter... filters) { - return getFile("Ok", "Ok", parent, filters); - } - - /** - * Retourne le nom du fichier entre dans la boite de dialogue. - * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. - * - * @param title le titre de la boite de dialogue - * @param approvalText le label du boutton d'acceptation - * @param parent le component parent du dialog - * @param filters les filtres a ajouter - * @return le fichier accepté, ou null si rien n'est choisi ou l'utilisateur a annulé - */ - public static File getFile(String title, - String approvalText, - Component parent, - javax.swing.filechooser.FileFilter... filters) { - try { - JFileChooser chooser = new JFileChooser(currentDirectory); - - chooser.setDialogType(JFileChooser.CUSTOM_DIALOG); - if (filters.length > 0) { - if (filters.length == 1) { - chooser.setFileFilter(filters[0]); - } else { - for (javax.swing.filechooser.FileFilter filter : filters) { - chooser.addChoosableFileFilter(filter); - } - } - } - chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - chooser.setDialogTitle(title); - int returnVal = chooser.showDialog(parent, approvalText); - if (returnVal == JFileChooser.APPROVE_OPTION) { - File theFile = chooser.getSelectedFile(); - if (theFile != null) { - currentDirectory = theFile; - return theFile.getAbsoluteFile(); - } - } - } catch (Exception eee) { - log.warn("Erreur:", eee); - } - return null; - } - - /** - * Retourne le nom du fichier entre dans la boite de dialogue. - * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. - * - * @param title le titre de la boite de dialogue - * @param approvalText le label du boutton d'acceptation - * @param parent le component parent du dialog - * @param patternOrDescriptionFilters les filtres a utiliser, les chaines doivent etre données - * par deux, le pattern du filtre + la description du filtre - * @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé - */ - public static File saveFile(String filename, - String title, - String approvalText, - Component parent, - String... patternOrDescriptionFilters) { - - if (patternOrDescriptionFilters.length % 2 != 0) { - throw new IllegalArgumentException( - "Arguments must be (pattern, description) couple"); - } - javax.swing.filechooser.FileFilter[] filters = - new javax.swing.filechooser.FileFilter[ - patternOrDescriptionFilters.length / 2]; - for (int i = 0; i < filters.length; i++) { - String pattern = patternOrDescriptionFilters[i * 2]; - String description = patternOrDescriptionFilters[i * 2 + 1]; - filters[i] = new FileUtil.PatternChooserFilter(pattern, description); - } - File result; - result = saveFile(filename, title, approvalText, parent, filters); - return result; - } - - /** - * Retourne le nom du fichier entre dans la boite de dialogue. - * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. - * - * @param title le titre de la boite de dialogue - * @param approvalText le label du boutton d'acceptation - * @param parent le component parent du dialog - * @param filters les filtres a ajouter - * @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé - */ - public static File saveFile(String filename, - String title, - String approvalText, - Component parent, - javax.swing.filechooser.FileFilter... filters) { - File selectedFile = new File(getCurrentDirectory(), filename); - JFileChooser chooser = new JFileChooser(selectedFile); - - chooser.setDialogType(JFileChooser.SAVE_DIALOG); - chooser.setSelectedFile(selectedFile); - if (filters.length > 0) { - if (filters.length == 1) { - chooser.setFileFilter(filters[0]); - } else { - for (javax.swing.filechooser.FileFilter filter : filters) { - chooser.addChoosableFileFilter(filter); - } - } - } - chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - chooser.setDialogTitle(title); - - File result = null; - - int returnVal = chooser.showDialog(parent, approvalText); - if (returnVal == JFileChooser.APPROVE_OPTION) { - result = chooser.getSelectedFile(); - if (result != null) { - setCurrentDirectory(result); - result = result.getAbsoluteFile(); - } - } - return result; - } - - /** - * @return le nom du repertoire entre dans la boite de dialogue. - * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne - * null. - */ - public static String getDirectory() { - return getDirectory(null, "Ok", "Ok"); - } - - /** - * @param title le nom de la boite de dialogue - * @param approvalText le texte de l'action d'acceptation du répertoire dans le file chooser - * @return le nom du repertoire entre dans la boite de dialogue. - * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne - * null. - */ - public static String getDirectory(String title, String approvalText) { - return getDirectory(null, title, approvalText); - } - - /** - * @param parent le component parent du dialog - * @param title le nom de la boite de dialogue - * @param approvalText le texte de l'action d'acceptation du répertoire dans le file chooser - * @return le nom du repertoire entre dans la boite de dialogue. - * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne - * null. - */ - public static String getDirectory(Component parent, - String title, - String approvalText) { - try { - JFileChooser chooser = new JFileChooser(currentDirectory); - chooser.setDialogType(JFileChooser.CUSTOM_DIALOG); - chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - chooser.setDialogTitle(title); - int returnVal = chooser.showDialog(parent, approvalText); - if (returnVal == JFileChooser.APPROVE_OPTION) { - File theFile = chooser.getSelectedFile(); - if (theFile != null) { - currentDirectory = theFile; - if (theFile.isDirectory()) { - return theFile.getAbsolutePath(); - } - } - } else { - return null; - } - } catch (Exception eee) { - log.warn("Erreur:", eee); - } - return null; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/JAXXAction.java b/jaxx-runtime/src/main/java/jaxx/runtime/JAXXAction.java deleted file mode 100644 index 61dbac2..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/JAXXAction.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime; - -import jaxx.runtime.context.JAXXInitialContext; - -/** - * This is the contract to be realized by any class to be used as Action class for an ui. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public interface JAXXAction { - - /** - * Prepare the initial context of the ui. - * - * @param parentContent the context of the parent of the ui (can be null if no parent is required) - * @param datas other datas to inject in initial context - * @return the {@link JAXXInitialContext} to be injected in the ui via the constructor of the {@link JAXXObject} - */ - JAXXInitialContext init(JAXXContext parentContent, Object... datas); - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/JAXXBinding.java b/jaxx-runtime/src/main/java/jaxx/runtime/JAXXBinding.java deleted file mode 100644 index aad6f19..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/JAXXBinding.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime; - -import java.beans.PropertyChangeListener; - -/** - * Created: 5 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - * - * Mise a jour: $Date$ par : - * $Author$ - */ -public interface JAXXBinding extends PropertyChangeListener { - /** @return the unique id of a binding */ - String getId(); - - /** @return the {@link JAXXObject} which owns the binding */ - JAXXObject getSource(); - - /** - * This state is not used actually, but will be usefull later... - * - * @return {@code true} if binding was registred as a default binding, {@code false} otherwise - */ - boolean isDefaultBinding(); - - /** Apply the binding without processing it (say just install listeners). */ - void applyDataBinding(); - - /** Processes the binding. */ - void processDataBinding(); - - /** Remove the binding. */ - void removeDataBinding(); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/JAXXContext.java b/jaxx-runtime/src/main/java/jaxx/runtime/JAXXContext.java deleted file mode 100644 index 7c397d3..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/JAXXContext.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime; - -/** - * The {@link jaxx.runtime.JAXXContext} contract defines a generic context. - * - * A context contains two king of entries : - * - * <h2>Unamed entry</h2> - * a such entry maps filter only on the clas of the object of the entry. - * - * To add a <b>unamed</b> entry, use {@link #setContextValue(Object)} and {@link #getContextValue(Class)} to reteave a - * such entry. - * - * <h2>named entry</h2> - * a such entry filter on class of the object and on the name of the entry. - * - * To add a <b>named</b> entry, use {@link #setContextValue(Object, String)} and {@link #getContextValue(Class, String)} - * to reteave a such entry. - * - * @author letellier - * @author Tony Chemit - chemit@codelutin.com - */ -public interface JAXXContext { - - /** - * Push in the context a new unamed entry. - * - * If a previous entry exists in context (unamed and same class), it will be removed. - * - * @param <T> type of data to set in context - * @param o the value to push in context - */ - <T> void setContextValue(T o); - - /** - * * Push in the context a new amed entry. - * - * If a previous entry exists in context (same name and class), it will be removed. - * - * @param <T> type of data to set in context - * @param o the value to push in context - * @param name the name of the new entry - */ - <T> void setContextValue(T o, String name); - - /** - * Remove from context the value with the given klazz as an unamed entry - * - * @param <T> type of data to remove from context - * @param klazz the klazz entry - */ - <T> void removeContextValue(Class<T> klazz); - - /** - * Remove from context the value with the given klazz as an unamed (if name is null) or named entry - * - * @param <T> type of data to remove from context - * @param klazz the klazz entry - * @param name extra name of the entry - */ - <T> void removeContextValue(Class<T> klazz, String name); - - /** - * Seek for a unamed entry in the context - * - * This is an exemple to call a method in JAXX : - * - * <code><JButton onActionPerformed='{getContextValue(Action.class).method(args[])}'/></code> - * - * @param <T> type of data to obtain from context - * @param clazz the class of unamed entry to seek in context - * @return the value of the unamed entry for the given class, or <code>null</code> if no such entry. - */ - <T> T getContextValue(Class<T> clazz); - - /** - * Seek for a named entry in the context - * - * @param <T> type of data to obtain from context - * @param clazz the class of named entry to seek in context - * @param name the name of the entry to seek in context - * @return the value of the named entry for the given class, or <code>null</code> if no such entry. - */ - <T> T getContextValue(Class<T> clazz, String name); - -// /** -// * Return parent's container corresponding to the Class clazz -// * -// * @param <O> type of container to obtain from context -// * @param clazz clazz desired -// * @return parent's container -// * @deprecated since 2.0.0 : breaks neutral since Swing -// */ -// @Deprecated -// public <O extends Container> O getParentContainer(Class<O> clazz); -// -// /** -// * Return parent's container corresponding to the Class clazz -// * -// * @param <O> type of container to obtain from context -// * @param top the top container -// * @param clazz desired -// * @return parent's container -// * @deprecated since 2.0.0 : breaks neutral since Swing -// */ -// @Deprecated -// public <O extends Container> O getParentContainer(Object top, Class<O> clazz); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/JAXXObject.java b/jaxx-runtime/src/main/java/jaxx/runtime/JAXXObject.java deleted file mode 100644 index 0e40984..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/JAXXObject.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime; - -import java.awt.Container; -import java.beans.PropertyChangeListener; -import java.io.Serializable; -import java.util.Map; - -/** - * The <code>JAXXObject</code> interface is implemented by all classes - * produced by the JAXX compiler. - */ -public interface JAXXObject extends JAXXContext, Serializable { - - /** - * Retrieves an object defined in an XML tag by its ID. - * - * @param id the id of the component to retrieve - * @return the object - */ - Object getObjectById(String id); - - /** - * Pretrieves the dictonary of knwon objects indexed by their ids. - * - * @return the dictonary of objects. - */ - Map<String, Object> get$objectMap(); - - /** @return the {@link JAXXContext} attached to the object */ - JAXXContext getDelegateContext(); - - /** @return all the databinding registred on the jaxx object */ - JAXXBinding[] getDataBindings(); - - /** - * Register a new binding in the jaxx object. - * - * @param binding the binding to add - */ - void registerDataBinding(JAXXBinding binding); - - /** - * Apply the data bind by name and then process it. - * - * @param id the id of the databinding - */ - void applyDataBinding(String id); - - /** - * Processes a data binding by name. Data binding names are comprised of an object ID and a property name: - * for example, the data binding in the tag <code><JLabel id='label' text='{foo.getText()}'/></code> is - * named <code>"label.text"</code>. Processing a data binding causes it to reevaluate its expression, in this - * case <code>foo.getText()</code>. - * - * @param dest the name of the data binding to run - */ - void processDataBinding(String dest); - - /** - * Processes a data binding by name. Data binding names are comprised of an object ID and a property name: - * for example, the data binding in the tag <code><JLabel id='label' text='{foo.getText()}'/></code> is - * named <code>"label.text"</code>. Processing a data binding causes it to reevaluate its expression, in this - * case <code>foo.getText()</code>. - * - * @param dest the name of the data binding to run - * @param force flag to force binding, even if already on run - */ - void processDataBinding(String dest, boolean force); - - /** - * Remove a databinding by name. - * - * @param id the name of databinding to remove - */ - void removeDataBinding(String id); - - /** - * Obtain a binding given his id. - * - * @param bindingId the id of the binding - * @return the binding, or {@code null} if not found. - * @see JAXXBinding - * @since 2.4.2 - */ - JAXXBinding getDataBinding(String bindingId); - - /** - * All <code>JAXXObject</code> implements are capable of broadcasting <code>PropertyChangeEvent</code>, and - * furthermore (for technical reasons) must allow code in outside packages, specifically the JAXX runtime, - * to trigger these events. - * - * @param name the name of the property which changed - * @param oldValue the old value of the property - * @param newValue the new value of the property - */ - void firePropertyChange(String name, Object oldValue, Object newValue); - - /** - * Register a general {@link PropertyChangeListener}. - * - * @param listener the listener to register - */ - void addPropertyChangeListener(PropertyChangeListener listener); - - /** - * Register a {@link PropertyChangeListener}. for the given {@code propertyName}. - * - * @param property the property name to listen - * @param listener the listener to register - */ - void addPropertyChangeListener(String property, PropertyChangeListener listener); - - /** - * Unregister a general {@link PropertyChangeListener}. - * - * @param listener the listener to unregister - */ - void removePropertyChangeListener(PropertyChangeListener listener); - - /** - * Unregister a {@link PropertyChangeListener}. for the given {@code propertyName}. - * - * @param property the property name to listen - * @param listener the listener to unregister - */ - void removePropertyChangeListener(String property, PropertyChangeListener listener); - - /** - * Return parent's container corresponding to the Class clazz - * - * @param <O> type of container to obtain from context - * @param clazz clazz desired - * @return parent's container - */ - <O extends Container> O getParentContainer(Class<O> clazz); - - /** - * Return parent's container corresponding to the Class clazz - * - * @param <O> type of container to obtain from context - * @param top the top container - * @param clazz desired - * @return parent's container - */ - <O extends Container> O getParentContainer(Object top, Class<O> clazz); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java b/jaxx-runtime/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java deleted file mode 100644 index bfe1655..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime; - -import jaxx.runtime.css.Stylesheet; - -import java.io.Serializable; - -public class JAXXObjectDescriptor implements Serializable { - private ComponentDescriptor[] descriptors; - - private Stylesheet stylesheet; - - private static final long serialVersionUID = 1L; - - - public JAXXObjectDescriptor(ComponentDescriptor[] descriptors, - Stylesheet stylesheet) { - this.descriptors = descriptors; - this.stylesheet = stylesheet; - } - - - public ComponentDescriptor[] getComponentDescriptors() { - return descriptors; - } - - - public Stylesheet getStylesheet() { - return stylesheet; - } - - @Override - public String toString() { - StringBuilder buffer = new StringBuilder(); - for (ComponentDescriptor descriptor : descriptors) { - buffer.append("\n").append(descriptor); - } - buffer.append("\n").append(stylesheet); - return buffer.toString(); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/JAXXUtil.java b/jaxx-runtime/src/main/java/jaxx/runtime/JAXXUtil.java deleted file mode 100644 index 926ac37..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/JAXXUtil.java +++ /dev/null @@ -1,664 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime; - -import jaxx.runtime.context.JAXXContextEntryDef; -import jaxx.runtime.context.JAXXInitialContext; -import org.apache.commons.beanutils.ConstructorUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.awt.Component; -import java.awt.Toolkit; -import java.awt.datatransfer.Clipboard; -import java.awt.datatransfer.StringSelection; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeListenerProxy; -import java.beans.PropertyChangeSupport; -import java.io.IOException; -import java.lang.ref.WeakReference; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EventListener; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; - -public class JAXXUtil { - - /** Logger */ - static private final Log log = LogFactory.getLog(JAXXUtil.class); - - public static final String PARENT = "parent"; - - // Maps root objects to lists of event listeners - - private static Map<Object, WeakReference<List<EventListenerDescriptor>>> - eventListeners = new WeakHashMap<Object, WeakReference<List<EventListenerDescriptor>>>(); - - private static Map<JAXXObject, WeakReference<List<DataBindingUpdateListener>>> - dataBindingUpdateListeners = new WeakHashMap<JAXXObject, WeakReference<List<DataBindingUpdateListener>>>(); - - private static final PropertyChangeListener[] EMPTY_ARRAY_PROPERTY_CHANGE_LISTENERS = new PropertyChangeListener[0]; - - private static class EventListenerDescriptor { - - Class<?> listenerClass; - - String listenerMethodName; - - String methodName; - - Object eventListener; - } - - /** - * Decodes the serialized representation of a JAXXObjectDescriptor. The - * string must be a byte-to-character mapping of the binary serialization - * data for a JAXXObjectDescriptor. See the comments in - * JAXXCompiler.createJAXXObjectDescriptorField for the rationale behind - * this (admittedly ugly) approach. - * - * @param descriptor descriptor to decode - * @return the dedoced descriptor - */ - public static JAXXObjectDescriptor decodeJAXXObjectDescriptor( - String descriptor) { - try { - return (JAXXObjectDescriptor) Base64Coder.deserialize(descriptor, - false); - } catch (IOException e) { - throw new RuntimeException("Internal error: can't-happen error", e); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Internal error: can't-happen error", e); - } - } - - public static JAXXObjectDescriptor decodeCompressedJAXXObjectDescriptor( - String descriptor) { - try { - return (JAXXObjectDescriptor) Base64Coder.deserialize(descriptor, - true); - } catch (IOException e) { - throw new RuntimeException("Internal error: can't-happen error", e); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Internal error: can't-happen error", e); - } - } - - public static <O> JAXXContextEntryDef<O> newContextEntryDef( - Class<O> klass) { - return newContextEntryDef(null, klass); - } - - public static <O> JAXXContextEntryDef<O> newContextEntryDef( - String name, Class<?> klass) { - return new JAXXContextEntryDef<O>(name, (Class<O>) klass); - } - - public static <O> JAXXContextEntryDef<List<O>> newListContextEntryDef() { - return newListContextEntryDef(null); - } - - public static <O> JAXXContextEntryDef<List<O>> newListContextEntryDef( - String name) { - Class<List<O>> castList = castList(); - return new JAXXContextEntryDef<List<O>>(name, castList); - } - - public static <K, V> JAXXContextEntryDef<Map<K, V>> newMapContextEntryDef( - String name) { - return new JAXXContextEntryDef<Map<K, V>>(Map.class, name); - } - - @SuppressWarnings({"unchecked"}) - protected static <K, V> Class<Map<K, V>> castMap() { - return (Class<Map<K, V>>) Collections.emptyMap().getClass(); - } - - @SuppressWarnings({"unchecked"}) - protected static <O> Class<List<O>> castList() { - return (Class<List<O>>) Collections.emptyList().getClass(); - } - - /** - * Method to initialize the context of a ui. - * - * @param ui the ui - * @param parentContext the context to set in ui - */ - public static void initContext(JAXXObject ui, JAXXContext parentContext) { - - if (parentContext instanceof JAXXInitialContext) { - ((JAXXInitialContext) parentContext).to(ui); - } else { - ui.setContextValue(parentContext); - } - // if parentContext is a JAXXObject then - // add an special parent entry to can go up - if (parentContext instanceof JAXXObject) { - ui.setContextValue(parentContext, PARENT); - } - } - - public static <E extends EventListener> E getEventListener( - Class<E> listenerClass, - final String listenerMethodName, - final Object methodContainer, - String methodName) { - - WeakReference<List<EventListenerDescriptor>> ref = - eventListeners.get(methodContainer); - List<EventListenerDescriptor> descriptors = ref != null ? - ref.get() : null; - if (descriptors == null) { - descriptors = new ArrayList<EventListenerDescriptor>(); - eventListeners.put( - methodContainer, - new WeakReference<List<EventListenerDescriptor>>( - descriptors)); - } else { - for (EventListenerDescriptor descriptor : descriptors) { - if (descriptor.listenerClass.equals(listenerClass) && - (listenerMethodName == null ? - descriptor.listenerMethodName == null : - listenerMethodName.equals( - descriptor.listenerMethodName)) && - methodName.equals(descriptor.methodName)) { - return (E) descriptor.eventListener; - } - } - } - - // else we need to create a new listener - final EventListenerDescriptor descriptor = new EventListenerDescriptor(); - descriptor.listenerClass = listenerClass; - descriptor.listenerMethodName = listenerMethodName; - descriptor.methodName = methodName; - try { - final List<Method> listenerMethods = - Arrays.asList(listenerClass.getMethods()); - Method listenerMethod = null; - if (listenerMethodName != null) { - for (Method listenerMethod1 : listenerMethods) { - if (listenerMethod1.getName().equals(listenerMethodName)) { - listenerMethod = listenerMethod1; - break; - } - } - } - if (listenerMethodName != null && listenerMethod == null) { - throw new IllegalArgumentException( - "no method named " + listenerMethodName + - " found in class " + listenerClass.getName()); - } - // tchemit 2010-12-01 : we must the exact method found, some none javaBeans - // api does use different signature for some of them listener - // an exemple is the TableColumnModelListener : http://download.oracle.com/javase/6/docs/api/javax/swing/event/TableColumnMo... - // This fix the bug https://forge.nuiton.org/issues/show/1124 - Class<?>[] parameterTypes; - if (listenerMethodName != null) { - - // search an exact method, so must use the exact found listener method - parameterTypes = listenerMethod.getParameterTypes(); - } else { - - // keep this horrible code which is not safe at all : - // see previous comment - parameterTypes = listenerMethods.get(0).getParameterTypes(); - } - Class<?> methodContainerClass = methodContainer.getClass(); - final Method targetMethod = - methodContainerClass.getMethod(methodName, parameterTypes); - descriptor.eventListener = - Proxy.newProxyInstance(listenerClass.getClassLoader(), - new Class<?>[]{listenerClass}, - new InvocationHandler() { - - @Override - public Object invoke(Object proxy, - Method method, - Object[] args) { - String methodName = method.getName(); - if (listenerMethodName == null && - listenerMethods.contains(method) || - methodName.equals(listenerMethodName)) { - try { - targetMethod.setAccessible(true); - return targetMethod.invoke( - methodContainer, args); - } catch (IllegalAccessException e) { - throw new RuntimeException( - "could not invoke on container " + - methodContainer, e); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - } - if (methodName.equals("toString")) { - return toString(); - } - if (methodName.equals("equals")) { - return descriptor.eventListener == args[0]; - } - if (methodName.equals("hashCode")) { - return hashCode(); - } - return null; - } - }); - descriptors.add(descriptor); - return (E) descriptor.eventListener; - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - - public static <E extends EventListener> E getEventListener( - Class<E> listenerClass, - Object methodContainer, - String methodName) { - return getEventListener(listenerClass, null, methodContainer, - methodName); - } - - public static DataBindingUpdateListener getDataBindingUpdateListener( - JAXXObject object, String bindingName) { - WeakReference<List<DataBindingUpdateListener>> ref = - dataBindingUpdateListeners.get(object); - List<DataBindingUpdateListener> listeners = ref == null ? null : - ref.get(); - if (listeners == null) { - listeners = new ArrayList<DataBindingUpdateListener>(); - dataBindingUpdateListeners.put( - object, - new WeakReference<List<DataBindingUpdateListener>>( - listeners)); - } else { - for (DataBindingUpdateListener listener : listeners) { - if (bindingName.equals(listener.getBindingName())) { - return listener; - } - } - } - DataBindingUpdateListener listener = - new DataBindingUpdateListener(object, bindingName); - listeners.add(listener); - return listener; - } - - /** - * Remove all listeners registred in given {@code pcs}. - * - * @param pcs the pcs to clean - */ - public static void destroy(PropertyChangeSupport pcs) { - PropertyChangeListener[] listeners = pcs.getPropertyChangeListeners(); - for (PropertyChangeListener l : listeners) { - if (log.isInfoEnabled()) { - if (l instanceof PropertyChangeListenerProxy) { - PropertyChangeListenerProxy ll = (PropertyChangeListenerProxy) l; - log.info("remove property change listener " + ll.getPropertyName() + " : " + l); - } else { - log.info("remove property change listener " + l); - } - } - pcs.removePropertyChangeListener(l); - } - } - - /** - * Remove all listeners registred in given {@code component}. - * - * @param component the pcs to clean - */ - public static void destroy(Component component) { - PropertyChangeListener[] listeners = component.getPropertyChangeListeners(); - for (PropertyChangeListener l : listeners) { - if (log.isInfoEnabled()) { - if (l instanceof PropertyChangeListenerProxy) { - PropertyChangeListenerProxy ll = (PropertyChangeListenerProxy) l; - log.info("remove property change listener " + ll.getPropertyName() + " : " + l); - } else { - log.info("remove property change listener " + l); - } - } - component.removePropertyChangeListener(l); - } - } - - /** @deprecated since 2.4.2, never use, will not be replaced */ - @Deprecated - public static boolean assignment(boolean value, - String name, - JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - /** @deprecated since 2.4.2, never use, will not be replaced */ - @Deprecated - - public static byte assignment(byte value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - /** @deprecated since 2.4.2, never use, will not be replaced */ - @Deprecated - public static short assignment(short value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - /** @deprecated since 2.4.2, never use, will not be replaced */ - @Deprecated - public static int assignment(int value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - /** @deprecated since 2.4.2, never use, will not be replaced */ - @Deprecated - public static long assignment(long value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - /** @deprecated since 2.4.2, never use, will not be replaced */ - @Deprecated - public static float assignment(float value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - /** @deprecated since 2.4.2, never use, will not be replaced */ - @Deprecated - public static double assignment(double value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - /** @deprecated since 2.4.2, never use, will not be replaced */ - @Deprecated - public static char assignment(char value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - /** @deprecated since 2.4.2, never use, will not be replaced */ - @Deprecated - public static Object assignment(Object value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - /** - * Compute the string representation of an object. - * - * Return empty string if given object is null - * - * @param value the value to write - * @return the string representation of the given object or an empty string - * if object is null. - */ - public static String getStringValue(Object value) { - String result; - result = value == null ? "" : value.toString(); - return result; - } - - /** - * Test if some entries exists in a given context and throw an - * IllegalArgumentException if not. - * - * - * @param context the context to test - * @param defs the definitions of entries to seek in context - * @throws IllegalArgumentException if the entry is not found in context. - */ - public static void checkJAXXContextEntries(JAXXContext context, - JAXXContextEntryDef<?>... defs) - throws IllegalArgumentException { - - for (JAXXContextEntryDef<?> def : defs) { - Object value = def.getContextValue(context); - - if (value == null) { - throw new IllegalArgumentException( - "the context entry [" + def + "] ] was not found in " + - "context " + context); - } - } - } - - /** - * Test if a type of entry exists in a given context and throw an - * IllegalArgumentException if not found. - * - * If entry is found, return his value in context. - * - * @param <T> the type of required data - * @param context the context to test - * @param def the definition of the entry to seek in context - * @return the value from the context - * @throws IllegalArgumentException if the entry is not found in context. - */ - public static <T> T checkJAXXContextEntry(JAXXContext context, - JAXXContextEntryDef<T> def) - throws IllegalArgumentException { - - T value = def.getContextValue(context); - - if (value == null) { - throw new IllegalArgumentException( - "the context entry [" + def + "] ] was not found in " + - "context " + context); - } - - return value; - } - - /** - * To reload a binding, the method will invoke - * <ul> - * <li>{@link JAXXBinding#removeDataBinding()}</li> - * <li>{@link JAXXBinding#applyDataBinding()}</li> - * </ul> - * - * @param binding the binding to reload. - * @since 2.4.2 - */ - public static void reloadBinding(JAXXBinding binding) { - binding.removeDataBinding(); - binding.applyDataBinding(); - } - - /** - * Convinient method to reload a given binding by his id on a JAXX ui. - * - * @param src the ui to treate - * @param bindingId the id of binding to reload. - * @since 2.4.2 - */ - public static void reloadBinding(JAXXObject src, String bindingId) { - JAXXBinding dataBinding = src.getDataBinding(bindingId); - if (dataBinding != null) { - reloadBinding(dataBinding); - } else { - if (log.isWarnEnabled()) { - log.warn("Could not found binding[" + bindingId + "] on ui " + src); - } - } - } - - /** - * Convinient method to apply more than one binding on a JAXX ui. - * - * @param src the ui to treate - * @param bindings the list of binding to process. - */ - public static void applyDataBinding(JAXXObject src, String... bindings) { - for (String binding : bindings) { - src.applyDataBinding(binding); - } - } - - /** - * Convinient method to apply more than one binding on a JAXX ui. - * - * @param src the ui to treate - * @param bindings the list of binding to process. - */ - public static void applyDataBinding(JAXXObject src, - Collection<String> bindings) { - for (String binding : bindings) { - src.applyDataBinding(binding); - } - } - - /** - * Convinient method to process more than one binding on a JAXX ui. - * - * @param src the ui to treate - * @param bindings the list of binding to process. - */ - public static void processDataBinding(JAXXObject src, String... bindings) { - for (String binding : bindings) { - src.processDataBinding(binding); - } - } - - /** - * Convinient method to remove more than one binding on a JAXX ui. - * - * @param src the ui to treate - * @param bindings the list of binding to process. - */ - public static void removeDataBinding(JAXXObject src, String... bindings) { - for (String binding : bindings) { - src.removeDataBinding(binding); - } - } - - /** - * Convinient method to remove all than one binding on a JAXX ui. - * - * @param src the ui to treate - * @since 2.10 - */ - public static void removeAllDataBindings(JAXXObject src) { - - JAXXBinding[] bindings = src.getDataBindings(); - for (JAXXBinding binding : bindings) { - removeDataBinding(src, binding.getId()); - } - - } - - /** - * detects all PropertychangedListener added by Jaxx uis (should be a {@link - * DataBindingListener} - * - * @param propertyNames the array of property names to find - * @param listeners the array of listeners to filter - * @return the filtered listeners - */ - public static PropertyChangeListener[] findJaxxPropertyChangeListener( - String[] propertyNames, PropertyChangeListener... listeners) { - if (listeners == null || listeners.length == 0) { - return EMPTY_ARRAY_PROPERTY_CHANGE_LISTENERS; - } - List<String> pNames = Arrays.asList(propertyNames); - - List<PropertyChangeListener> toRemove = - new ArrayList<PropertyChangeListener>(); - - for (PropertyChangeListener listener : listeners) { - String pName = null; - PropertyChangeListenerProxy plistener = null; - if (listener instanceof PropertyChangeListenerProxy) { - plistener = (PropertyChangeListenerProxy) listener; - if (!pNames.contains(plistener.getPropertyName())) { - // not on the good property - continue; - } - listener = (PropertyChangeListener) plistener.getListener(); - pName = plistener.getPropertyName(); - } - if (plistener != null && - pName != null && - listener instanceof DataBindingListener) { - if (log.isDebugEnabled()) { - log.debug("find config listener to remove [" + pName + - "] : " + listener); - } - toRemove.add(plistener); - //toRemove.add(listener); - } - } - return toRemove.toArray(new PropertyChangeListener[toRemove.size()]); - } - - /** - * Overrides the commons method to have generict cast fiex. - * - * @param type the type of objet to instanciate - * @param prototype prototype of the constructor - * @param parms params to pass to constructor - * @param <O> type of object to create - * @return the new object - * @throws Exception if something wrong - * @since 2.1 - */ - @SuppressWarnings({"unchecked"}) - public static <O> O invokeConstructor(Class<O> type, - Class<?>[] prototype, - Object... parms) throws Exception { - return (O) ConstructorUtils.invokeConstructor(type, - parms, - prototype - ); - } - - /** - * Copy to clipBoard the content of the given text. - * - * @param text text to copy to clipboard - * @since 2.17 - */ - public static void copyToClipBoard(String text) { - - Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - if (log.isInfoEnabled()) { - log.info("Put in clipboard :\n" + text); - } - StringSelection selection = new StringSelection(text); - clipboard.setContents(selection, selection); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/SwingUtil.java b/jaxx-runtime/src/main/java/jaxx/runtime/SwingUtil.java deleted file mode 100644 index 4fd2900..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/SwingUtil.java +++ /dev/null @@ -1,1531 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime; - -import com.google.common.base.Predicate; -import jaxx.runtime.swing.Item; -import jaxx.runtime.swing.JAXXComboBox; -import jaxx.runtime.swing.editor.BooleanCellEditor; -import jaxx.runtime.swing.model.JaxxDefaultComboBoxModel; -import jaxx.runtime.swing.model.JaxxDefaultListModel; -import jaxx.runtime.swing.renderer.BooleanCellRenderer; -import jaxx.runtime.swing.renderer.EmptyNumberTableCellRenderer; -import jaxx.runtime.swing.renderer.EnumTableCellRenderer; -import jaxx.runtime.swing.renderer.I18nTableCellRenderer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.jxlayer.JXLayer; -import org.jdesktop.jxlayer.plaf.LayerUI; -import org.jdesktop.swingx.JXTreeTable; - -import javax.swing.ComboBoxModel; -import javax.swing.DefaultComboBoxModel; -import javax.swing.DefaultListModel; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JLayeredPane; -import javax.swing.JList; -import javax.swing.JRootPane; -import javax.swing.JTabbedPane; -import javax.swing.JTable; -import javax.swing.JTree; -import javax.swing.ListModel; -import javax.swing.ListSelectionModel; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; -import javax.swing.table.TableModel; -import javax.swing.text.AbstractDocument; -import javax.swing.text.JTextComponent; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.Desktop; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Rectangle; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Field; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.EventObject; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; -import java.util.Properties; - -import static org.nuiton.i18n.I18n.t; - -/** - * The runtime swing util class with some nice stuff. - * - * Note : Replace previous class jaxx.runtime.swing.Utils in previous versions. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.2 - */ -public class SwingUtil extends JAXXUtil { - - /** Logger */ - static private final Log log = LogFactory.getLog(SwingUtil.class); - - public static final String DEFAULT_ICON_PATH = "/icons/"; - - public static final String DEFAULT_ICON_PATH_PROPERTY = "default.icon.path"; - - private static Field numReaders; - - private static Field notifyingListeners; - - public static final String ICON_PREFIX = "icon."; - - public static final String COLOR_PREFIX = "color."; - - public static Dimension newMinDimension() { - return new Dimension(0, 0); - } - - public static Dimension newMaxXDimension() { - return new Dimension(Short.MAX_VALUE, 0); - } - - public static Dimension newMaxYDimension() { - return new Dimension(0, Short.MAX_VALUE); - } - - public static Dimension newMaxXYDimension() { - return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); - } - - public static void setText(final JTextComponent c, final String text) { - try { - // AbstractDocument deadlocks if we try to acquire a write lock while a read lock is held by the current thread - // If there are any readers, dispatch an invokeLater. This should only happen in the event of circular bindings. - // Similarly, circular bindings can result in an "Attempt to mutate in notification" error, which we deal with - // by checking for the 'notifyingListeners' property. - AbstractDocument document = (AbstractDocument) c.getDocument(); - if (numReaders == null) { - numReaders = AbstractDocument.class.getDeclaredField("numReaders"); - numReaders.setAccessible(true); - } - if (notifyingListeners == null) { - notifyingListeners = AbstractDocument.class.getDeclaredField("notifyingListeners"); - notifyingListeners.setAccessible(true); - } - - if (notifyingListeners.get(document).equals(Boolean.TRUE)) { - return; - } - - if ((Integer) numReaders.get(document) > 0) { - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - if (!c.getText().equals(text)) { - c.setText(text); - } - } - }); - return; - } - - String oldText = c.getText(); - if (oldText == null || !oldText.equals(text)) { - c.setText(text); - } - } catch (NoSuchFieldException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } catch (SecurityException e) { - c.setText(text); - } - } - - /** - * Fill a combo box model with some datas, and select after all the given object - * - * @param combo the combo to fill - * @param data data ot inject in combo - * @param select the object to select in combo after reflling his model - */ - public static void fillComboBox(JComboBox combo, Collection<?> data, - Object select) { - - ComboBoxModel comboBoxModel = combo.getModel(); - - if (comboBoxModel instanceof JaxxDefaultComboBoxModel) { - JaxxDefaultComboBoxModel model = - (JaxxDefaultComboBoxModel) comboBoxModel; - - // evince the model - model.removeListDataListener(combo); - - // set data - model.setAllElements((Collection) data); - - // attach the model - model.addListDataListener(combo); - model.setSelectedItem(select); - } else if (comboBoxModel instanceof DefaultComboBoxModel) { - DefaultComboBoxModel model = (DefaultComboBoxModel) combo.getModel(); - // evince the model - model.removeListDataListener(combo); - model.removeAllElements(); - if (data != null) { - for (Object o : data) { - model.addElement(o); - } - } - // attach the model - model.addListDataListener(combo); - model.setSelectedItem(select); - } else { - throw new IllegalArgumentException( - "this method need a DefaultComboBoxModel for " + - "this model but was " + combo.getModel().getClass()); - } - - } - - /** - * Fill a list model with some datas, and select after all the given object - * - * @param list the list to fill - * @param data data ot inject in combo - * @param select the object to select in combo after reflling his model - */ - public static void fillList(JList list, Collection<?> data, Object select) { - ListModel listModel = list.getModel(); - if (listModel instanceof JaxxDefaultListModel) { - JaxxDefaultListModel model = (JaxxDefaultListModel) listModel; - - // evince the model -// model.removeListDataListener(combo); - model.setAllElements(data); - - // attach the model -// model.addListDataListener(combo); - list.setSelectedValue(select, true); - } else if (listModel instanceof DefaultListModel) { - DefaultListModel model = (DefaultListModel) listModel; - // evince the model -// model.removeListDataListener(combo); - model.removeAllElements(); - if (data != null) { - for (Object o : data) { - model.addElement(o); - } - } - // attach the model -// model.addListDataListener(combo); - list.setSelectedValue(select, true); - } else { - throw new IllegalArgumentException( - "this method need a DefaultListModel for this model " + - "but was " + listModel.getClass()); - } - } - - /** - * TODO move this to JAXXComboBox. - * - * Fill a combo box model with some datas, and select after all the given object - * - * @param combo the combo to fill - * @param data data ot inject in combo - * @param select the object to select in combo after reflling his model - * @param firstNull add a first null element - * @deprecated since 1.7.XXX this code is moved to JAXXComboBox - */ - @Deprecated - public static void fillComboBox(JAXXComboBox combo, - Collection<?> data, - Object select, boolean firstNull) { - List<Item> items = new ArrayList<Item>(); - if (firstNull) { - items.add(new Item("null", " ", null, false)); - } - if (data != null) { - for (Object d : data) { - Item item = new Item(d.toString(), d.toString(), d, - d.equals(select)); - items.add(item); - } - } - combo.setItems(items); - } - - /** - * Return parent's container corresponding to the Class clazz - * - * @param <O> type of container to obtain from context - * @param top the top container - * @param clazz desired - * @return parent's container - */ - @SuppressWarnings({"unchecked"}) - public static <O extends Container> O getParentContainer(Object top, - Class<O> clazz) { - - return getParent(top, clazz); - } - - - /** - * Find a parent of the given {@code top} object using the container api to get up. - * - * Stop on parent when it is of the given{@code clazz} type. - * - * @param <O> type of container to obtain from context - * @param top the top container - * @param clazz desired - * @return parent's container - * @since 2.5.14 - */ - public static <O> O getParent(Object top, Class<O> clazz) { - if (top == null) { - throw new IllegalArgumentException("top parameter can not be null"); - } - if (!Container.class.isAssignableFrom(top.getClass())) { - throw new IllegalArgumentException("top parameter " + top + - " is not a " + Container.class); - } - Container parent = ((Container) top).getParent(); - if (parent != null && !clazz.isAssignableFrom(parent.getClass())) { - parent = (Container) getParent(parent, clazz); - } - return (O) parent; - } - - public static int computeTableColumnWidth(JTable table, - Font font, - int columnIndex, String suffix) { - int width = 0; - if (font == null) { - font = table.getFont(); - } -// if (font == null) { -// TableColumn column = table.getColumnModel().getColumn(columnIndex); -// font = ((JComponent) column.getCellRenderer()).getFont(); -// } - FontMetrics fontMetrics = table.getFontMetrics(font); - for (int i = 0, rowCount = table.getRowCount(); i < rowCount; i++) { - String key = (String) table.getModel().getValueAt(i, 0); - int w = fontMetrics.stringWidth(key + suffix); - if (w > width) { - width = w; - } - } - return width; - } - - public static void fixTableColumnWidth(JTable table, - int columnIndex, - int width) { - TableColumn column = table.getColumnModel().getColumn(columnIndex); - column.setMaxWidth(width); - column.setMinWidth(width); - column.setWidth(width); - column.setPreferredWidth(width); - } - - public static void setTableColumnEditor(JTable table, - int columnIndex, - TableCellEditor editor) { - TableColumn column = table.getColumnModel().getColumn(columnIndex); - column.setCellEditor(editor); - } - - public static void setTableColumnRenderer(JTable table, - int columnIndex, - TableCellRenderer editor) { - TableColumn column = table.getColumnModel().getColumn(columnIndex); - column.setCellRenderer(editor); - } - - public static void setI18nTableHeaderRenderer(JTable table, - String... libelles) { - I18nTableCellRenderer defaultRenderer = - new I18nTableCellRenderer( - table.getTableHeader().getDefaultRenderer(), libelles); - table.getTableHeader().setDefaultRenderer(defaultRenderer); - } - - public static TableCellRenderer newStringTableCellRenderer( - final DefaultTableCellRenderer renderer, - final int length, - final boolean tooltip) { - - return new DefaultTableCellRenderer() { - - private static final long serialVersionUID = 1l; - - @Override - public Component getTableCellRendererComponent( - JTable table, - Object value, - boolean isSelected, - boolean hasFocus, - int row, - int column) { - - renderer.getTableCellRendererComponent( - table, - value, - isSelected, - hasFocus, - row, - column - ); - String val = renderer.getText(); - String val2 = val; - if (val.length() > length) { - val2 = val.substring(0, length - 3) + "..."; - } - - JComponent comp = (JComponent) - super.getTableCellRendererComponent( - table, - val2, - isSelected, - hasFocus, - row, - column - ); - if (tooltip) { - comp.setToolTipText(val); - } - return comp; - } - }; - } - - /** - * Box a component in a {@link JXLayer}. - * - * @param component the component to box - * @return the {@link JXLayer} boxing the component - */ - public static <V extends JComponent> JXLayer<V> boxComponentWithJxLayer(V component) { - JXLayer<V> layer = getLayer(component); - if (layer != null) { - return layer; - } - layer = new JXLayer<V>(); - layer.setView(component); - return layer; - } - - public static List<JComponent> getLayeredComponents(JAXXObject object) { - List<JComponent> result = new ArrayList<JComponent>(); - for (Entry<String, Object> child : object.get$objectMap().entrySet()) { - if (child.getValue() == null) { - log.warn("find a null object in $objectMap " + child.getKey()); - continue; - } - if (JComponent.class.isAssignableFrom(child.getValue().getClass())) { - JComponent comp = (JComponent) child.getValue(); - if (isLayered(comp)) { - result.add(comp); - } - } - } - return result; - } - - public static <V extends JComponent> JXLayer<V> getLayer(V comp) { - if (!isLayered(comp)) { - return null; - } - return (JXLayer<V>) comp.getParent(); - } - - public static void setLayerUI(JComponent comp, LayerUI<JComponent> ui) { - JXLayer<JComponent> layer = getLayer(comp); - layer.setUI(ui); - } - - public static boolean isLayered(JComponent comp) { - Container parent = comp.getParent(); - return parent != null && parent instanceof JXLayer<?>; - } - - /** - * recherche les composants portant le meme nom que les champs de la classe - * clazz. Cette methode est statique pour pouvoir eventuellement l'utiliser - * dans un autre context (je pense par exemple a la generation jaxx). - * - * Si la recherche echoue pour quelque raison que se soit, aucune exception - * n'est leve, et la map retournee est tout simplement vide ou incomplete - * - * @param clazz la classe ou recherche les champs - * @param container le container ou rechercher les composants d'edition - * @return le dictionnaire des composants recherches. - */ - public static Map<String, JComponent> lookingForEditor( - Class<?> clazz, - Container container) { - Map<String, JComponent> result = new HashMap<String, JComponent>(); - try { - // looking for all component with name set - Map<String, JComponent> allNamedComponent = - new HashMap<String, JComponent>(); - List<Container> todo = new LinkedList<Container>(); - todo.add(container); - while (todo.size() > 0) { - for (ListIterator<Container> i = todo.listIterator(); - i.hasNext(); ) { - Container parent = i.next(); - i.remove(); - for (Component c : parent.getComponents()) { - if (c instanceof Container) { - i.add((Container) c); - String name = c.getName(); - if (c instanceof JComponent && - name != null && !"".equals(name)) { - allNamedComponent.put(name, (JComponent) c); - } - } - } - } - } - - // looking for all properties on class - BeanInfo info = Introspector.getBeanInfo(clazz); - PropertyDescriptor[] props = info.getPropertyDescriptors(); - - // find if one properties have same name that component - for (PropertyDescriptor prop : props) { - String name = prop.getName(); - if (allNamedComponent.containsKey(name)) { - result.put(name, allNamedComponent.get(name)); - } - } - - } catch (IntrospectionException eee) { - log.warn("Can't introspect bean", eee); - } - - if (log.isDebugEnabled()) { - log.debug("Result: " + result); - } - - return result; - } - - /** - * Centrer un component graphique au center d'un autre component. - * - * <b>Note:</b> si le parent est null, alors on ne fait rien. - * - * @param parent le component parent - * @param component le component à centrer - */ - public static void center(Component parent, Component component) { - if (parent == null) { - return; - } - Rectangle r = parent.getBounds(); - int x = r.x + (r.width - component.getSize().width) / 2; - int y = r.y + (r.height - component.getSize().height) / 2; - component.setLocation(x, y); - } - - /** - * Try to load the Nimbus look and feel. - * - * @throws UnsupportedLookAndFeelException if nimbus is not applicable - * @throws ClassNotFoundException - * @throws InstantiationException - * @throws IllegalAccessException - */ - public static void initNimbusLoookAndFeel() throws UnsupportedLookAndFeelException, ClassNotFoundException, InstantiationException, IllegalAccessException { - - for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { - if ("Nimbus".equals(laf.getName())) { - UIManager.setLookAndFeel(laf.getClassName()); - } - } - } - - /** - * Load the ui.properties file and set in {@link UIManager} colors and - * icons found. - * - * @param defaultUIConfig le path vers le fichier de la config d'ui par - * défaut (doit etre dansle class-path) - * @param extraUIConfig le path vers une surcharge de la config d'ui - * (doit etre dans le class-path) - * @throws IOException if could not load the ui.properties file - */ - public static void loadUIConfig(String defaultUIConfig, - String extraUIConfig) throws IOException { - - Properties p = new Properties(); - log.info("loading default UI config " + defaultUIConfig); - p.load(SwingUtil.class.getResourceAsStream(defaultUIConfig)); - if (log.isDebugEnabled()) { - log.debug(p.toString()); - } - if (extraUIConfig != null) { - InputStream extraStream = - SwingUtil.class.getResourceAsStream(extraUIConfig); - if (extraStream == null) { - log.warn("could not find extraUIConfig : " + extraUIConfig); - } else { - log.info("loading extra UI config " + extraUIConfig); - Properties p2 = new Properties(p); - p2.load(extraStream); - if (log.isDebugEnabled()) { - log.debug(p2.toString()); - } - p.putAll(p2); - } - } - for (Entry<Object, Object> entry : p.entrySet()) { - String key = (String) entry.getKey(); - if (key.startsWith(ICON_PREFIX)) { - ImageIcon icon; - try { - icon = createImageIcon((String) entry.getValue()); - UIManager.put(key.substring(ICON_PREFIX.length()), icon); - } catch (Exception e) { - log.warn("could not load icon " + entry.getValue()); - } - continue; - } - if (key.startsWith(COLOR_PREFIX)) { - String value = (String) entry.getValue(); - String[] rgb = value.split(","); - UIManager.put( - key.substring(COLOR_PREFIX.length()), - new Color( - Integer.valueOf(rgb[0]), - Integer.valueOf(rgb[1]), - Integer.valueOf(rgb[2]) - ) - ); - } - } - } - - /** - * Load the ui.properties file and set in {@link UIManager} colors and - * icons found. - * - * @param incoming the ui resources to load. - * @since 2.1 - */ - public static void loadUIConfig(Properties incoming) { - - for (Entry<Object, Object> entry : incoming.entrySet()) { - String key = (String) entry.getKey(); - if (key.startsWith(ICON_PREFIX)) { - ImageIcon icon; - try { - icon = createImageIcon((String) entry.getValue()); - UIManager.put(key.substring(ICON_PREFIX.length()), icon); - } catch (Exception e) { - log.warn("could not load icon " + entry.getValue()); - } - continue; - } - if (key.startsWith(COLOR_PREFIX)) { - String value = (String) entry.getValue(); - String[] rgb = value.split(","); - UIManager.put( - key.substring(COLOR_PREFIX.length()), - new Color( - Integer.valueOf(rgb[0]), - Integer.valueOf(rgb[1]), - Integer.valueOf(rgb[2]) - ) - ); - } - } - } - - /** - * Iterate the components of a {@link JTabbedPane} in natural order. - * - * Says using method {@link JTabbedPane#getComponent(int)} - * - * @param tabs the - * @return the iterator - * @since 1.4 - */ - public static TabbedPaneIterator<Component> newTabbedPaneIterator( - JTabbedPane tabs) { - return new TabbedPaneIterator<Component>(false, tabs) { - - @Override - protected Component get(int index, Component comp) { - return comp; - } - }; - } - - /** - * Return the selected rows of the table in the model coordinate or empty - * array if selection is empty. - * - * @param table the table to seek - * @return the selected rows of the table in the model coordinate or empty - * array if selection is empty. - * @since 2.5.29 - */ - public static int[] getSelectedModelRows(JTable table) { - int[] selectedRows = table.getSelectedRows(); - int length = selectedRows.length; - int[] result = new int[length]; - for (int i = 0; i < length; i++) { - int selectedRow = selectedRows[i]; - result[i] = table.convertRowIndexToModel(selectedRow); - } - return result; - } - - /** - * Return the selected row of the table in the model coordinate or - * {@code -1} if selection is empty. - * - * @param table the table to seek - * @return the selected row of the table in the model coordinate or - * {@code -1} if selection is empty. - * @since 2.5.29 - */ - public static int getSelectedModelRow(JTable table) { - int result = table.getSelectedRow(); - if (result != -1) { - // can convert to model coordinate - result = table.convertRowIndexToModel(result); - } - return result; - } - - /** - * Return the selected column of the table in the model coordinate or - * {@code -1} if selection is empty. - * - * @param table the table to seek - * @return the selected column of the table in the model coordinate or - * {@code -1} if selection is empty. - * @since 2.5.29 - */ - public static int getSelectedModelColumn(JTable table) { - int result = table.getSelectedColumn(); - if (result != -1) { - // can convert to model coordinate - result = table.convertColumnIndexToModel(result); - } - return result; - } - - /** - * Select the given row index {@code rowIndex} (from the model coordinate) - * in the selection of the given table. - * - * @param table the table where to set the selection - * @param rowIndex the row index in the model coordinate to set as selection - * @since 2.5.29 - */ - public static void setSelectionInterval(JTable table, int rowIndex) { - - int rowViewIndex = table.convertRowIndexToView(rowIndex); - table.getSelectionModel().setSelectionInterval(rowViewIndex, rowViewIndex); - } - - /** - * Add the given row index {@code rowIndex} (from the model coordinate) - * in the selection of the given table. - * - * @param table the table where to set the selection - * @param rowIndex the row index in the model coordinate to add to selection - * @since 2.5.29 - */ - public static void addRowSelectionInterval(JTable table, int rowIndex) { - - int rowViewIndex = table.convertRowIndexToView(rowIndex); - table.getSelectionModel().addSelectionInterval(rowViewIndex, rowViewIndex); - } - - /** - * A simple iterator on a {@link JTabbedPane}. - * - * Implements the method {@link #get(int, Component)} to obtain - * the data required given the component (or index). - * - * You can also inverse the order by usin the method {@link #reverse()}. - * - * Note: After the use of the method {@link #reverse()} the iterator returns - * to the first element. - * - * @param <O> the type of return elements. - * @since 1.4 - */ - public static abstract class TabbedPaneIterator<O> implements Iterator<O> { - - final JTabbedPane tabs; - - boolean reverse; - - int index; - - int increment; - - protected abstract O get(int index, Component comp); - - public TabbedPaneIterator(boolean reverse, JTabbedPane tabs) { - this.tabs = tabs; - setReverse(reverse); - } - - public void reset() { - setReverse(reverse); - } - - public int size() { - return tabs.getTabCount(); - } - - public TabbedPaneIterator<O> reverse() { - setReverse(!reverse); - return this; - } - - @Override - public boolean hasNext() { - return reverse ? index > 0 : index < tabs.getTabCount(); - } - - public int getIndex() { - return index; - } - - @Override - public O next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - Component next = tabs.getComponentAt(index); - O result = get(index, next); - index += increment; - return result; - } - - @Override - public void remove() { - throw new IllegalStateException("not implemented for " + this); - } - - @Override - public String toString() { - return super.toString() + "< reverse:" + reverse + ", index:" + - index + ", size:" + tabs.getTabCount() + " >"; - } - - protected void setReverse(boolean reverse) { - if (reverse) { - index = tabs.getTabCount() - 1; - increment = -1; - } else { - index = 0; - increment = 1; - } - this.reverse = reverse; - } - } - - public static JLabel newLabel(String text, Object iconKey, int aligment) { - Icon icon = null; - if (iconKey instanceof Icon) { - icon = (Icon) iconKey; - } else if (iconKey instanceof String) { - icon = getUIManagerActionIcon((String) iconKey); - } - JLabel result; - if (icon == null) { - result = new JLabel(text, aligment); - } else { - result = new JLabel(text, icon, aligment); - } - return result; - } - - /** - * Gets the higest visible component in a ancestor hierarchy at - * specific x,y coordinates - * - * @param parent - * @param x - * @param y - * @return the deppest component - */ - public static Component getDeepestObjectAt(Component parent, int x, int y) { - - if (parent instanceof Container) { - Container cont = (Container) parent; - // use a copy of 1.3 Container.findComponentAt - Component child = findComponentAt(cont, - cont.getWidth(), - cont.getHeight(), x, y); - if (child != null && child != cont) { - //log.info("child find : " + child.getName()); - if (child instanceof JRootPane) { - JLayeredPane lp = ((JRootPane) child).getLayeredPane(); - Rectangle b = lp.getBounds(); - child = getDeepestObjectAt(lp, x - b.x, y - b.y); - } - if (child != null) { - return child; - } - } - } - // if the parent is not a Container then it might be a MenuItem. - // But even if it isn't a MenuItem just return the parent because - // that's a close as we can come. - return parent; - } - - public static Component findComponentAt(Container cont, - int width, - int height, - int x, - int y) { - //log.info("container : " + cont.getName()); - synchronized (cont.getTreeLock()) { - - if (!(x >= 0 && x < width && y >= 0 && y < height && - cont.isVisible() && cont.isEnabled())) { - return null; - } - - Component[] component = cont.getComponents(); - int ncomponents = cont.getComponentCount(); - - // Two passes: see comment in sun.awt.SunGraphicsCallback - for (int i = 0; i < ncomponents; i++) { - Component comp = component[i]; - Rectangle rect = null; - - if (comp != null && !comp.isLightweight()) { - if (rect == null || rect.width == 0 || rect.height == 0) { - rect = comp.getBounds(); - } - if (comp instanceof JXLayer<?>) { - JXLayer<?> layer = (JXLayer<?>) comp; - comp = layer.getView(); - } - if (comp instanceof Container) { - comp = findComponentAt( - (Container) comp, - rect.width, - rect.height, - x - rect.x, - y - rect.y - ); - } else { - comp = comp.getComponentAt(x - rect.x, y - rect.y); - } - if (comp != null && comp.isVisible() && comp.isEnabled()) { - return comp; - } - } - } - - for (int i = 0; i < ncomponents; i++) { - Component comp = component[i]; - Rectangle rect = null; - - if (comp != null && comp.isLightweight()) { - if (rect == null || rect.width == 0 || rect.height == 0) { - rect = comp.getBounds(); - } - if (comp instanceof JXLayer<?>) { - JXLayer<?> layer = (JXLayer<?>) comp; - comp = layer.getView(); - } - if (comp instanceof Container) { - comp = findComponentAt( - (Container) comp, - rect.width, - rect.height, - x - rect.x, - y - rect.y - ); - } else { - comp = comp.getComponentAt(x - rect.x, y - rect.y); - } - if (comp != null && comp.isVisible() && comp.isEnabled()) { - return comp; - } - } - } - return cont; - } - } - - public static TableCellRenderer newDeleteCellRenderer( - DefaultTableCellRenderer renderer) { - Icon icon = UIManager.getIcon("Table.removeIcon"); - if (icon == null) { - // try with default icon - icon = createActionIcon("delete"); - } - return new BooleanCellEditor(renderer, icon); - } - - public static TableCellRenderer newBooleanTableCellRenderer( - TableCellRenderer renderer) { - return new BooleanCellRenderer(renderer); - } - - public static TableCellRenderer newBooleanTableCellRenderer( - TableCellRenderer renderer, Predicate<?> predicate) { - return new BooleanCellRenderer(renderer, predicate); - } - - public static TableCellRenderer newBooleanTableCellEditorAndRenderer( - TableCellRenderer renderer) { - return new BooleanCellEditor(renderer); - } - - public static BooleanCellEditor newBooleanTableCellEditor( - TableCellRenderer renderer) { - return new BooleanCellEditor(renderer); - } - - public static EmptyNumberTableCellRenderer newEmptyNumberTableCellRenderer( - TableCellRenderer renderer) { - return new EmptyNumberTableCellRenderer(renderer); - } - - public static <E extends Enum<E>> EnumTableCellRenderer<E> - newEnumTableCellRenderer(TableCellRenderer renderer, Class<E> enumClass) { - return new EnumTableCellRenderer<E>(renderer, enumClass); - } - - /** - * Open a link coming from a {@link HyperlinkEvent}. - * - * And try to open the link if an url in a browser. - * - * @param he the event to treate - * @since 1.6.0 - */ - public static void openLink(HyperlinkEvent he) { - if (he.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - - if (Desktop.isDesktopSupported()) { - try { - URL u = he.getURL(); - if (u.getProtocol().equalsIgnoreCase("mailto") || - u.getProtocol().equalsIgnoreCase("http") || - u.getProtocol().equalsIgnoreCase("ftp")) { - Desktop.getDesktop().browse(u.toURI()); - } - } catch (IOException e) { - if (log.isErrorEnabled()) { - log.error("Error while opening link", e); - } - } catch (URISyntaxException e) { - if (log.isErrorEnabled()) { - log.error("Error while opening link", e); - } - } - } - } - } - - public static void openLink(String url) { - - try { - if (!Desktop.isDesktopSupported()) { - throw new IllegalStateException( - t("swing.error.desktop.not.supported")); - } - - - Desktop desktop = Desktop.getDesktop(); - - if (!desktop.isSupported(Desktop.Action.BROWSE)) { - - throw new IllegalStateException( - t("swing.error.desktop.browse.not.supported")); - } - - URI uri = new URI(url); - desktop.browse(uri); - } catch (Exception e) { - - if (log.isErrorEnabled()) { - log.error("Error while opening link", e); - } - } - } - - /** - * Expand all childs of a tree. - * - * @param tree the tree to expand - */ - public static void expandTree(final JTree tree) { - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - int i = 0; - while (i < tree.getRowCount()) { - tree.expandRow(i++); - } - } - }); - } - - /** - * Expand all childs of a tree table. - * - * FIXME : Voir pour enlever le copier coller - * - * @param treeTable the tree to expand - */ - public static void expandTreeTable(final JXTreeTable treeTable) { - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - int i = 0; - while (i < treeTable.getRowCount()) { - treeTable.expandRow(i++); - } - } - }); - } - - /** - * Add a listener of tree selection model to expand a new selected node - * when it is selected. - * - * @param tree the tree to treate - */ - public static void addExpandOnClickListener(final JTree tree) { - - tree.getSelectionModel().addTreeSelectionListener( - new TreeSelectionListener() { - - @Override - public void valueChanged(final TreeSelectionEvent e) { - TreeNode node = (TreeNode) - e.getPath().getLastPathComponent(); - if (node != null && !node.isLeaf()) { - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - for (TreePath path : e.getPaths()) { - if (e.isAddedPath(path) && - !tree.isExpanded(path)) { - log.info("expand node [" + path - + "]"); - // will expand the node - tree.expandPath(path); - } - } - } - }); - } - } - }); - } - - /** - * Add a listener of tree table selection model to expand a new selected - * node when it is selected. - * - * FIXME : Voir pour enlever le copier coller - * - * @param treeTable the tree to treate - */ - public static void addExpandOnClickListener(final JXTreeTable treeTable) { - - treeTable.addTreeSelectionListener(new TreeSelectionListener() { - - @Override - public void valueChanged(final TreeSelectionEvent e) { - TreeNode node = (TreeNode) e.getPath().getLastPathComponent(); - if (node != null && !node.isLeaf()) { - - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - for (TreePath path : e.getPaths()) { - if (e.isAddedPath(path) && - !treeTable.isExpanded(path)) { - log.info("expand node [" + path + "]"); - // will expand the node - treeTable.expandPath(path); - } - } - } - }); - } - } - }); - } - - /** - * Set the width of the given component - * - * @param component the component to resize - * @param width the new width to apply - */ - public static void setComponentWidth(Component component, int width) { - component.setSize(width, component.getHeight()); - if (component instanceof JComponent) { - JComponent jcomponent = (JComponent) component; - jcomponent.setPreferredSize( - new Dimension(width, - jcomponent.getPreferredSize().height) - ); - jcomponent.setMinimumSize( - new Dimension(width, - jcomponent.getPreferredSize().height) - ); - if (jcomponent.isDisplayable()) { - jcomponent.revalidate(); - } - } - } - - /** - * Set the height of a given component. - * - * @param component the component to resize - * @param height the new height to apply - */ - public static void setComponentHeight(Component component, int height) { - component.setSize(component.getWidth(), height); - if (component instanceof JComponent) { - JComponent jcomponent = (JComponent) component; - jcomponent.setPreferredSize( - new Dimension(jcomponent.getPreferredSize().width, height)); - jcomponent.setMinimumSize( - new Dimension(jcomponent.getPreferredSize().width, height)); - if (jcomponent.isDisplayable()) { - jcomponent.revalidate(); - } - } - } - - public static ImageIcon createIcon(String path) { - URL imgURL = JAXXUtil.class.getResource(path); - if (imgURL != null) { - return new ImageIcon(imgURL); - } else { - throw new IllegalArgumentException("could not find icon " + path); - } - } - - /** - * @param path the location of icons in root directory icons - * @return the icon at {@link #getIconPath()}+path - */ - public static ImageIcon createImageIcon(String path) { - String iconPath = getIconPath(); - return createIcon(iconPath + path); - } - - /** - * @param key the key of the icon to retreave from {@link UIManager} - * @return the icon, or {@code null} if no icon found in {@link UIManager} - */ - public static Icon getUIManagerIcon(String key) { - return UIManager.getIcon(key); - } - - /** - * retreave for the {@link UIManager} the icon prefixed by {@code action}. - * - * @param key the key of the action icon to retreave from {@link UIManager} - * @return the icon, or {@code null} if no icon found in {@link UIManager} - */ - public static Icon getUIManagerActionIcon(String key) { - return getUIManagerIcon("action." + key); - } - - public static ImageIcon createActionIcon(String name) { - String iconPath = getIconPath(); - return createIcon("action", name); - } - - public static ImageIcon createIcon(String classifier, String name) { - String iconPath = getIconPath(); - return createIcon(iconPath + classifier + "-" + name + ".png"); - } - - public static ImageIcon createI18nIcon(String name) { - String iconPath = getIconPath(); - return createIcon(iconPath + "i18n/" + name + ".png"); - } - - private static String getIconPath() { - String iconPath = UIManager.getString(DEFAULT_ICON_PATH_PROPERTY); - if (iconPath == null) { - iconPath = DEFAULT_ICON_PATH; - } else { - if (!iconPath.endsWith("/")) { - iconPath += "/"; - } - } - return iconPath; - } - - /** - * Add {@link java.awt.event.KeyListener} to focus next editable cell on TAB key - * - * @param table to add TAB {@link java.awt.event.KeyListener} - */ - public static void makeTableTabFocusable(final JTable table) { - table.setCellSelectionEnabled(true); - table.setSurrendersFocusOnKeystroke(true); - table.addKeyListener(new KeyAdapter() { - - @Override - public void keyReleased(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_TAB) { - - // get table informations - int selectedColumn = table.getSelectedColumn(); - int selectedRow = table.getSelectedRow(); - - if (log.isDebugEnabled()) { - log.debug("Selected was row[" + selectedRow + "] column[" + selectedColumn + "]"); - } - - int columnCount = table.getColumnCount(); - int rowCount = table.getRowCount(); - - // search on current line - for (int toSelectColumn = selectedColumn; toSelectColumn < columnCount; toSelectColumn++) { - - if (editCell(table, selectedRow, toSelectColumn)) { - return; - } - } - - // search on other lines - for (int toSelectRow = selectedRow; toSelectRow < rowCount; toSelectRow++) { - for (int toSelectColumn = 0; toSelectColumn < columnCount; toSelectColumn++) { - - if (editCell(table, toSelectRow, toSelectColumn)) { - return; - } - } - } - } - } - }); - } - - /** - * Used to edit a cell of a given table. - * - * @param table the table to edit - * @param row row index of cell to editing - * @param colummn column index of cell to editing - * @return {@code false} if for any reason the cell cannot be edited, - * or if the indices are invalid - */ - public static boolean editCell(JTable table, int row, int colummn) { - - boolean result = false; - if (table.isCellEditable(row, colummn)) { - - if (table.isEditing()) { - - int editingRow = table.getEditingRow(); - int editingColumn = table.getEditingColumn(); - - // stop edition - TableCellEditor cellEditor = table.getCellEditor(editingRow, - editingColumn); - cellEditor.stopCellEditing(); - } - - // select row - table.setColumnSelectionInterval(colummn, colummn); - table.setRowSelectionInterval(row, row); - - // edit cell - result = table.editCellAt(row, colummn, new EventObject(table)); - Component component = table.getEditorComponent(); - component.requestFocus(); - - if (log.isDebugEnabled()) { - log.debug("Select row[" + row + "] column[" + colummn + - "] return : " + result); - } - } - return result; - } - - public static void ensureRowIndex(TableModel model, int rowIndex) - throws ArrayIndexOutOfBoundsException { - if (rowIndex < -1 || rowIndex >= model.getRowCount()) { - throw new ArrayIndexOutOfBoundsException( - "the rowIndex was " + rowIndex + ", but should be int [0," - + (model.getRowCount() - 1) + "]"); - } - } - - public static void ensureColumnIndex(TableModel model, int index) - throws ArrayIndexOutOfBoundsException { - if (index < -1 || index >= model.getColumnCount()) { - throw new ArrayIndexOutOfBoundsException( - "the columnIndex was " + index + ", but should be int [0," - + (model.getColumnCount() - 1) + "]"); - } - } - - /** - * Add to a given table a selec tion model listener to always scroll to - * current cell selection. - * - * @param table the table - * @since 2.5.3 - */ - public static void scrollToTableSelection(final JTable table) { - - table.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - ListSelectionModel listSelectionModel = - (ListSelectionModel) e.getSource(); - int firstIndex = e.getFirstIndex(); - int lastIndex = e.getLastIndex(); - Integer newSelectedRow = null; - - if (listSelectionModel.isSelectionEmpty()) { - - // no selection - } else if (listSelectionModel.isSelectedIndex(firstIndex)) { - - // use first index - newSelectedRow = firstIndex; - } else if (listSelectionModel.isSelectedIndex(lastIndex)) { - - // use last index - newSelectedRow = lastIndex; - } - if (newSelectedRow != null) { - Rectangle rect = table.getCellRect(newSelectedRow, 0, true); - table.scrollRectToVisible(rect); - } - } - }); - } - - /** - * Get the first char of a String, or return default value. - * - * Used for example by generated code (i18nMnemonic). - * - * @param text the text to cut - * @param defaultValue default char value if text is null, or empty - * @return the first char of the given text or the default value if text is null or empty. - * @since 2.6.14 - */ - public static char getFirstCharAt(String text, char defaultValue) { - return text == null || text.trim().length() == 0 ? - defaultValue : text.charAt(0); - } - - public static void openLink(URI uri) { - - Desktop desktop = getDesktopForBrowse(); - - try { - - desktop.browse(uri); - } catch (Exception e) { - - throw new RuntimeException( - t("application.error.cannot.open.link", uri), e); - } - } - - public static Desktop getDesktopForBrowse() { - - if (!Desktop.isDesktopSupported()) { - throw new RuntimeException( - t("application.error.desktop.not.supported")); - } - - Desktop desktop = Desktop.getDesktop(); - - if (!desktop.isSupported(Desktop.Action.BROWSE)) { - - throw new RuntimeException( - t("application.error.desktop.browse.not.supported")); - } - - return desktop; - } - - public static DefaultComboBoxModel newComboModel(Object... items) { - return new DefaultComboBoxModel(items); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/BuildTreeVisitor.java b/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/BuildTreeVisitor.java deleted file mode 100644 index 163a10e..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/BuildTreeVisitor.java +++ /dev/null @@ -1,69 +0,0 @@ -package jaxx.runtime.awt.visitor; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.jdesktop.jxlayer.JXLayer; - -import javax.swing.JRootPane; -import java.awt.Component; -import java.awt.Container; - -/** - * A visitor to build the tree from a given component. - * - * To obtain a tree from a compoent use the method {@link #buildTree(Component)}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.14 - */ -public class BuildTreeVisitor implements ComponentTreeNodeVisitor { - - public static ComponentTreeNode buildTree(Component component) { - BuildTreeVisitor v = new BuildTreeVisitor(); - ComponentTreeNode rootNode = new ComponentTreeNode(component); - rootNode.visit(v); - return rootNode; - } - - @Override - public void startNode(ComponentTreeNode node) { - Component component = node.getUserObject(); - if (component instanceof Container) { - Container container = (Container) component; - //TODO-TC-2013-03-17 Should use some rules to add this. - for (Component child : container.getComponents()) { - if (child instanceof JXLayer<?>) { - child = ((JXLayer<?>) child).getView(); - } else if (child instanceof JRootPane) { - child = ((JRootPane) child).getLayeredPane(); - } - ComponentTreeNode childNode = new ComponentTreeNode(child); - node.add(childNode); - } - } - } - - @Override - public void endNode(ComponentTreeNode componentTree) { - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/ComponentTreeNode.java b/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/ComponentTreeNode.java deleted file mode 100644 index 0cd4ce1..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/ComponentTreeNode.java +++ /dev/null @@ -1,111 +0,0 @@ -package jaxx.runtime.awt.visitor; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.collections4.iterators.EnumerationIterator; - -import javax.swing.tree.DefaultMutableTreeNode; -import java.awt.Component; -import java.awt.Container; -import java.util.Iterator; - -/** - * A node where userObject is a {@link Component}. - * - * If the component is a {@link Container}, then his children are the components - * of the container. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.14 - */ -public class ComponentTreeNode extends DefaultMutableTreeNode implements Iterable<ComponentTreeNode> { - - private static final long serialVersionUID = 1L; - - public ComponentTreeNode(Component userObject) { - super(userObject, true); - } - - /** - * To visit a node. - * - * @param visitor the visitor - */ - public void visit(ComponentTreeNodeVisitor visitor) { - visitor.startNode(this); - for (ComponentTreeNode child : this) { - child.visit(visitor); - } - visitor.endNode(this); - } - - @Override - public Component getUserObject() { - return (Component) super.getUserObject(); - } - - @Override - public ComponentTreeNode getParent() { - return (ComponentTreeNode) super.getParent(); - } - - @Override - public ComponentTreeNode getNextLeaf() { - return (ComponentTreeNode) super.getNextLeaf(); - } - - @Override - public ComponentTreeNode getNextNode() { - return (ComponentTreeNode) super.getNextNode(); - } - - @Override - public ComponentTreeNode getNextSibling() { - return (ComponentTreeNode) super.getNextSibling(); - } - - @Override - public ComponentTreeNode getPreviousLeaf() { - return (ComponentTreeNode) super.getPreviousLeaf(); - } - - @Override - public ComponentTreeNode getPreviousNode() { - return (ComponentTreeNode) super.getPreviousNode(); - } - - @Override - public ComponentTreeNode getPreviousSibling() { - return (ComponentTreeNode) super.getPreviousSibling(); - } - - @Override - public ComponentTreeNode getRoot() { - return (ComponentTreeNode) super.getRoot(); - } - - @Override - public Iterator<ComponentTreeNode> iterator() { - return new EnumerationIterator(children()); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/ComponentTreeNodeVisitor.java b/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/ComponentTreeNodeVisitor.java deleted file mode 100644 index b04ad94..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/ComponentTreeNodeVisitor.java +++ /dev/null @@ -1,36 +0,0 @@ -package jaxx.runtime.awt.visitor; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -/** - * To visit a {@link ComponentTreeNode}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.14 - */ -public interface ComponentTreeNodeVisitor { - - void startNode(ComponentTreeNode componentTree); - - void endNode(ComponentTreeNode componentTree); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/DebugComponentTreeNodeVisitor.java b/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/DebugComponentTreeNodeVisitor.java deleted file mode 100644 index cde129d..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/DebugComponentTreeNodeVisitor.java +++ /dev/null @@ -1,87 +0,0 @@ -package jaxx.runtime.awt.visitor; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.awt.Component; - -/** - * To print a tree node. - * - * Created on 1/10/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.7 - */ -public class DebugComponentTreeNodeVisitor implements ComponentTreeNodeVisitor { - - /** Logger. */ - private static final Log log = - LogFactory.getLog(DebugComponentTreeNodeVisitor.class); - - /** - * Flag to log in debug level (otherwise will be in info level). - */ - protected boolean debug; - - protected int level = 0; - - public void parse(ComponentTreeNode componentTree) { - - sb = new StringBuilder(); - componentTree.visit(this); - - String message = sb.toString(); - if (debug) { - log.debug(message); - } else { - log.info(message); - } - } - - protected StringBuilder sb = new StringBuilder(); - - @Override - public void startNode(ComponentTreeNode componentTree) { - String message = StringUtils.leftPad(" ", 2 * level); - sb.append("\n").append(message).append(getMessage(componentTree)); - level++; - } - - @Override - public void endNode(ComponentTreeNode componentTree) { - level--; - } - - public void setDebug(boolean debug) { - this.debug = debug; - } - - public String getMessage(ComponentTreeNode componentTree) { - Component userObject = componentTree.getUserObject(); - return userObject.getClass().getSimpleName() + "::" + userObject.getName(); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/GetCompopentAtPointVisitor.java b/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/GetCompopentAtPointVisitor.java deleted file mode 100644 index fd0cbdb..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/GetCompopentAtPointVisitor.java +++ /dev/null @@ -1,114 +0,0 @@ -package jaxx.runtime.awt.visitor; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.collect.Lists; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.awt.Component; -import java.awt.Point; -import java.awt.Rectangle; -import java.util.List; - -/** - * A visitor to get the deepest component given a point in a tree. - * - * To obtain the component use the method {@link #get(ComponentTreeNode, Point)}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.14 - */ -public class GetCompopentAtPointVisitor implements ComponentTreeNodeVisitor { - - /** Logger. */ - private static final Log log = - LogFactory.getLog(GetCompopentAtPointVisitor.class); - - int currentX; - - int currentY; - - final List<ComponentTreeNode> components = Lists.newArrayList(); - - public static Component get(ComponentTreeNode node, Point p) { - - GetCompopentAtPointVisitor v = new GetCompopentAtPointVisitor(p); - node.visit(v); - Component result = v.getLastComponent(); - v.components.clear(); - return result; - } - - public GetCompopentAtPointVisitor(Point p) { - currentX = (int) p.getX(); - currentY = (int) p.getY(); - } - - public Component getLastComponent() { - Component result = null; - if (!components.isEmpty()) { - ComponentTreeNode node = components.get(components.size() - 1); - result = node.getUserObject(); - } - return result; - } - - @Override - public void startNode(ComponentTreeNode node) { - Component component = node.getUserObject(); - - if (!(component.isVisible() && component.isShowing())) { - if (log.isDebugEnabled()) { - log.debug("Skip invisible component: " + - component.getClass().getSimpleName() + "::" + - component.getName()); - } - return; - } - - // check parent is ok - if (node.isRoot() || components.contains(node.getParent())) { - - Point locationOnScreen = component.getLocationOnScreen(); - Rectangle bounds = component.getBounds(); - bounds.setLocation(locationOnScreen); - - boolean containsPoint = bounds.contains(currentX, currentY); - - if (containsPoint) { - - if (log.isDebugEnabled()) { - log.debug("Accept component: " + component); - } - - // keep this node - components.add(node); - } - } - } - - @Override - public void endNode(ComponentTreeNode componentTree) { - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/bean/BeanTypeAware.java b/jaxx-runtime/src/main/java/jaxx/runtime/bean/BeanTypeAware.java deleted file mode 100644 index ef5bf9f..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/bean/BeanTypeAware.java +++ /dev/null @@ -1,41 +0,0 @@ -package jaxx.runtime.bean; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -/** - * Contract for ui which contains a {@code beanType} property. - * - * In a jaxx file, if an object has a genericType and implementsthis contract - * then the {@code beanType} will be automaticly setted. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.9 - */ -public interface BeanTypeAware<O> { - - String PROPERTY_BEAN_TYPE= "beanType"; - - Class<O> getBeanType(); - - void setBeanType(Class<O> beanType); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/binding/DefaultJAXXBinding.java b/jaxx-runtime/src/main/java/jaxx/runtime/binding/DefaultJAXXBinding.java deleted file mode 100644 index aca4f70..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/binding/DefaultJAXXBinding.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.binding; - -import jaxx.runtime.JAXXBinding; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.JAXXUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.beans.PropertyChangeEvent; - - -/** - * A <code>PropertyChangeListener</code> which processes a data binding when it receives a - * <code>PropertyChangeEvent</code>. - */ -public abstract class DefaultJAXXBinding implements JAXXBinding { - - /** Logger */ - private static final Log log = LogFactory.getLog(DefaultJAXXBinding.class); - - /** Counter of all bindings hits */ - private static long NB; - - /** Counter of current binding hits */ - private long nb; - - /** Id of the binding */ - private final String id; - - /** The source of the binding. */ - protected final JAXXObject source; - - /** - * flag to know {@code true} : if the binding was init from a generated - * jaxx object, {@code false} otherwise. - */ - protected final boolean defaultBinding; - - /** - * Internal state to reapply the binding after each fires :this is sometimes - * necessary when binding is complex. For example with this binding - * <pre> - * ui.getModel().getProperty() - * </pre> - * We need to listen two things : first listen on {@code ui} the - * modification of {@code model}, then on {@code model} the {@code property}. - * - * @since 2.4.2 - */ - protected final boolean reloadAfterFire; - - /** - * Creates a new Data binding which will run the given data binding - * when it receives a <code>PropertyChangeEvent</code>. - * - * @param source the {@link JAXXObject} source of the binding - * @param id the name of the data binding to run - * @param defaultBinding flag to knwon if binding is coming from a generated jaxx object ({@code true}). - */ - public DefaultJAXXBinding(JAXXObject source, String id, - boolean defaultBinding) { - this(source, id, defaultBinding, false); - } - - /** - * Creates a new Data binding which will run the given data binding - * when it receives a <code>PropertyChangeEvent</code>. - * - * @param source the {@link JAXXObject} source of the binding - * @param id the name of the data binding to run - * @param defaultBinding flag to know if binding is coming from a generated jaxx object ({@code true}). - * @param reloadAfterFire flag to know if the binding need to be reload after each fires - */ - public DefaultJAXXBinding(JAXXObject source, String id, - boolean defaultBinding, - boolean reloadAfterFire) { - this.source = source; - this.id = id; - this.defaultBinding = defaultBinding; - this.reloadAfterFire = reloadAfterFire; - } - - @Override - public String getId() { - return id; - } - - @Override - public JAXXObject getSource() { - return source; - } - - @Override - public boolean isDefaultBinding() { - return defaultBinding; - } - - @Override - public String toString() { - return super.toString() + ":" + id; - } - - private static final String LOG_START_PATTERN = ">> (hits:%1$5d, total:%2$5d) on %3$s"; - - private static final String LOG_END_PATTERN = "<< %4$3d (hits:%1$5d, total:%2$5d) on %3$s"; - - /** - * Processes the data binding in response to a <code>PropertyChangeEvent</code>. - * - * When the binding is wake up, delegate the process to the source object which - * can manage re-entrant code (can not process a re-entrant event). - * - * @param e the event which triggered the binding - */ - @Override - public void propertyChange(PropertyChangeEvent e) { - long count = NB; - if (log.isDebugEnabled()) { - log.debug(String.format(LOG_START_PATTERN, ++nb, ++NB, this)); - } - //TODO-TC-20091202 perharps could we have a nicer way to process it, - // let the source deal with it to avoid re-entrant code - source.processDataBinding(id); - - //TODO-20091201 Must test on a lot of cases before next release 2.0.0-beta-2 - //TC-20091201 : I really don't see the point - // I comment the code, and still working fine ? Any trick - // for now, handle dependency changes by always removing & reapplying - // the binding. We should be more efficient and only do this when it's - // actually necessary - if (reloadAfterFire) { - JAXXUtil.reloadBinding(this); - } -// source.removeDataBinding(id); -// source.applyDataBinding(id); - if (log.isDebugEnabled()) { - log.debug(String.format(LOG_END_PATTERN, ++nb, ++NB, this, NB - count)); - } - } - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/binding/SimpleJAXXObjectBinding.java b/jaxx-runtime/src/main/java/jaxx/runtime/binding/SimpleJAXXObjectBinding.java deleted file mode 100644 index ef1abfc..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/binding/SimpleJAXXObjectBinding.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.binding; - -import jaxx.runtime.JAXXObject; - -/** - * Created: 5 déc. 2009 - * - * @author Tony Chemit - chemit@codelutin.com - * @version $Revision$ - * - * Mise a jour: $Date$ par : - * $Author$ - */ -public abstract class SimpleJAXXObjectBinding extends DefaultJAXXBinding { - - protected final String[] propertyNames; - - /** - * Creates a new Data binding which will run the given data binding - * when it receives a <code>PropertyChangeEvent</code>. - * - * @param source the {@link JAXXObject} source of the binding - * @param id the name of the data binding to run - * @param defaultBinding flag to knwon if binding is coming from a generated jaxx object ({@code true}). - * @param propertyNames the name of properties to listen on source - */ - public SimpleJAXXObjectBinding(JAXXObject source, String id, boolean defaultBinding, String... propertyNames) { - super(source, id, defaultBinding); - if (propertyNames == null || propertyNames.length == 0) { - throw new IllegalArgumentException("must at least have one propertyName "); - } - this.propertyNames = propertyNames; - } - - public boolean canApply() { - return true; - } - - public String[] getPropertyNames() { - return propertyNames; - } - - @Override - public void applyDataBinding() { - if (canApply()) { - for (String s : propertyNames) { - source.addPropertyChangeListener(s, this); - } - } - } - - @Override - public void removeDataBinding() { - if (canApply()) { - for (String s : propertyNames) { - source.removePropertyChangeListener(s, this); - } - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/context/DataContext.java b/jaxx-runtime/src/main/java/jaxx/runtime/context/DataContext.java deleted file mode 100644 index 49c9c49..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/context/DataContext.java +++ /dev/null @@ -1,448 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.context; - -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.regex.Pattern; - -/** - * Un contexte de données qui permet l'utilisation des bindings sur les - * entrées du contexte. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.3 - */ -public abstract class DataContext { - - /** Logger */ - static private Log log = LogFactory.getLog(DataContext.class); - - public static final DataContextEntry<?>[] EMPTY_DATA_CONTEXT_ENTRY_ARRAY = - new DataContextEntry<?>[0]; - - /** le context qui contient les données */ - protected final DefaultJAXXContext delegate; - - /** la definition de l'entree actuallement selectionnee */ - protected DataContextEntry<?> currentEntry; - - /** to manage properties modifications */ - protected final PropertyChangeSupport pcs; - - protected DataContextEntry<?>[] entries; - - protected final String[] DEFAULT_JAXX_PCS; - - public abstract String getContextPath(Object... e); - - public DataContext(String[] DEFAULT_JAXX_PCS, - DataContextEntry<?>[] entries) { - this.DEFAULT_JAXX_PCS = DEFAULT_JAXX_PCS; - this.entries = entries; - delegate = new DefaultJAXXContext() { - - @Override - protected void setParentContext(JAXXContext parentContext) { - throw new IllegalStateException( - "can not use this method for this type of context"); - } - - @Override - protected JAXXContext getParentContext() { - return null; - } - - @Override - public <T> void removeContextValue(Class<T> klazz, String name) { - if (log.isTraceEnabled()) { - log.trace(klazz + " - " + name); - } - super.removeContextValue(klazz, name); - } - - @Override - public <T> void setContextValue(T o, String name) { - if (log.isTraceEnabled()) { - log.trace(name + " - " + o.getClass()); - } - super.setContextValue(o, name); - } - }; - pcs = new PropertyChangeSupport(this); - } - - public DefaultJAXXContext getDelegate() { - return delegate; - } - - public Iterable<? extends DataContextEntry<?>> iterateOnAll() { - return new Iterable<DataContextEntry<?>>() { - - @Override - public Iterator<DataContextEntry<?>> iterator() { - return new DataContextEntryIterator(entries); - } - }; - } - - public Iterable<? extends DataContextEntry<?>> iterateToLevel( - final int level) { - return new Iterable<DataContextEntry<?>>() { - - @Override - public Iterator<DataContextEntry<?>> iterator() { - return new DataContextEntryIterator(entries, level); - } - }; - } - - public Iterable<? extends DataContextEntry<?>> reverseIterateOnAll() { - - return new Iterable<DataContextEntry<?>>() { - - @Override - public Iterator<DataContextEntry<?>> iterator() { - return new DataContextEntryIterator(entries, true); - } - }; - } - - public DataContextEntry<?> getCurrentEntry() { - return currentEntry; - } - - public DataContextEntry<?> getEntry(String path) { - for (DataContextEntry<?> scope : reverseIterateOnAll()) { - if (scope.acceptPath(path)) { - return scope; - } - } - return null; - } - - public DataContextEntry<?> getEntry(Class<?> type) { - for (DataContextEntry<?> scope : iterateOnAll()) { - if (scope.acceptType(type)) { - return scope; - } - } - return null; - } - - public <T> T getContextValue(DataContextEntry<T> entry, String key) { - String contextKey = getKey(entry, key); - return delegate.getContextValue(entry.getKlass(), contextKey); - } - - public void setContextValue(DataContextEntry<?> entry, - Object value, - String key) { - String contextKey = getKey(entry, key); - delegate.setContextValue(value, contextKey); - } - - /** - * @param entry - * @param klass - * @param key - */ - public void removeContextValue(DataContextEntry<?> entry, - Class<?> klass, - String key) { - String contextKey = getKey(entry, key); - delegate.removeContextValue(klass, key); - } - - public void removeContextValue(DataContextEntry<?> entry, - String key) { - String contextKey = getKey(entry, key); - delegate.removeContextValue(entry.getKlass(), contextKey); - } - - @SuppressWarnings("unchecked") - public void updateSelectedData(String path, - Object data, - UpdateDataContext updator) { - - if (log.isDebugEnabled()) { - log.debug("-----------------------------------------------------" + - "-----------"); - } - if (currentEntry != null) { - - if (log.isDebugEnabled()) { - log.debug("remove from old entry " + currentEntry); - } - for (DataContextEntry<?> s : currentEntry) { - if (log.isDebugEnabled()) { - log.debug("remove entry " + s); - } - updator.onRemovingData(this, s); - } - } - - currentEntry = getEntry(path); - - if (log.isDebugEnabled()) { - log.debug("new entry " + currentEntry + " for path " + path); - } - - if (currentEntry != null) { - - for (DataContextEntry<?> s : - iterateToLevel(currentEntry.getLevel())) { - - if (log.isDebugEnabled()) { - log.debug("add entry " + s); - } - updator.onAddingData(this, s, path); - } - } - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - pcs.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - pcs.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.removePropertyChangeListener(propertyName, listener); - } - - public synchronized boolean hasListeners(String propertyName) { - return pcs.hasListeners(propertyName); - } - - public synchronized PropertyChangeListener[] getPropertyChangeListeners( - String propertyName) { - return pcs.getPropertyChangeListeners(propertyName); - } - - public synchronized PropertyChangeListener[] getPropertyChangeListeners() { - return pcs.getPropertyChangeListeners(); - } - - public void removeJaxxPropertyChangeListener() { - PropertyChangeListener[] toRemove = - JAXXUtil.findJaxxPropertyChangeListener( - DEFAULT_JAXX_PCS, getPropertyChangeListeners()); - if (toRemove == null || toRemove.length == 0) { - return; - } - if (log.isDebugEnabled()) { - log.debug("before remove : " + getPropertyChangeListeners().length); - log.debug("toRemove : " + toRemove.length); - } - for (PropertyChangeListener listener : toRemove) { - removePropertyChangeListener(listener); - } - if (log.isDebugEnabled()) { - log.debug("after remove : " + getPropertyChangeListeners().length); - } - } - - protected void firePropertyChange(String name, - Object oldValue, - Object newValue) { - pcs.firePropertyChange(name, oldValue, newValue); - } - - protected String getKey(DataContextEntry<?> entry, String key) { - String result = null; - if (key != null) { - result = entry.hashCode() + "#" + key; - } - return result; - } - - public void close() throws Exception { - clear(); - - // suppression des ecouteurs - - for (PropertyChangeListener l : getPropertyChangeListeners()) { - removePropertyChangeListener(l); - } - } - - public void clear() { - delegate.clear(); - } - - public static abstract class DataContextEntry<E> implements Iterable<DataContextEntry<?>> { - - private final int level; - - private final DataContextEntry<?> previous; - - private final DataContextEntry<?>[] parents; - - private Class<E> klass; - - public DataContextEntry(Class<E> klass, DataContextEntry<?> previous) { - this.previous = previous; - level = previous.level + 1; - this.klass = klass; - parents = new DataContextEntry<?>[level]; - int i = level; - while (i > 0) { - parents[--i] = previous; - previous = previous.previous; - } - } - - public DataContextEntry(Class<E> klass) { - level = 0; - this.klass = klass; - previous = null; - parents = EMPTY_DATA_CONTEXT_ENTRY_ARRAY; - } - - public Class<E> getKlass() { - return klass; - } - - public int getLevel() { - return level; - } - - public DataContextEntry<?>[] getParents() { - return parents; - } - - public abstract Pattern getPattern(); - - public abstract String getContextPath(Object... args); - - public boolean acceptPath(String path) { - return getPattern().matcher(path).matches(); - } - - public boolean acceptType(Class<?> type) { - return klass.isAssignableFrom(type); - } - - @Override - public Iterator<DataContextEntry<?>> iterator() { - int length = parents.length; - DataContextEntry<?>[] t = new DataContextEntry<?>[length + 1]; - System.arraycopy(parents, 0, t, 0, length); - t[length] = this; - return new DataContextEntryIterator(t, true); - } - - @Override - public String toString() { - return super.toString() + "<type: " + klass.getSimpleName() + ">"; - } - } - - public interface UpdateDataContext<D extends DataContext> { - - void onRemovingData(D context, DataContextEntry<D> entry); - - void onAddingData(D context, DataContextEntry<D> entry, String path); - } - - public static class DataContextEntryIterator implements Iterator<DataContextEntry<?>> { - - protected final DataContextEntry<?>[] datas; - - protected final boolean reverse; - - protected final int level; - - protected int index; - - public DataContextEntryIterator(DataContextEntry<?>[] datas) { - this(datas, false, -1); - } - - public DataContextEntryIterator(DataContextEntry<?>[] datas, - int level) { - this(datas, false, level); - } - - public DataContextEntryIterator(DataContextEntry<?>[] datas, - boolean reverse) { - this(datas, reverse, -1); - } - - DataContextEntryIterator(DataContextEntry<?>[] datas, - boolean reverse, - int level) { - this.datas = datas; - this.reverse = reverse; - if (reverse) { - index = datas.length; - } else { - index = -1; - } - this.level = level; - } - - @Override - public boolean hasNext() { - if (reverse) { - return index > 0; - } else { - return index + 1 < datas.length && - (level == -1 || datas[index + 1].getLevel() <= level); - } - } - - @Override - public DataContextEntry<?> next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - if (reverse) { - index--; - } else { - index++; - } - return datas[index]; - } - - @Override - public void remove() { - throw new UnsupportedOperationException("Not supported yet."); - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/context/DefaultApplicationContext.java b/jaxx-runtime/src/main/java/jaxx/runtime/context/DefaultApplicationContext.java deleted file mode 100644 index cb8d4f9..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/context/DefaultApplicationContext.java +++ /dev/null @@ -1,473 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.context; - -import jaxx.runtime.JAXXContext; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; - -/** - * The default context to be used for an application. - * - * This extends the {@link DefaultJAXXContext} and add a possibility to - * auto-instanciate some classes asked via {@link #getContextValue(Class)} and - * {@link #getContextValue(Class, String)} methods. - * - * To registred a such class, just annotate your class with {@link AutoLoad}. - * - * @author Tony Chemit - chemit@codelutin.com - * @see DefaultJAXXContext - * @since 1.2 - */ -public class DefaultApplicationContext extends DefaultJAXXContext { - - /** - * A class annotated @AutoLoad is used by context to auto instanciate - * the class when required. - * - * Note : A such class always have a public default constructor. - * - * @author Tony Chemit - chemit@codelutin.com - * @version 1.0, 21/02/09 - * @since 1.2 - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.TYPE) - public @interface AutoLoad { - //TODO use this to add a method to init - - String initMethod() default ""; - } - - /** - * A class annotated @MethodAccess is used by context to obtain the - * value of an entry via a declared method. - * - * Note : A such class must have a method called {@link #methodName()} with - * a single String parameter. - * - * @author Tony Chemit - chemit@codelutin.com - * @version 1.0, 21/02/09 - * @since 1.2 - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.TYPE) - public @interface MethodAccess { - - /** - * Define a forward to a target class. When the target class will be - * asked with method {@link JAXXContext#getContextValue(Class, String)} - * it will be delegating to this class. - * - * @return the forwarded class - */ - Class<?> target() default Object.class; - - /** @return the name of the method to access data */ - String methodName(); - } - - /** Map of forwarded classes (key) to classes (values). */ - protected Map<Class<?>, Class<?>> forwards; - - /** - * Map of entries to watch associated with the property to fires if a - * modification was found. - */ - protected Map<JAXXContextEntryDef<?>, String> entryListened; - - public DefaultApplicationContext() { - forwards = new HashMap<Class<?>, Class<?>>(); - pcs = new PropertyChangeSupport(this); - } - - /** Logger */ - static private final Log log = - LogFactory.getLog(DefaultApplicationContext.class); - - /** to manage properties modifications */ - protected PropertyChangeSupport pcs; - - @SuppressWarnings({"unchecked"}) - @Override - public <T> T getContextValue(Class<T> clazz, String name) { - Object value; - MethodAccess access; - - Class<?> realClass; - - if (forwards.containsKey(clazz)) { - // this is a forward class - realClass = forwards.get(clazz); - // always call the forwarder with no name - value = getContextValue(realClass, null); - if (log.isDebugEnabled()) { - log.debug("detect forward from " + clazz + " to " + realClass + - " (" + value + ")"); - } - - } else { - realClass = clazz; - value = super.getContextValue(realClass, name); - } - - //TC-20091007 TODO Make possible use of named autoload entries - //(add a parameter on AutoLoad annotation) - if (value == null) { - AutoLoad anno = clazz.getAnnotation(AutoLoad.class); - - if (anno == null) { - // no annotation, so do nothing - return null; - } - - if (name != null) { - throw new IllegalArgumentException( - "an " + AutoLoad.class.getName() + " can not have " + - "a named context but was call with this one : " + name); - } - value = newInstance(clazz); - if (!anno.initMethod().trim().isEmpty()) { - // apply method on class - newAccess(clazz, value, anno.initMethod().trim()); - } - if (log.isDebugEnabled()) { - log.debug("new instance " + clazz + " : " + value); - } - // save new instance - setContextValue(value, null); - } - - access = realClass.getAnnotation(MethodAccess.class); - - if (access != null) { - if (name == null) { - if (!Object.class.equals(access.target())) { - // register forward - Class<?> targetClass = access.target(); - if (!forwards.containsKey(targetClass)) { - // register forward - forwards.put(targetClass, clazz); - if (log.isDebugEnabled()) { - log.debug("register forward from " + targetClass + - " to " + clazz); - } - } - } - } else { - // specialized access - value = newAccess(realClass, value, access.methodName(), name); - } - } - return (T) value; - } - - @Override - public <T> void removeContextValue(Class<T> klass, String name) { - Entry<Class<?>, Class<?>> entry; - if (name == null && forwards.containsValue(klass)) { - // remove forward - Iterator<Entry<Class<?>, Class<?>>> itr = - forwards.entrySet().iterator(); - while (itr.hasNext()) { - entry = itr.next(); - if (entry.getValue().equals(klass)) { - itr.remove(); - if (log.isDebugEnabled()) { - log.debug("removed forward from " + entry.getKey() + - " to " + klass); - } - break; - } - } - } - //FIXME should update forwards state - JAXXContextEntryDef<?> entryToDel = getEntry(klass, name); - Object t = remove0(klass, name); - if (log.isDebugEnabled()) { - log.debug("removed object = " + t); - } - if (t != null && entryToDel != null) { - // a value was removed - // notify listeners - fireEntryChanged(entryToDel, t, null); - } -// super.removeContextValue(klass, name); - } - - @Override - public <T> void setContextValue(T o, String name) { -// super.setContextValue(o, name); - if (name == null && PARENT_CONTEXT_ENTRY.accept2(o.getClass(), null)) { - setParentContext((JAXXContext) o); - return; - } - JAXXContextEntryDef<?> entry = getKey(name, o.getClass()); - // first remove entry - Object oldValue = remove0(o.getClass(), name); - if (oldValue != null) { - if (log.isDebugEnabled()) { - log.debug("remove value " + oldValue.getClass() + " for " + - entry); - } - } - // then can put safely - data.put(entry, o); - if (log.isDebugEnabled()) { - log.debug("[" + name + "] set value for entry " + entry); - } - // firezs - fireEntryChanged(entry.getKlass(), name, oldValue, o); - } - - /** - * To add a listen modification of the given entry in the context. - * - * @param entry the entry to listen - * @param name the property name to fire if necessary - * @param listener the listener to notify if entry has changed - * @since 2.0.1 - */ - public void addPropertyChangeListener(JAXXContextEntryDef<?> entry, - String name, - PropertyChangeListener listener) { - if (entryListened == null) { - entryListened = new HashMap<JAXXContextEntryDef<?>, String>(); - } - entryListened.put(entry, name); - if (log.isDebugEnabled()) { - log.debug("[" + name + "] for " + entry); - } - pcs.addPropertyChangeListener(name, listener); - } - - /** - * To remove a listen modification of the given entry in the context. - * - * @param entry the entry to listen - * @param name the property name to fire if necessary - * @param listener the listener to notify if entry has changed - * @since 2.0.1 - */ - public void removePropertyChangeListener(JAXXContextEntryDef<?> entry, - String name, - PropertyChangeListener listener) { - if (entryListened == null) { - entryListened = new HashMap<JAXXContextEntryDef<?>, String>(); - } - entryListened.remove(entry); - pcs.removePropertyChangeListener(name, listener); - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - pcs.addPropertyChangeListener(listener); - } - - - public void addPropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - pcs.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.removePropertyChangeListener(propertyName, listener); - } - - public synchronized boolean hasListeners(String propertyName) { - return pcs.hasListeners(propertyName); - } - - public synchronized PropertyChangeListener[] getPropertyChangeListeners( - String propertyName) { - return pcs.getPropertyChangeListeners(propertyName); - } - - public synchronized PropertyChangeListener[] getPropertyChangeListeners() { - return pcs.getPropertyChangeListeners(); - } - - protected void fireEntryChanged(Class<?> klass, - String name, - Object oldValue, - Object newValue) { - // a value was removed - if (entryListened != null) { - // look if the entry was listened - - if (log.isTraceEnabled()) { - log.trace("data size : " + data.size()); - for (Entry<JAXXContextEntryDef<?>, Object> e : data.entrySet()) { - log.trace(e.getKey()); - } - } - JAXXContextEntryDef<?> entry2 = getEntry(klass, name); - if (log.isDebugEnabled()) { - log.debug("[" + name + "] : try to find a changer for " + entry2); - } - if (entry2 != null) { - // entry find directly on this context - String propertyName = entryListened.get(entry2); - if (log.isTraceEnabled()) { - log.trace("registred property name = " + propertyName); - } - if (propertyName != null) { - if (log.isDebugEnabled()) { - log.debug("will notify modification on " + entry2); - } - // fires the removed - firePropertyChange(propertyName, oldValue, newValue); - } - } - } - } - - protected void fireEntryChanged(JAXXContextEntryDef<?> entryDef, - Object oldValue, - Object newValue) { - // a value was removed - if (entryListened != null) { - // look if the entry was listened - - if (log.isTraceEnabled()) { - log.trace("data size : " + data.size()); - for (Entry<JAXXContextEntryDef<?>, Object> e : data.entrySet()) { - log.trace(e.getKey()); - } - } -// JAXXContextEntryDef<?> entry2 = getEntry(klass, name); -// if (log.isDebugEnabled()) { -// log.debug("[" + name + "] : try to find a changer for " + entry2); -// } - if (entryDef != null) { - // entry find directly on this context - String propertyName = entryListened.get(entryDef); - if (log.isTraceEnabled()) { - log.trace("registred property name = " + propertyName); - } - if (propertyName != null) { - if (log.isDebugEnabled()) { - log.debug("will notify modification on " + entryDef); - } - // fires the removed - firePropertyChange(propertyName, oldValue, newValue); - } - } - } - } - - protected Object newInstance(Class<?> clazz) throws - IllegalArgumentException { - - Object value; - - Constructor<?> constructor; - try { - constructor = clazz.getConstructor(); - // auto instanciate the class - if (constructor == null) { - throw new IllegalArgumentException( - clazz + " has no public constructor"); - } - } catch (NoSuchMethodException ex) { - throw new IllegalArgumentException(ex); - } catch (SecurityException ex) { - throw new IllegalArgumentException(ex); - } - try { - value = constructor.newInstance(); - - } catch (InstantiationException ex) { - throw new IllegalArgumentException(ex); - } catch (IllegalAccessException ex) { - throw new IllegalArgumentException(ex); - } catch (InvocationTargetException ex) { - throw new IllegalArgumentException(ex); - } - return value; - } - - protected Object newAccess( - Class<?> clazz, - Object parent, - String methodName, - String name) throws IllegalArgumentException { - Object value; - try { - Method m = clazz.getMethod(methodName, String.class); - value = m.invoke(parent, name); - return value; - } catch (NoSuchMethodException ex) { - throw new IllegalArgumentException(ex); - } catch (SecurityException ex) { - throw new IllegalArgumentException(ex); - } catch (IllegalAccessException ex) { - throw new IllegalArgumentException(ex); - } catch (InvocationTargetException ex) { - throw new IllegalArgumentException(ex); - } - } - - protected Object newAccess( - Class<?> clazz, - Object parent, - String methodName) throws IllegalArgumentException { - Object value; - try { - Method m = clazz.getMethod(methodName); - value = m.invoke(parent); - return value; - } catch (NoSuchMethodException ex) { - throw new IllegalArgumentException(ex); - } catch (SecurityException ex) { - throw new IllegalArgumentException(ex); - } catch (IllegalAccessException ex) { - throw new IllegalArgumentException(ex); - } catch (InvocationTargetException ex) { - throw new IllegalArgumentException(ex); - } - } - - protected void firePropertyChange(String name, - Object oldValue, - Object newValue) { - pcs.firePropertyChange(name, oldValue, newValue); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/context/DefaultJAXXContext.java b/jaxx-runtime/src/main/java/jaxx/runtime/context/DefaultJAXXContext.java deleted file mode 100644 index 4ec3b53..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/context/DefaultJAXXContext.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.context; - -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.JAXXUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -/** - * The default {@link JAXXContext} to be used in a {@link JAXXObject} by - * delegation. - * - * The values are store in a {@link Map} but we can not use directly the values - * as key. - * - * Because, it does not work if we add for the same object multi entries (named - * and unamed)... - * - * We prefer use as entry the {@link JAXXContextEntryDef} associated with the - * value. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class DefaultJAXXContext implements JAXXContext { - - /** entry of the parent context */ - protected static final JAXXContextEntryDef<JAXXContext> - PARENT_CONTEXT_ENTRY = JAXXUtil.newContextEntryDef(JAXXContext.class); - - /** Logger */ - static private final Log log = LogFactory.getLog(DefaultJAXXContext.class); - - /** le context parent */ - protected JAXXContext parentContext; - - /** les données contenues dans le context */ - protected final Map<JAXXContextEntryDef<?>, Object> data; - - public DefaultJAXXContext() { - data = new HashMap<JAXXContextEntryDef<?>, Object>(); - } - - @Override - public <T> void setContextValue(T o) { - setContextValue(o, null); - } - - @Override - public <T> void setContextValue(T o, String name) { - if (name == null && PARENT_CONTEXT_ENTRY.accept2(o.getClass(), null)) { - setParentContext((JAXXContext) o); - return; - } - JAXXContextEntryDef<?> entry = getKey(name, o.getClass()); - // first remove entry - Object oldValue = remove0(o.getClass(), name); - if (oldValue != null) { - if (log.isDebugEnabled()) { - log.debug("remove value " + oldValue.getClass() + " for " + - entry); - } - } - // then can put safely - data.put(entry, o); - } - - @Override - public <T> T getContextValue(Class<T> clazz) { - return getContextValue(clazz, null); - } - - @SuppressWarnings({"unchecked"}) - @Override - public <T> T getContextValue(Class<T> clazz, String name) { - if (parentContext != null && - parentContext.getClass().equals(clazz) || - PARENT_CONTEXT_ENTRY.accept(clazz, name)) { - return (T) getParentContext(); - } - for (Entry<JAXXContextEntryDef<?>, Object> entry : data.entrySet()) { - if (entry.getKey().accept(clazz, name)) { - return (T) entry.getValue(); - } - } - - // no value found in this context, will try in the parent context - if (JAXXContext.class.equals(clazz)) { - // no seek in the parent context, since we are already looking - // for it - return null; - } - - JAXXContext parent = getParentContext(); - if (parent == null) { - // no parent context, so no value find - return null; - } - // seek in parent context - return parent.getContextValue(clazz, name); - } - - @Override - public <T> void removeContextValue(Class<T> klazz) { - removeContextValue(klazz, null); - } - - @Override - public <T> void removeContextValue(Class<T> klazz, String name) { - remove0(klazz, name); - } - - /** - * Obtain all the keys of data for a given type. - * - * @param klass the type of searched keys - * @return the array of all names of keys for the given type of data - * @since 1.3 - */ - public String[] getKeys(Class<?> klass) { - List<String> keys = new ArrayList<String>(); - for (JAXXContextEntryDef<?> key : data.keySet()) { - if (key.getKlass().equals(klass)) { - keys.add(key.getName()); - } - } - return keys.toArray(new String[keys.size()]); - - } - - public void clear() { - data.clear(); - } - - protected JAXXContextEntryDef<?> getKey(String name, Class<?> klass) { - //FIXME-TC20100322 : must change this to have a store, we instanciate - // a new object each time we wants to deal with the context... - return JAXXUtil.newContextEntryDef(name, klass); - } - - @SuppressWarnings({"unchecked"}) - protected <T> T remove0(Class<T> klass, String name) { - if (PARENT_CONTEXT_ENTRY.accept(klass, name)) { - JAXXContext old = getParentContext(); - setParentContext(null); - return (T) old; - } - JAXXContextEntryDef<?> entry = getEntry(klass, name); -// JAXXContextEntryDef<?> entry = null; -// for (JAXXContextEntryDef<?> entryDef : data.keySet()) { -// if (entryDef.accept(klass, name)) { -// entry = entryDef; -// break; -// } -// } - if (entry != null) { - return (T) data.remove(entry); - } - - if (JAXXContext.class.equals(klass)) { - return null; - } - - // try on parent - JAXXContext parent = getParentContext(); - - if (parent == null) { - // no parent, stop now, can not found entry - return null; - } - - if (parent instanceof DefaultJAXXContext) { - // try now on the parent - return ((DefaultJAXXContext) parent).remove0(klass, name); - } - - // can not find the entry anywhere, so says that nothing was removed - return null; - } - - protected JAXXContextEntryDef<?> getEntry(Class<?> klass, String name) { - JAXXContextEntryDef<?> entry = null; - for (JAXXContextEntryDef<?> entryDef : data.keySet()) { - if (entryDef.accept(klass, name)) { - entry = entryDef; - break; - } - } - return entry; - } - - protected JAXXContext getParentContext() { - return parentContext; - } - - protected void setParentContext(JAXXContext parentContext) { - if (parentContext instanceof JAXXObject) { - // keep the real context, not the ui - parentContext = ((JAXXObject) parentContext).getDelegateContext(); - } - this.parentContext = parentContext; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/context/JAXXContextEntryDef.java b/jaxx-runtime/src/main/java/jaxx/runtime/context/JAXXContextEntryDef.java deleted file mode 100644 index ca8fbea..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/context/JAXXContextEntryDef.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.context; - -import jaxx.runtime.JAXXContext; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; - -/** - * To qualify an entry in a {@link JAXXContext}. - * - * Use the factory methods <code>newContextEntryDef</code> and - * <code>newListContextEntryDef</code> to obtain new instances. - * - * @param <O> type of the entry associated to the definition - * @author Tony Chemit - chemit@codelutin.com - */ -public class JAXXContextEntryDef<O> implements Serializable { - - /** name of the entry, can be nuill for a unamed entry. */ - protected String name; - - /** class of the entry, can not be null */ - protected Class<O> klass; - - private static final long serialVersionUID = 1L; - - public String getName() { - return name; - } - - public Class<O> getKlass() { - return klass; - } - - public O getContextValue(JAXXContext context) { - return context.getContextValue(klass, name); - } - - public void removeContextValue(JAXXContext context) { - context.removeContextValue(klass, name); - } - - public void setContextValue(JAXXContext context, O value) { - context.setContextValue(value, name); - } - - @Override - public String toString() { - return super.toString() + "<" + klass + ":" + name + ">"; - } - - public JAXXContextEntryDef(Class<O> klass) { - this(null, klass); - } - - /** - * Special constructor for map, otherwise it is not possible to cast to O - * - * @param mapClass map class - * @param name name of content - * @since 2.0.2 - */ - @SuppressWarnings({"unchecked"}) - public JAXXContextEntryDef(Class<Map> mapClass, String name) { - this(name, (Class<O>) mapClass); - } - - @SuppressWarnings("unchecked") - public JAXXContextEntryDef(String name, Class<O> klass) { - if (klass == null) { - throw new IllegalArgumentException("class can not be null"); - } - this.name = name; - if (List.class.isAssignableFrom(klass)) { - klass = (Class<O>) List.class; - } - this.klass = klass; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof JAXXContextEntryDef<?>)) { - return false; - } - JAXXContextEntryDef<?> that = (JAXXContextEntryDef<?>) o; - return klass.equals(that.klass) && - !(name != null ? !name.equals(that.name) : that.name != null); - } - - @Override - public int hashCode() { - int result = name != null ? name.hashCode() : 0; - return 31 * result + klass.hashCode(); - } - - public boolean accept(Class<?> klass, String name) { - if (Object.class.equals(klass) && !Object.class.equals(this.klass)) { - // try on name only - return this.name != null && name != null && this.name.equals(name); - } - return klass.isAssignableFrom(this.klass) && (this.name == null && name == null - || (this.name != null && name != null && this.name.equals(name))); - } - - public boolean accept2(Class<?> klass, String name) { - return !(Object.class.equals(klass) && - !Object.class.equals(this.klass)) && - this.klass.isAssignableFrom(klass) && - (this.name == null && name == null || - (this.name != null && name != null && this.name.equals(name)) - ); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/context/JAXXInitialContext.java b/jaxx-runtime/src/main/java/jaxx/runtime/context/JAXXInitialContext.java deleted file mode 100644 index 9422379..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/context/JAXXInitialContext.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.context; - -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXObject; - -import java.util.Map.Entry; - -/** - * An initial context to be inject in a {@link JAXXObject}. - * - * The method {@link #add(Object)} register a simple value. - * - * The method {@link #add(String, Object)} register a named value. - * - * The method {@link #to(JAXXContext)} inject in the {@link JAXXObject} the values registred in the initial context. - * - * The initial context is also a "limited" {@link JAXXContext}, since we can only use the two methods - * - * {@link #getContextValue(Class)} or {@link #getContextValue(Class, String)}. - * - * @see JAXXContext - */ -public class JAXXInitialContext extends DefaultJAXXContext { - - public JAXXInitialContext() { - super(); - } - - /** - * Register a simple (none named) value in the context. - * - * @param value the value to be registred in the context - * @return the instance of the context - */ - public JAXXInitialContext add(Object value) { - return add((String) null, value); - } - - /** - * Register a named value in the context. - * - * @param name the name of the value - * @param value the value to registred - * @return the instance of the context - */ - public JAXXInitialContext add(String name, Object value) { - super.setContextValue(value, name); - return this; - } - - /** - * Register a named (or not) value in the context. - * - * @param <O> type of data to add - * @param def definition of entry - * @param value the value to registred - * @return the instance of the context - */ - public <O> JAXXInitialContext add(JAXXContextEntryDef<O> def, O value) { - super.setContextValue(value, def.getName()); - return this; - } - - /** - * Inject all the registed values into the {@link JAXXObject} - * - * @param dst the object to fill. - */ - public void to(JAXXContext dst) { - if (parentContext != null) { - dst.setContextValue(parentContext); - } - for (Entry<JAXXContextEntryDef<?>, Object> entry : data.entrySet()) { - dst.setContextValue(entry.getValue(), entry.getKey().getName()); - } - } - - @Override - public void setContextValue(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public void setContextValue(Object o, String name) { - throw new UnsupportedOperationException(); - } - - @Override - public <T> void removeContextValue(Class<T> klazz) { - throw new UnsupportedOperationException(); - } - - @Override - public <T> void removeContextValue(Class<T> klazz, String name) { - throw new UnsupportedOperationException(); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/css/DataBinding.java b/jaxx-runtime/src/main/java/jaxx/runtime/css/DataBinding.java deleted file mode 100644 index 4409557..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/css/DataBinding.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.css; - -/** - * Represents a data binding bound to an attribute at runtime. Used by {@link Pseudoclasses} to keep - * track of which data bindings are in effect. - */ -public class DataBinding { - - private String id; - - public DataBinding(String id) { - this.id = id; - } - - public String getId() { - return id; - } - - @Override - public boolean equals(Object o) { - return o instanceof DataBinding && ((DataBinding) o).getId().equals(getId()); - } - - @Override - public int hashCode() { - return id.hashCode(); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/css/Pseudoclasses.java b/jaxx-runtime/src/main/java/jaxx/runtime/css/Pseudoclasses.java deleted file mode 100644 index 4fc3536..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/css/Pseudoclasses.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.css; - -import jaxx.runtime.JAXXObject; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; - -public class Pseudoclasses { - - public static final String NO_PSEUDOCLASS = "no pseudoclass"; - - private static Map<Object, Map<String, List<PropertyValue>>> properties = new WeakHashMap<Object, Map<String, List<PropertyValue>>>(); - - private static class PropertyValue implements Comparable<PropertyValue> { - - private Object value; - - private int id; - - public PropertyValue(Object value, int id) { - this.value = value; - this.id = id; - } - - public Object getValue() { - return value; - } - - public int getId() { - return id; - } - - @Override - public int compareTo(PropertyValue o) { - return getId() - o.getId(); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof PropertyValue)) { - return false; - } - PropertyValue that = (PropertyValue) o; - if (that.getId() != getId()) { - return false; - } - if (that.getValue() == null) { - return getValue() == null; - } - return that.getValue().equals(getValue()); - } - - @Override - public int hashCode() { - return (value != null ? value.hashCode() : 0) ^ id; - } - - @Override - public String toString() { - return "PropertyValue[" + value + ", " + id + "]"; - } - } - - private static List<PropertyValue> getPropertyList(Object object, String property) { - Map<String, List<PropertyValue>> propertyMap = properties.get(object); - if (propertyMap == null) { - propertyMap = new HashMap<String, List<PropertyValue>>(); - properties.put(object, propertyMap); - } - - List<PropertyValue> propertyList = propertyMap.get(property); - if (propertyList == null) { - propertyList = new ArrayList<PropertyValue>(); - propertyMap.put(property, propertyList); - } - - return propertyList; - } - - public static boolean isPropertyApplied(Object object, String property, int id) { - for (PropertyValue aPropertyList : getPropertyList(object, property)) { - if (aPropertyList.getId() == id) { - return true; - } - } - return false; - } - - public static void propertyApplied(Object object, String property, Object value, int id) { - List<PropertyValue> propertyList = getPropertyList(object, property); - propertyList.add(new PropertyValue(value, id)); - Collections.sort(propertyList); - } - - public static void propertyRemoved(Object object, String property, Object value, int id) { - List<PropertyValue> propertyList = getPropertyList(object, property); - propertyList.remove(new PropertyValue(value, id)); - } - - public static Object getCurrentValue(Object object, String property) { - List<PropertyValue> propertyList = getPropertyList(object, property); - if (propertyList.size() > 0) { - return propertyList.get(propertyList.size() - 1).getValue(); - } - return NO_PSEUDOCLASS; - } - - public static Object applyProperty(JAXXObject parent, Object object, String property, Object newValue, Object currentValue, int id) { - if (!isPropertyApplied(object, property, id)) { - Object value = getCurrentValue(object, property); - if (value == NO_PSEUDOCLASS) { - propertyApplied(object, property, wrap(currentValue), -1); - } - propertyApplied(object, property, wrap(newValue), id); - value = getCurrentValue(object, property); - if (value instanceof DataBinding) { - parent.applyDataBinding(((DataBinding) value).getId()); - } - return value; - } else { - return currentValue; - } - } - - public static Object removeProperty(JAXXObject parent, Object object, String property, Object oldValue, Object currentValue, int id) { - if (isPropertyApplied(object, property, id)) { - Object value = getCurrentValue(object, property); - if (value == NO_PSEUDOCLASS) { - throw new IllegalStateException("found NO_PSEUDOCLASS value for a property which does not have a default value"); - } - if (value instanceof DataBinding) { - parent.removeDataBinding(((DataBinding) value).getId()); - } - propertyRemoved(object, property, wrap(oldValue), id); - value = getCurrentValue(object, property); - return value; - } else { - return currentValue; - } - } - - public static Object wrap(boolean value) { - return value; - } - - public static Object wrap(byte value) { - return value; - } - - public static Object wrap(short value) { - return value; - } - - public static Object wrap(int value) { - return value; - } - - public static Object wrap(long value) { - return value; - } - - public static Object wrap(float value) { - return value; - } - - public static Object wrap(double value) { - return value; - } - - public static Object wrap(char value) { - return value; - } - - public static Object wrap(Object value) { - return value; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/css/Rule.java b/jaxx-runtime/src/main/java/jaxx/runtime/css/Rule.java deleted file mode 100644 index 015996f..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/css/Rule.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.css; - -import java.util.Map; - -public class Rule implements java.io.Serializable, Comparable<Rule> { - - public static final String INLINE_ATTRIBUTE = "<inline attribute>"; - - public static final String DATA_BINDING = "<data binding>"; - - private Selector[] selectors; - - private Map<String, String> properties; - - private static final long serialVersionUID = 1L; - - public Rule(Selector[] selectors, Map<String, String> properties) { - this.selectors = selectors; - java.util.Arrays.sort(selectors); - this.properties = properties; - } - - public Rule(Selector[] selectors, String[] keys, String[] values) { - this.selectors = selectors; - java.util.Arrays.sort(selectors); - this.properties = new java.util.HashMap<String, String>(); - if (keys.length != values.length) { - throw new IllegalArgumentException("keys and values must have the same number of entries"); - } - for (int i = 0; i < keys.length; i++) { - properties.put(keys[i], values[i]); - } - } - - public Selector[] getSelectors() { - return selectors; - } - - public Map<String, String> getProperties() { - return properties; - } - - @Override - public int compareTo(Rule o) { - return selectors[0].compareTo(o.selectors[0]); // they are already sorted so we only need to compare the highest-ranked from each one - } - - @Override - public String toString() { - return "Rule[" + java.util.Arrays.asList(selectors) + ", " + properties + "]"; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/css/Selector.java b/jaxx-runtime/src/main/java/jaxx/runtime/css/Selector.java deleted file mode 100644 index dfff9ed..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/css/Selector.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.css; - -public class Selector implements java.io.Serializable, Comparable<Selector> { - - public static final int NEVER_APPLIES = 0; - - public static final int PSEUDOCLASS_APPLIES_INHERIT_ONLY = 1; - - public static final int PSEUDOCLASS_APPLIES = 2; - - public static final int ALWAYS_APPLIES_INHERIT_ONLY = 3; - - public static final int ALWAYS_APPLIES = 4; - - private String javaClassName; - - private String styleClass; - - private String pseudoClass; - - private String id; - - private boolean inline; - - private static final long serialVersionUID = 1L; - - public Selector(String javaClassName, String styleClass, String pseudoClass, String id) { - this(javaClassName, styleClass, pseudoClass, id, false); - } - - public Selector(String javaClassName, String styleClass, String pseudoClass, String id, boolean inline) { - this.javaClassName = javaClassName; - this.styleClass = styleClass; - this.pseudoClass = pseudoClass; - this.id = id; - this.inline = inline; - } - - public String getJavaClassName() { - return javaClassName; - } - - public String getStyleClass() { - return styleClass; - } - - public String getPseudoClass() { - return pseudoClass; - } - - public String getId() { - return id; - } - - public boolean isInline() { - return inline; - } - - @Override - public int compareTo(Selector selector) { - if (inline && !selector.inline) { - return 1; - } - if (!inline && selector.inline) { - return -1; - } - if (pseudoClass != null && selector.pseudoClass == null) { - return 1; - } - if (pseudoClass == null && selector.pseudoClass != null) { - return -1; - } - if (id != null && selector.id == null) { - return 1; - } - if (id == null && selector.id != null) { - return -1; - } - if (styleClass != null && selector.styleClass == null) { - return 1; - } - if (styleClass == null && selector.styleClass != null) { - return -1; - } - if (javaClassName != null && selector.javaClassName == null) { - return 1; - } - if (javaClassName == null && selector.javaClassName != null) { - return -1; - } - return 0; - } - - @Override - public String toString() { - return "Selector[" + javaClassName + ", " + styleClass + ", " + pseudoClass + ", " + id + "]"; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/css/Stylesheet.java b/jaxx-runtime/src/main/java/jaxx/runtime/css/Stylesheet.java deleted file mode 100644 index ebc182a..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/css/Stylesheet.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.css; - -public class Stylesheet implements java.io.Serializable { - - private Rule[] rules; - - private static final long serialVersionUID = 1L; - - public Stylesheet() { - rules = new Rule[0]; - } - - public Stylesheet(Rule[] rules) { - this.rules = rules; - java.util.Arrays.sort(rules); - } - - public Rule[] getRules() { - return rules; - } - - public void add(Rule newRule) { - Rule[] oldRules = rules; - rules = new Rule[oldRules.length + 1]; - System.arraycopy(oldRules, 0, rules, 0, oldRules.length); - rules[rules.length - 1] = newRule; - java.util.Arrays.sort(rules); - } - - public void add(Rule[] newRules) { - Rule[] oldRules = rules; - rules = new Rule[oldRules.length + newRules.length]; - System.arraycopy(oldRules, 0, rules, 0, oldRules.length); - System.arraycopy(newRules, 0, rules, oldRules.length, newRules.length); - java.util.Arrays.sort(rules); - } - - @Override - public String toString() { - return "Stylesheet" + java.util.Arrays.asList(rules); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/spi/UIHandler.java b/jaxx-runtime/src/main/java/jaxx/runtime/spi/UIHandler.java deleted file mode 100644 index 780e5c3..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/spi/UIHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -package jaxx.runtime.spi; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.JAXXObject; - -/** - * Created on 11/26/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public interface UIHandler<UI extends JAXXObject> { - - void beforeInit(UI ui); - - void afterInit(UI ui); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/Application.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/Application.java deleted file mode 100644 index a1ad913..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/Application.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.JFrame; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; -import java.awt.GraphicsConfiguration; - -public class Application extends JFrame { - - private static final long serialVersionUID = 1L; - // Special: jaxxc will automatically add a main() method to any components which - // extend <Application> - - public Application() { - } - - public Application(GraphicsConfiguration gc) { - super(gc); - } - - public Application(String title) { - super(title); - } - - public Application(String title, GraphicsConfiguration gc) { - super(title, gc); - } - - public void setLookAndFeel(String lookAndFeel) { - if (lookAndFeel.equals("system")) { - lookAndFeel = UIManager.getSystemLookAndFeelClassName(); - } else if (lookAndFeel.equals("cross_platform")) { - lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName(); - } - try { - UIManager.setLookAndFeel(lookAndFeel); - if (isDisplayable()) { - SwingUtilities.updateComponentTreeUI(this); - } - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } catch (InstantiationException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } catch (UnsupportedLookAndFeelException e) { - throw new RuntimeException(e); - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/BlockingLayerUI.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/BlockingLayerUI.java deleted file mode 100644 index 11c7e3b..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/BlockingLayerUI.java +++ /dev/null @@ -1,375 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import org.jdesktop.jxlayer.JXLayer; -import org.jdesktop.jxlayer.plaf.AbstractLayerUI; - -import javax.swing.Action; -import javax.swing.ImageIcon; -import javax.swing.JComponent; -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Component; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.RenderingHints; -import java.awt.event.ActionEvent; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseWheelEvent; -import java.awt.image.BufferedImage; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -/** - * A JXLayer ui implementation that permits to block a component but still - * allow an action when clicking on the right-top icon painted on the layer. - * - * You can change the blocking and accepting icon. - * - * To hook an click on the layer's icon, you can : - * - * <ul><li>pass an Action via method {@link #setAcceptAction(Action)}</li> - * <li>override the method {@link #acceptEvent(MouseEvent, JXLayer)}</li> - * </ul> - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.2 - */ -public class BlockingLayerUI extends AbstractLayerUI<JComponent> { - - public static final String CAN_CLICK_PROPERTY = "canClick"; - - public static final String ACCEPT_ICON_PROPERTY = "acceptIcon"; - - public static final String BLOCK_ICON_PROPERTY = "blockIcon"; - - public static final String BLOCK_PROPERTY = "block"; -// private static final long serialVersionUID = 1L; - - /** Action to be treated when click on icon */ - protected Action acceptAction; - - /** Icon when you can not click */ - protected BufferedImage blockIcon; - - /** Icon when you can click */ - protected BufferedImage acceptIcon; - - /** Optinal color to put fill background when blocking */ - protected Color blockingColor; - - /** Internal state to known when we can accept click */ - protected boolean canClick; - - /** - * A flag to enable or disable the use of the icon. - * - * If set to false, no icon will be displayed and no action - * will be possible. - * - * By default, this is active. - */ - protected boolean useIcon = true; - - /** Internal state when should block event and paint layer */ - protected boolean block; - - /** Extra components names to accept even in block mode */ - protected final Set<String> acceptedComponentNames; - - /** Extra components types to accept even in block mode */ - protected final Set<Class<?>> acceptedComponentTypes; - - public BlockingLayerUI() { - acceptedComponentNames = new HashSet<String>(); - acceptedComponentTypes = new HashSet<Class<?>>(); - } - - public void setAcceptedComponentNames(String... acceptedComponentNames) { - this.acceptedComponentNames.clear(); - this.acceptedComponentNames.addAll(Arrays.asList(acceptedComponentNames)); - setDirty(true); - } - - public void setAcceptedComponentTypes(Class<?>... acceptedComponentTypes) { - this.acceptedComponentTypes.clear(); - this.acceptedComponentTypes.addAll(Arrays.asList(acceptedComponentTypes)); - setDirty(true); - } - - public void setAcceptAction(Action acceptAction) { - this.acceptAction = acceptAction; - } - - public void setAcceptIcon(ImageIcon acceptIcon) { - this.acceptIcon = prepareIcon(acceptIcon); - firePropertyChange(ACCEPT_ICON_PROPERTY, null, acceptIcon); - setDirty(true); - } - - public void setBlockIcon(ImageIcon blockIcon) { - this.blockIcon = prepareIcon(blockIcon); - firePropertyChange(BLOCK_ICON_PROPERTY, null, blockIcon); - setDirty(true); - } - - public void setCanClick(boolean canClick) { - boolean oldvalue = this.canClick; - this.canClick = canClick; - firePropertyChange(CAN_CLICK_PROPERTY, oldvalue, canClick); - if (oldvalue != canClick) { - setDirty(true); - } - } - - public void setBlock(boolean block) { - boolean oldvalue = this.block; - this.block = block; - firePropertyChange(BLOCK_PROPERTY, oldvalue, block); - if (oldvalue != block) { - setDirty(true); - } - } - - @Override - public void setDirty(boolean isDirty) { - super.setDirty(isDirty); - } - - public void setBlockIcon(BufferedImage blockIcon) { - this.blockIcon = blockIcon; - } - - public void setBlockingColor(Color blockingColor) { - this.blockingColor = blockingColor; - } - - public BufferedImage getBlockIcon() { - return blockIcon; - } - - protected BufferedImage getAcceptIcon() { - return acceptIcon; - } - - public boolean isCanClick() { - return canClick; - } - - public void setUseIcon(boolean useIcon) { - boolean oldvalue = this.useIcon; - this.useIcon = useIcon; - if (oldvalue != useIcon) { - setDirty(true); - } - } - - @Override - public BlockingLayerUI clone() { - BlockingLayerUI clone = new BlockingLayerUI(); - clone.acceptAction = acceptAction; - clone.acceptIcon = acceptIcon; - clone.blockIcon = blockIcon; - clone.useIcon = useIcon; - clone.block = block; - clone.blockingColor = blockingColor; - clone.setCanClick(false); - return clone; - } - - @Override - protected void processKeyEvent(KeyEvent e, JXLayer<? extends JComponent> l) { - if (useIcon) { - e.consume(); - } else if (block) { - - acceptEventOrConsumeIt(e); - - } - } - - @Override - protected void processMouseMotionEvent(MouseEvent e, JXLayer<? extends JComponent> l) { - if (useIcon) { - updateCanClickState(l, e); - e.consume(); - } else if (block) { - - acceptEventOrConsumeIt(e); - - } - } - - @Override - protected void processMouseEvent(MouseEvent e, JXLayer<? extends JComponent> l) { - if (useIcon) { - switch (e.getID()) { - case MouseEvent.MOUSE_ENTERED: - updateCanClickState(l, e); - break; - case MouseEvent.MOUSE_EXITED: - setCanClick(false); - break; - case MouseEvent.MOUSE_CLICKED: - if (canClick) { - acceptEvent(e, l); - } - break; - } - e.consume(); - } else if (block) { - - if (acceptEventOrConsumeIt(e)) { - - switch (e.getID()) { - case MouseEvent.MOUSE_ENTERED: - break; - case MouseEvent.MOUSE_EXITED: - break; - case MouseEvent.MOUSE_CLICKED: - acceptEvent(e, l); - break; - } - - } - - } - - } - - @Override - protected void processMouseWheelEvent(MouseWheelEvent e, JXLayer<? extends JComponent> l) { - - if (useIcon) { - - e.consume(); - } else if (block) { - - if (acceptEventOrConsumeIt(e)) { - acceptEvent(e, l); - } - - } - - } - - protected boolean acceptEventOrConsumeIt(InputEvent e) { - - Object source = e.getSource(); - - boolean accept = source instanceof JComponent; - if (accept) { - - JComponent component = (JComponent) source; - - accept = acceptedComponentNames.contains(component.getName()); - - if (!accept) { - - for (Class<?> acceptedComponentType : acceptedComponentTypes) { - accept = acceptedComponentType.isAssignableFrom(component.getClass()); - if (accept) { - break; - } - } - - } - - } - - if (!accept) { - e.consume(); - } - - return accept; - - } - - @Override - protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { - super.paintLayer(g2, l); - if (block && blockingColor != null) { - // to be in sync with the view if the layer has a border - /*Insets layerInsets = l.getInsets(); - g2.translate(layerInsets.left, layerInsets.top); - - JComponent view = l.getView(); - // To prevent painting on view's border - Insets insets = view.getInsets(); - g2.clip(new Rectangle(insets.left, insets.top, - view.getWidth() - insets.left - insets.right, - view.getHeight() - insets.top - insets.bottom)); - */ - - g2.setColor(blockingColor); - g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .1f)); - g2.fillRect(0, 0, l.getWidth(), l.getHeight()); - } - if (useIcon && getCurrentIcon() != null) { - g2.drawImage(getCurrentIcon(), l.getWidth() - getCurrentIcon().getWidth() - 1, 0, null); - } - } - - protected void acceptEvent(MouseEvent e, JXLayer<? extends JComponent> l) { - if (acceptAction != null) { - acceptAction.putValue("layer", l); - Component source = l.getView(); - acceptAction.actionPerformed(new ActionEvent(source, 0, "accept")); - } - } - - protected BufferedImage getCurrentIcon() { - return canClick ? acceptIcon : blockIcon; - } - - protected BufferedImage prepareIcon(ImageIcon image) { - BufferedImage icon = new BufferedImage(image.getIconWidth(), image.getIconHeight(), BufferedImage.TYPE_INT_ARGB); - Graphics2D g2 = (Graphics2D) icon.getGraphics(); - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); - g2.drawImage(image.getImage(), 0, 0, null); - g2.dispose(); - return icon; - } - - protected void updateCanClickState(JXLayer<? extends JComponent> l, MouseEvent e) { - // udpate toolTipText - Point layerLocation = l.getView().getLocation(); - Point mousePoint = e.getPoint(); - BufferedImage currentIcon = getCurrentIcon(); - if (currentIcon == null) { - setCanClick(false); - return; - } - int minX = (int) layerLocation.getX() + l.getWidth() - currentIcon.getWidth(); - int maxX = (int) layerLocation.getX() + l.getWidth(); - int minY = 0; - int maxY = currentIcon.getHeight(); - boolean accept = minX <= mousePoint.getX() && mousePoint.getX() <= maxX; - accept &= minY <= mousePoint.getLocation().getY() && mousePoint.getLocation().getY() <= maxY; - setCanClick(accept); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/BlockingLayerUI2.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/BlockingLayerUI2.java deleted file mode 100644 index 54fa1b1..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/BlockingLayerUI2.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import org.jdesktop.jxlayer.JXLayer; -import org.jdesktop.jxlayer.plaf.AbstractLayerUI; - -import javax.swing.Action; -import javax.swing.ImageIcon; -import javax.swing.JComponent; -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Component; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.RenderingHints; -import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseWheelEvent; -import java.awt.image.BufferedImage; - -/** - * A JXLayer ui implementation that permits to block a component but still - * allow an action when clicking everywhere on the layer. - * - * Moreover, an icon can be added on the right-top icon painted and changed - * when the mouse is over the layer. - * - * You can change the blocking and accepting icon. - * - * To hook an click on the layer's icon, you can : - * - * <ul><li>pass an Action via method {@link #setAcceptAction(Action)}</li> - * <li>override the method {@link #acceptEvent(MouseEvent, JXLayer)}</li> - * </ul> - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.3 - */ -public class BlockingLayerUI2 extends AbstractLayerUI<JComponent> { - - public static final String CAN_CLICK_PROPERTY = "canClick"; - - public static final String ACCEPT_ICON_PROPERTY = "acceptIcon"; - - public static final String BLOCK_ICON_PROPERTY = "blockIcon"; - - /** Action to be treated when click on icon */ - protected Action acceptAction; - - /** Icon when you can not click */ - protected BufferedImage blockIcon; - - /** Icon when you can click */ - protected BufferedImage acceptIcon; - - /** Optinal color to put fill background when blocking */ - protected Color blockingColor; - - /** Internal state to known when we can accept click */ - protected boolean canClick; - - public void setAcceptAction(Action acceptAction) { - this.acceptAction = acceptAction; - } - - public void setAcceptIcon(ImageIcon acceptIcon) { - this.acceptIcon = prepareIcon(acceptIcon); - firePropertyChange(ACCEPT_ICON_PROPERTY, null, acceptIcon); - setDirty(true); - } - - public void setBlockIcon(ImageIcon blockIcon) { - this.blockIcon = prepareIcon(blockIcon); - firePropertyChange(BLOCK_ICON_PROPERTY, null, blockIcon); - setDirty(true); - } - - public void setCanClick(boolean canClick) { - boolean oldvalue = this.canClick; - this.canClick = canClick; - firePropertyChange(CAN_CLICK_PROPERTY, oldvalue, canClick); - if (oldvalue != canClick) { - setDirty(true); - } - } - - @Override - public void setDirty(boolean isDirty) { - super.setDirty(isDirty); - } - - public void setBlockingColor(Color blockingColor) { - this.blockingColor = blockingColor; - } - - public void setBlockIcon(BufferedImage blockIcon) { - this.blockIcon = blockIcon; - } - - public BufferedImage getBlockIcon() { - return blockIcon; - } - - protected BufferedImage getAcceptIcon() { - return acceptIcon; - } - - public boolean isCanClick() { - return canClick; - } - - @Override - public BlockingLayerUI2 clone() { - BlockingLayerUI2 clone = new BlockingLayerUI2(); - clone.acceptAction = acceptAction; - clone.acceptIcon = acceptIcon; - clone.blockIcon = blockIcon; - clone.blockingColor = blockingColor; - clone.setCanClick(false); - return clone; - } - - @Override - protected void processKeyEvent(KeyEvent e, JXLayer<? extends JComponent> l) { - e.consume(); - } - - @Override - protected void processMouseMotionEvent(MouseEvent e, JXLayer<? extends JComponent> l) { - e.consume(); - } - - @Override - protected void processMouseWheelEvent(MouseWheelEvent e, JXLayer<? extends JComponent> l) { - e.consume(); - } - - @Override - protected void processMouseEvent(MouseEvent e, JXLayer<? extends JComponent> l) { - switch (e.getID()) { - case MouseEvent.MOUSE_ENTERED: - setCanClick(true); - break; - case MouseEvent.MOUSE_EXITED: - setCanClick(false); - break; - case MouseEvent.MOUSE_CLICKED: - if (canClick) { - acceptEvent(e, l); - } - break; - } - e.consume(); - } - - @Override - protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { - super.paintLayer(g2, l); - if (blockingColor != null) { - // to be in sync with the view if the layer has a border - /*Insets layerInsets = l.getInsets(); - g2.translate(layerInsets.left, layerInsets.top); - - JComponent view = l.getView(); - // To prevent painting on view's border - Insets insets = view.getInsets(); - g2.clip(new Rectangle(insets.left, insets.top, - view.getWidth() - insets.left - insets.right, - view.getHeight() - insets.top - insets.bottom)); - */ - - g2.setColor(blockingColor); - g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .1f)); - g2.fillRect(0, 0, l.getWidth(), l.getHeight()); - } - if (getCurrentIcon() != null) { - g2.drawImage(getCurrentIcon(), l.getWidth() - getCurrentIcon().getWidth() - 1, 0, null); - } - } - - protected void acceptEvent(MouseEvent e, JXLayer<? extends JComponent> l) { - if (acceptAction != null) { - acceptAction.putValue("layer", l); - Component source = l.getView(); - acceptAction.actionPerformed(new ActionEvent(source, 0, "accept")); - } - } - - protected BufferedImage getCurrentIcon() { - return canClick ? acceptIcon : blockIcon; - } - - protected BufferedImage prepareIcon(ImageIcon image) { - BufferedImage icon = new BufferedImage(image.getIconWidth(), image.getIconHeight(), BufferedImage.TYPE_INT_ARGB); - Graphics2D g2 = (Graphics2D) icon.getGraphics(); - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); - g2.drawImage(image.getImage(), 0, 0, null); - g2.dispose(); - return icon; - } - - protected void updateCanClickState(JXLayer<JComponent> l, MouseEvent e) { - // udpate toolTipText - Point layerLocation = l.getView().getLocation(); - Point mousePoint = e.getPoint(); - BufferedImage currentIcon = getCurrentIcon(); - if (currentIcon == null) { - setCanClick(false); - return; - } - int minX = (int) layerLocation.getX() + l.getWidth() - currentIcon.getWidth(); - int maxX = (int) layerLocation.getX() + l.getWidth(); - int minY = 0; - int maxY = currentIcon.getHeight(); - boolean accept = minX <= mousePoint.getX() && mousePoint.getX() <= maxX; - accept &= minY <= mousePoint.getLocation().getY() && mousePoint.getLocation().getY() <= maxY; - setCanClick(accept); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2.java deleted file mode 100644 index f0fa1a9..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.awt.CardLayout; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Insets; -import java.io.Serializable; -import java.util.LinkedList; -import java.util.List; - -/** - * An override of the awt {@link CardLayout}. - * - * Because in the original layout is not overridable : everything is package level accessible. - * - * This new class offers to test if a constrains (as a Serializable) is actually dealed by the layout, - * via the method {@link #contains(Serializable)}. - * - * We had also another method to obtain the current visible component in a container layouted by the class, - * via the method {@link #getVisibleComponent(Container)}. - * - * @author Tony Chemit - chemit@codelutin.com - * @version 1.0 - */ -public class CardLayout2 extends CardLayout { - - /** log */ - static private Log log = LogFactory.getLog(CardLayout2.class); - - private static final long serialVersionUID = 1L; - - /** list of already loaded context (since the {@link #vector} attribute is package visible... */ - protected List<Serializable> contexts = new LinkedList<Serializable>(); - - /** - * A flag to compute dimension only on visible component. - * - * This is usefull when we only care of the visible component. - */ - protected boolean useOnlyVisibleComponentDimension; - - @Override - public void addLayoutComponent(Component comp, Object constraints) { - super.addLayoutComponent(comp, constraints); - contexts.remove(constraints); - contexts.add((Serializable) constraints); - if (log.isDebugEnabled()) { - log.debug(this + " new constraints : " + constraints); - } - } - - public void removeLayoutComponent(Component comp, Serializable constraints) { - removeLayoutComponent(comp); - contexts.remove(constraints); - } - - /** - * Test if a constrains is contained in the layout. - * - * @param constraints l'identifiant a tester - * @return {@code true} si l'identifiant est deja present dans le - * layout, {@code false} otherwise. - */ - public boolean contains(Serializable constraints) { - return contexts.contains(constraints); - } - - /** - * Obtain the visible component in the container. - * - * @param container the container using this layout - * @return the component visible in the container. - */ - public Component getVisibleComponent(Container container) { - checkContainer(container); - for (Component component : container.getComponents()) { - if (component.isVisible()) { - return component; - } - } - // no component actually visible - return null; - } - - public Component getComponent(Container container, String constraints) { - checkContainer(container); - checkConstraints(constraints); - int index = contexts.indexOf(constraints); - return container.getComponents()[index]; - } - - /** - * Determines the preferred size of the container argument using - * this card layout. - * - * @param parent the parent container in which to do the layout - * @return the preferred dimensions to lay out the subcomponents - * of the specified container - * @see Container#getPreferredSize - * @see CardLayout#minimumLayoutSize - */ - @Override - public Dimension preferredLayoutSize(Container parent) { - Dimension dimension = null; - if (useOnlyVisibleComponentDimension) { - Component comp = getVisibleComponent(parent); - if (comp != null) { - dimension = comp.getPreferredSize(); - } - } - if (dimension == null) { - dimension = super.preferredLayoutSize(parent); - } - return dimension; - } - - /** - * Calculates the minimum size for the specified panel. - * - * @param parent the parent container in which to do the layout - * @return the minimum dimensions required to lay out the - * subcomponents of the specified container - * @see Container#doLayout - * @see CardLayout#preferredLayoutSize - */ - @Override - public Dimension minimumLayoutSize(Container parent) { - Dimension dimension = null; - if (useOnlyVisibleComponentDimension) { - Component comp = getVisibleComponent(parent); - if (comp != null) { - dimension = comp.getMinimumSize(); - } - } - if (dimension == null) { - dimension = super.minimumLayoutSize(parent); - } - return dimension; - } - - /** - * Returns the maximum dimensions for this layout given the components - * in the specified target container. - * - * @param target the component which needs to be laid out - * @see Container - * @see #minimumLayoutSize - * @see #preferredLayoutSize - */ - @Override - public Dimension maximumLayoutSize(Container target) { - Dimension dimension = null; - if (useOnlyVisibleComponentDimension) { - Component comp = getVisibleComponent(target); - if (comp != null) { - dimension = comp.getMaximumSize(); - } - } - if (dimension == null) { - dimension = super.maximumLayoutSize(target); - } - return dimension; - } - - /** - * Lays out the specified container using this card layout. - * - * Each component in the <code>parent</code> container is reshaped - * to be the size of the container, minus space for surrounding - * insets, horizontal gaps, and vertical gaps. - * - * @param parent the parent container in which to do the layout - * @see Container#doLayout - */ - @Override - public void layoutContainer(Container parent) { - if (useOnlyVisibleComponentDimension) { - Component comp = getVisibleComponent(parent); - if (comp != null) { - //dimension = comp.getMinimumSize(); - Insets insets = parent.getInsets(); - comp.setBounds(getHgap() + insets.left, getVgap() + insets.top, - parent.getWidth() - (getHgap() * 2 + insets.left + insets.right), - parent.getHeight() - (getVgap() * 2 + insets.top + insets.bottom)); - } else { - super.layoutContainer(parent); - } - } else { - super.layoutContainer(parent); - } - } - - public boolean isUseOnlyVisibleComponentDimension() { - return useOnlyVisibleComponentDimension; - } - - public void setUseOnlyVisibleComponentDimension(boolean useOnlyVisibleComponentDimension) { - this.useOnlyVisibleComponentDimension = useOnlyVisibleComponentDimension; - } - - /** - * remove from cardlayout and linked container all his components. - * - * @param parent the parent container linked with the layout - */ - public void reset(Container parent) { - checkContainer(parent); - for (Component component : parent.getComponents()) { - removeLayoutComponent(component); - parent.remove(component); - } - contexts.clear(); - - } - - protected void checkContainer(Container container) { - if (!equals(container.getLayout())) { - throw new IllegalArgumentException("the container is not managed by the current layout"); - } - } - - protected void checkConstraints(String constraints) { - if (!contains(constraints)) { - throw new IllegalArgumentException("the constraints '" + constraints + "' is not supported by this layout : " + contexts); - } - } - - public Serializable[] getContexts() { - return contexts.toArray(new Serializable[contexts.size()]); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2Ext.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2Ext.java deleted file mode 100644 index af8b87c..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2Ext.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import jaxx.runtime.JAXXObject; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.awt.Container; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; - -/** - * Une extension de {@link CardLayout2} pour pouvoir automatiquement afficher un - * contenu à partir de la propriété {@link #selected}. - * - * Ainsi, en changeant cette propriété via la méthode {@link #setSelected(String)}, - * le contenu sera changé automatiquement, ce qui permet une utilisation direct - * dans jaxx sans à avoir à écrire d'écouteur. - * - * @author Tony Chemit - chemit@codelutin.com - * @see CardLayout2 - * @since 1.3 - */ -public class CardLayout2Ext extends CardLayout2 { - - /** log */ - static private Log log = LogFactory.getLog(CardLayout2.class); - - private static final long serialVersionUID = 1L; - - public static final String SELECTED_PROPERTY_NAME = "selected"; - - /** pour propager les changements dans le modèle vers l'ui */ - protected PropertyChangeSupport pcs; - - /** le contenu sélectionné */ - protected String selected; - - private String containerName; - - private JAXXObject ui; - - private Container container; - - public CardLayout2Ext(JAXXObject ui, String containerName) { - pcs = new PropertyChangeSupport(this); - this.ui = ui; - this.containerName = containerName; - } - - public String getSelected() { - return selected; - } - - public String getPreviousSelected() { - int index = contexts.indexOf(selected); - if (index < 1) { - return null; - } - return contexts.get(index - 1) + ""; - } - - public String getNextSelected() { - int index = contexts.indexOf(selected); - if (index >= contexts.size()) { - return null; - } - return contexts.get(index + 1) + ""; - } - - public void setSelected(String selected) { - String oldSelected = this.selected; - this.selected = selected; - show(getContainer(), selected); - pcs.firePropertyChange(SELECTED_PROPERTY_NAME, oldSelected, selected); - } - - public Container getContainer() { - if (container == null) { - container = (Container) ui.getObjectById(containerName); - } - return container; - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - pcs.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - pcs.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.removePropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListeners() { - for (PropertyChangeListener l : pcs.getPropertyChangeListeners()) { - pcs.removePropertyChangeListener(l); - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/ComponentMover.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/ComponentMover.java deleted file mode 100644 index cfb956d..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/ComponentMover.java +++ /dev/null @@ -1,380 +0,0 @@ -package jaxx.runtime.swing; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - - -import javax.swing.JComponent; -import javax.swing.SwingUtilities; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.GraphicsEnvironment; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Window; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -/** - * This class allows you to move a Component by using a mouse. The Component - * moved can be a high level Window (ie. Window, Frame, Dialog) in which case - * the Window is moved within the desktop. Or the Component can belong to a - * Container in which case the Component is moved within the Container. - * - * When moving a Window, the listener can be added to a child Component of - * the Window. In this case attempting to move the child will result in the - * Window moving. For example, you might create a custom "Title Bar" for an - * undecorated Window and moving of the Window is accomplished by moving the - * title bar only. Multiple components can be registered as "window movers". - * - * Components can be registered when the class is created. Additional - * components can be added at any time using the registerComponent() method. - * - * @since 2.5.10 - */ -public class ComponentMover extends MouseAdapter { - private Insets dragInsets = new Insets(0, 0, 0, 0); - - private Dimension snapSize = new Dimension(1, 1); - - private Insets edgeInsets = new Insets(0, 0, 0, 0); - - private boolean changeCursor = true; - - private boolean autoLayout = false; - - private Class destinationClass; - - private Component destinationComponent; - - private Component destination; - - private Component source; - - private Point pressed; - - private Point location; - - private Cursor originalCursor; - - private boolean autoscrolls; - - private boolean potentialDrag; - - - /** - * Constructor for moving individual components. The components must be - * regisetered using the registerComponent() method. - */ - public ComponentMover() { - } - - /** - * Constructor to specify a Class of Component that will be moved when - * drag events are generated on a registered child component. The events - * will be passed to the first ancestor of this specified class. - * - * @param destinationClass the Class of the ancestor component - * @param components the Components to be registered for forwarding - * drag events to the ancestor Component. - */ - public ComponentMover(Class destinationClass, Component... components) { - this.destinationClass = destinationClass; - registerComponent(components); - } - - /** - * Constructor to specify a parent component that will be moved when drag - * events are generated on a registered child component. - * - * @param destinationComponent the component drage events should be forwareded to - * @param components the Components to be registered for forwarding drag - * events to the parent component to be moved - */ - public ComponentMover(Component destinationComponent, Component... components) { - this.destinationComponent = destinationComponent; - registerComponent(components); - } - - /** - * Get the auto layout property - * - * @return the auto layout property - */ - public boolean isAutoLayout() { - return autoLayout; - } - - /** - * Set the auto layout property - * - * @param autoLayout when true layout will be invoked on the parent container - */ - public void setAutoLayout(boolean autoLayout) { - this.autoLayout = autoLayout; - } - - /** - * Get the change cursor property - * - * @return the change cursor property - */ - public boolean isChangeCursor() { - return changeCursor; - } - - /** - * Set the change cursor property - * - * @param changeCursor when true the cursor will be changed to the - * Cursor.MOVE_CURSOR while the mouse is pressed - */ - public void setChangeCursor(boolean changeCursor) { - this.changeCursor = changeCursor; - } - - /** - * Get the drag insets - * - * @return the drag insets - */ - public Insets getDragInsets() { - return dragInsets; - } - - /** - * Set the drag insets. The insets specify an area where mouseDragged - * events should be ignored and therefore the component will not be moved. - * This will prevent these events from being confused with a - * MouseMotionListener that supports component resizing. - * - * @param dragInsets - */ - public void setDragInsets(Insets dragInsets) { - this.dragInsets = dragInsets; - } - - /** - * Get the bounds insets - * - * @return the bounds insets - */ - public Insets getEdgeInsets() { - return edgeInsets; - } - - /** - * Set the edge insets. The insets specify how close to each edge of the parent - * component that the child component can be moved. Positive values means the - * component must be contained within the parent. Negative values means the - * component can be moved outside the parent. - * - * @param edgeInsets - */ - public void setEdgeInsets(Insets edgeInsets) { - this.edgeInsets = edgeInsets; - } - - /** - * Remove listeners from the specified component - * - * @param components the component the listeners are removed from - */ - public void deregisterComponent(Component... components) { - for (Component component : components) - component.removeMouseListener(this); - } - - /** - * Add the required listeners to the specified component - * - * @param components the component the listeners are added to - */ - public void registerComponent(Component... components) { - for (Component component : components) - component.addMouseListener(this); - } - - /** - * Get the snap size - * - * @return the snap size - */ - public Dimension getSnapSize() { - return snapSize; - } - - /** - * Set the snap size. Forces the component to be snapped to - * the closest grid position. Snapping will occur when the mouse is - * dragged half way. - */ - public void setSnapSize(Dimension snapSize) { - if (snapSize.width < 1 - || snapSize.height < 1) - throw new IllegalArgumentException("Snap sizes must be greater than 0"); - - this.snapSize = snapSize; - } - - /** - * Setup the variables used to control the moving of the component: - * - * source - the source component of the mouse event - * destination - the component that will ultimately be moved - * pressed - the Point where the mouse was pressed in the destination - * component coordinates. - */ - @Override - public void mousePressed(MouseEvent e) { - source = e.getComponent(); - int width = source.getSize().width - dragInsets.left - dragInsets.right; - int height = source.getSize().height - dragInsets.top - dragInsets.bottom; - Rectangle r = new Rectangle(dragInsets.left, dragInsets.top, width, height); - - if (r.contains(e.getPoint())) - setupForDragging(e); - } - - private void setupForDragging(MouseEvent e) { - source.addMouseMotionListener(this); - potentialDrag = true; - - // Determine the component that will ultimately be moved - - if (destinationComponent != null) { - destination = destinationComponent; - } else if (destinationClass == null) { - destination = source; - } else // forward events to destination component - { - destination = SwingUtilities.getAncestorOfClass(destinationClass, source); - } - - pressed = e.getLocationOnScreen(); - location = destination.getLocation(); - - if (changeCursor) { - originalCursor = source.getCursor(); - source.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); - } - - // Making sure autoscrolls is false will allow for smoother dragging of - // individual components - - if (destination instanceof JComponent) { - JComponent jc = (JComponent) destination; - autoscrolls = jc.getAutoscrolls(); - jc.setAutoscrolls(false); - } - } - - /** - * Move the component to its new location. The dragged Point must be in - * the destination coordinates. - */ - @Override - public void mouseDragged(MouseEvent e) { - Point dragged = e.getLocationOnScreen(); - int dragX = getDragDistance(dragged.x, pressed.x, snapSize.width); - int dragY = getDragDistance(dragged.y, pressed.y, snapSize.height); - - int locationX = location.x + dragX; - int locationY = location.y + dragY; - - // Mouse dragged events are not generated for every pixel the mouse - // is moved. Adjust the location to make sure we are still on a - // snap value. - - while (locationX < edgeInsets.left) - locationX += snapSize.width; - - while (locationY < edgeInsets.top) - locationY += snapSize.height; - - Dimension d = getBoundingSize(destination); - - while (locationX + destination.getSize().width + edgeInsets.right > d.width) - locationX -= snapSize.width; - - while (locationY + destination.getSize().height + edgeInsets.bottom > d.height) - locationY -= snapSize.height; - - // Adjustments are finished, move the component - - destination.setLocation(locationX, locationY); - } - - /* - * Determine how far the mouse has moved from where dragging started - * (Assume drag direction is down and right for positive drag distance) - */ - private int getDragDistance(int larger, int smaller, int snapSize) { - int halfway = snapSize / 2; - int drag = larger - smaller; - drag += (drag < 0) ? -halfway : halfway; - drag = (drag / snapSize) * snapSize; - - return drag; - } - - /* - * Get the bounds of the parent of the dragged component. - */ - private Dimension getBoundingSize(Component source) { - if (source instanceof Window) { - GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); - Rectangle bounds = env.getMaximumWindowBounds(); - return new Dimension(bounds.width, bounds.height); - } else { - return source.getParent().getSize(); - } - } - - /** Restore the original state of the Component */ - @Override - public void mouseReleased(MouseEvent e) { - if (!potentialDrag) return; - - source.removeMouseMotionListener(this); - potentialDrag = false; - - if (changeCursor) - source.setCursor(originalCursor); - - if (destination instanceof JComponent) { - ((JComponent) destination).setAutoscrolls(autoscrolls); - } - - // Layout the components on the parent container - - if (autoLayout) { - if (destination instanceof JComponent) { - ((JComponent) destination).revalidate(); - } else { - destination.validate(); - } - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/ComponentResizer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/ComponentResizer.java deleted file mode 100644 index 3a7c11e..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/ComponentResizer.java +++ /dev/null @@ -1,475 +0,0 @@ -package jaxx.runtime.swing; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - - -import javax.swing.JComponent; -import javax.swing.SwingUtilities; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.GraphicsEnvironment; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Window; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.HashMap; -import java.util.Map; - -/** - * The ComponentResizer allows you to resize a component by dragging a border - * of the component. - * - * @since 2.5.10 - */ -public class ComponentResizer extends MouseAdapter { - - public static final String DIRECTION_VERTICAL = "vertical"; - public static final String DIRECTION_HORIZONTAL = "horizontal"; - public static final String DIRECTION_BOTH = "both"; - - private final static Dimension MINIMUM_SIZE = new Dimension(10, 10); - - private final static Dimension MAXIMUM_SIZE = - new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); - - private static Map<Integer, Integer> cursors = new HashMap<Integer, Integer>(); - - static { - cursors.put(1, Cursor.N_RESIZE_CURSOR); - cursors.put(2, Cursor.W_RESIZE_CURSOR); - cursors.put(4, Cursor.S_RESIZE_CURSOR); - cursors.put(8, Cursor.E_RESIZE_CURSOR); - cursors.put(3, Cursor.NW_RESIZE_CURSOR); - cursors.put(9, Cursor.NE_RESIZE_CURSOR); - cursors.put(6, Cursor.SW_RESIZE_CURSOR); - cursors.put(12, Cursor.SE_RESIZE_CURSOR); - } - - private Insets dragInsets; - - private Dimension snapSize; - - private int direction; - - protected static final int NORTH = 1; - - protected static final int WEST = 2; - - protected static final int SOUTH = 4; - - protected static final int EAST = 8; - - private Cursor sourceCursor; - - private boolean resizing; - - private Rectangle bounds; - - private Point pressed; - - private boolean autoscrolls; - - private Dimension minimumSize = MINIMUM_SIZE; - - private Dimension maximumSize = MAXIMUM_SIZE; - - protected Map<Component, String> authorizedDirectionByComponent = new HashMap<Component, String>(); - - /** - * Convenience contructor. All borders are resizable in increments of - * a single pixel. Components must be registered separately. - */ - public ComponentResizer() { - this(new Insets(5, 5, 5, 5), new Dimension(1, 1)); - } - - /** - * Convenience contructor. All borders are resizable in increments of - * a single pixel. Components can be registered when the class is created - * or they can be registered separately afterwards. - * - * @param components components to be automatically registered - */ - public ComponentResizer(Component... components) { - this(new Insets(5, 5, 5, 5), new Dimension(1, 1), components); - } - - /** - * Convenience contructor. Eligible borders are resisable in increments of - * a single pixel. Components can be registered when the class is created - * or they can be registered separately afterwards. - * - * @param dragInsets Insets specifying which borders are eligible to be - * resized. - * @param components components to be automatically registered - */ - public ComponentResizer(Insets dragInsets, Component... components) { - this(dragInsets, new Dimension(1, 1), components); - } - - /** - * Create a ComponentResizer. - * - * @param dragInsets Insets specifying which borders are eligible to be - * resized. - * @param snapSize Specify the dimension to which the border will snap to - * when being dragged. Snapping occurs at the halfway mark. - * @param components components to be automatically registered - */ - public ComponentResizer(Insets dragInsets, Dimension snapSize, Component... components) { - setDragInsets(dragInsets); - setSnapSize(snapSize); - registerComponent(components); - } - - /** - * Get the drag insets - * - * @return the drag insets - */ - public Insets getDragInsets() { - return dragInsets; - } - - /** - * Set the drag dragInsets. The insets specify an area where mouseDragged - * events are recognized from the edge of the border inwards. A value of - * 0 for any size will imply that the border is not resizable. Otherwise - * the appropriate drag cursor will appear when the mouse is inside the - * resizable border area. - * - * @param dragInsets Insets to control which borders are resizeable. - */ - public void setDragInsets(Insets dragInsets) { - validateMinimumAndInsets(minimumSize, dragInsets); - - this.dragInsets = dragInsets; - } - - /** - * Get the components maximum size. - * - * @return the maximum size - */ - public Dimension getMaximumSize() { - return maximumSize; - } - - /** - * Specify the maximum size for the component. The component will still - * be constrained by the size of its parent. - * - * @param maximumSize the maximum size for a component. - */ - public void setMaximumSize(Dimension maximumSize) { - this.maximumSize = maximumSize; - } - - /** - * Get the components minimum size. - * - * @return the minimum size - */ - public Dimension getMinimumSize() { - return minimumSize; - } - - /** - * Specify the minimum size for the component. The minimum size is - * constrained by the drag insets. - * - * @param minimumSize the minimum size for a component. - */ - public void setMinimumSize(Dimension minimumSize) { - validateMinimumAndInsets(minimumSize, dragInsets); - - this.minimumSize = minimumSize; - } - - /** - * Remove listeners from the specified component - * - * @param components the component the listeners are removed from - */ - public void deregisterComponent(Component... components) { - for (Component component : components) { - component.removeMouseListener(this); - component.removeMouseMotionListener(this); - authorizedDirectionByComponent.remove(component); - } - } - - /** - * Add the required listeners to the specified component - * - * @param components the component the listeners are added to - */ - public void registerComponent(Component... components) { - registerComponent(DIRECTION_BOTH, components); - } - - public void registerComponent(String authorizedDirection, Component... components) { - for (Component component : components) { - component.addMouseListener(this); - component.addMouseMotionListener(this); - authorizedDirectionByComponent.put(component, authorizedDirection); - } - } - - /** - * Get the snap size. - * - * @return the snap size. - */ - public Dimension getSnapSize() { - return snapSize; - } - - /** - * Control how many pixels a border must be dragged before the size of - * the component is changed. The border will snap to the size once - * dragging has passed the halfway mark. - * - * @param snapSize Dimension object allows you to separately spcify a - * horizontal and vertical snap size. - */ - public void setSnapSize(Dimension snapSize) { - this.snapSize = snapSize; - } - - /** - * When the components minimum size is less than the drag insets then - * we can't determine which border should be resized so we need to - * prevent this from happening. - */ - private void validateMinimumAndInsets(Dimension minimum, Insets drag) { - int minimumWidth = drag.left + drag.right; - int minimumHeight = drag.top + drag.bottom; - - if (minimum.width < minimumWidth - || minimum.height < minimumHeight) { - String message = "Minimum size cannot be less than drag insets"; - throw new IllegalArgumentException(message); - } - } - - /** - */ - @Override - public void mouseMoved(MouseEvent e) { - Component source = e.getComponent(); - Point location = e.getPoint(); - direction = 0; - - String authorizedDirection = authorizedDirectionByComponent.get(source); - - if (location.x < dragInsets.left && !DIRECTION_VERTICAL.equals(authorizedDirection)) - direction += WEST; - - if (location.x > source.getWidth() - dragInsets.right - 1 && !DIRECTION_VERTICAL.equals(authorizedDirection)) - direction += EAST; - - if (location.y < dragInsets.top && !DIRECTION_HORIZONTAL.equals(authorizedDirection)) - direction += NORTH; - - if (location.y > source.getHeight() - dragInsets.bottom - 1 && !DIRECTION_HORIZONTAL.equals(authorizedDirection)) - direction += SOUTH; - - // Mouse is no longer over a resizable border - - if (direction == 0) { - source.setCursor(sourceCursor); - } else // use the appropriate resizable cursor - { - int cursorType = cursors.get(direction); - Cursor cursor = Cursor.getPredefinedCursor(cursorType); - source.setCursor(cursor); - } - } - - @Override - public void mouseEntered(MouseEvent e) { - if (!resizing) { - Component source = e.getComponent(); - sourceCursor = source.getCursor(); - } - } - - @Override - public void mouseExited(MouseEvent e) { - if (!resizing) { - Component source = e.getComponent(); - source.setCursor(sourceCursor); - } - } - - @Override - public void mousePressed(MouseEvent e) { - // The mouseMoved event continually updates this variable - - if (direction == 0) return; - - // Setup for resizing. All future dragging calculations are done based - // on the original bounds of the component and mouse pressed location. - - resizing = true; - - Component source = e.getComponent(); - pressed = e.getPoint(); - SwingUtilities.convertPointToScreen(pressed, source); - bounds = source.getBounds(); - - // Making sure autoscrolls is false will allow for smoother resizing - // of components - - if (source instanceof JComponent) { - JComponent jc = (JComponent) source; - autoscrolls = jc.getAutoscrolls(); - jc.setAutoscrolls(false); - } - } - - /** Restore the original state of the Component */ - @Override - public void mouseReleased(MouseEvent e) { - resizing = false; - - Component source = e.getComponent(); - source.setCursor(sourceCursor); - - if (source instanceof JComponent) { - ((JComponent) source).setAutoscrolls(autoscrolls); - } - } - - /** - * Resize the component ensuring location and size is within the bounds - * of the parent container and that the size is within the minimum and - * maximum constraints. - * - * All calculations are done using the bounds of the component when the - * resizing started. - */ - @Override - public void mouseDragged(MouseEvent e) { - if (resizing == false) return; - - Component source = e.getComponent(); - Point dragged = e.getPoint(); - SwingUtilities.convertPointToScreen(dragged, source); - - changeBounds(source, direction, bounds, pressed, dragged); - } - - protected void changeBounds(Component source, int direction, Rectangle bounds, Point pressed, Point current) { - // Start with original locaton and size - - int x = bounds.x; - int y = bounds.y; - int width = bounds.width; - int height = bounds.height; - - // Resizing the West or North border affects the size and location - - if (WEST == (direction & WEST)) { - int drag = getDragDistance(pressed.x, current.x, snapSize.width); - int maximum = Math.min(width + x, maximumSize.width); - drag = getDragBounded(drag, snapSize.width, width, minimumSize.width, maximum); - - x -= drag; - width += drag; - } - - if (NORTH == (direction & NORTH)) { - int drag = getDragDistance(pressed.y, current.y, snapSize.height); - int maximum = Math.min(height + y, maximumSize.height); - drag = getDragBounded(drag, snapSize.height, height, minimumSize.height, maximum); - - y -= drag; - height += drag; - } - - // Resizing the East or South border only affects the size - - if (EAST == (direction & EAST)) { - int drag = getDragDistance(current.x, pressed.x, snapSize.width); - Dimension boundingSize = getBoundingSize(source); - int maximum = Math.min(boundingSize.width - x, maximumSize.width); - drag = getDragBounded(drag, snapSize.width, width, minimumSize.width, maximum); - width += drag; - } - - if (SOUTH == (direction & SOUTH)) { - int drag = getDragDistance(current.y, pressed.y, snapSize.height); - Dimension boundingSize = getBoundingSize(source); - int maximum = Math.min(boundingSize.height - y, maximumSize.height); - drag = getDragBounded(drag, snapSize.height, height, minimumSize.height, maximum); - height += drag; - } - - source.setBounds(x, y, width, height); - source.validate(); - } - - /* - * Determine how far the mouse has moved from where dragging started - */ - private int getDragDistance(int larger, int smaller, int snapSize) { - int halfway = snapSize / 2; - int drag = larger - smaller; - drag += (drag < 0) ? -halfway : halfway; - drag = (drag / snapSize) * snapSize; - - return drag; - } - - /* - * Adjust the drag value to be within the minimum and maximum range. - */ - private int getDragBounded(int drag, int snapSize, int dimension, int minimum, int maximum) { - while (dimension + drag < minimum) - drag += snapSize; - - while (dimension + drag > maximum) - drag -= snapSize; - - - return drag; - } - - /* - * Keep the size of the component within the bounds of its parent. - */ - private Dimension getBoundingSize(Component source) { - if (source instanceof Window) { - GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); - Rectangle bounds = env.getMaximumWindowBounds(); - return new Dimension(bounds.width, bounds.height); - } else { - return source.getParent().getSize(); - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/GBC.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/GBC.java deleted file mode 100644 index 4bc3230..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/GBC.java +++ /dev/null @@ -1,132 +0,0 @@ -/* %%Ignore-License -GBC - A convenience class to tame the GridBagLayout - -Copyright (C) 2002 Cay S. Horstmann (http://horstmann.com) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -package jaxx.runtime.swing; - -import java.awt.GridBagConstraints; -import java.awt.Insets; - -/** - * This class simplifies the use of the GridBagConstraints - * class. - */ -public class GBC extends GridBagConstraints { - private static final long serialVersionUID = -3626882543530638704L; - - /** - * Constructs a GBC with a given gridx and gridy position and - * all other grid bag constraint values set to the default. - * - * @param gridx the gridx position - * @param gridy the gridy position - */ - public GBC(int gridx, int gridy) { - this.gridx = gridx; - this.gridy = gridy; - } - - /** - * Constructs a GBC with given gridx, gridy, gridwidth, gridheight - * and all other grid bag constraint values set to the default. - * - * @param gridx the gridx position - * @param gridy the gridy position - * @param gridwidth the cell span in x-direction - * @param gridheight the cell span in y-direction - */ - public GBC(int gridx, int gridy, int gridwidth, int gridheight) { - this.gridx = gridx; - this.gridy = gridy; - this.gridwidth = gridwidth; - this.gridheight = gridheight; - } - - /** - * Sets the anchor. - * - * @param anchor the anchor value - * @return this object for further modification - */ - public GBC setAnchor(int anchor) { - this.anchor = anchor; - return this; - } - - /** - * Sets the fill direction. - * - * @param fill the fill direction - * @return this object for further modification - */ - public GBC setFill(int fill) { - this.fill = fill; - return this; - } - - /** - * Sets the cell weights. - * - * @param weightx the cell weight in x-direction - * @param weighty the cell weight in y-direction - * @return this object for further modification - */ - public GBC setWeight(double weightx, double weighty) { - this.weightx = weightx; - this.weighty = weighty; - return this; - } - - /** - * Sets the insets of this cell. - * - * @param distance the spacing to use in all directions - * @return this object for further modification - */ - public GBC setInsets(int distance) { - this.insets = new Insets(distance, distance, distance, distance); - return this; - } - - /** - * Sets the insets of this cell. - * - * @param top the spacing to use on top - * @param left the spacing to use to the left - * @param bottom the spacing to use on the bottom - * @param right the spacing to use to the right - * @return this object for further modification - */ - public GBC setInsets(int top, int left, int bottom, int right) { - this.insets = new Insets(top, left, bottom, right); - return this; - } - - /** - * Sets the internal padding - * - * @param ipadx the internal padding in x-direction - * @param ipady the internal padding in y-direction - * @return this object for further modification - */ - public GBC setIpad(int ipadx, int ipady) { - this.ipadx = ipadx; - this.ipady = ipady; - return this; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBox.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBox.java deleted file mode 100644 index 5dc3517..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBox.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.JPanel; -import java.awt.Insets; - -/** - * Panel which uses an {@link HBoxLayout} by default. - * - * @author Ethan Nicholas - */ -public class HBox extends JPanel { - - private static final long serialVersionUID = 1L; - - public static final String SPACING_PROPERTY = "spacing"; - - public static final String MARGIN_PROPERTY = "margin"; - - public static final String HORIZONTAL_ALIGNMENT_PROPERTY = "horizontalAlignment"; - - public static final String VERTICAL_ALIGNMENT_PROPERTY = "verticalAlignment"; - - private Insets margin; - - public HBox() { - super(new HBoxLayout()); - } - - /** - * Returns the spacing between components, in pixels. Spacing is applied between components only, - * not to the top or bottom of the container. - * - * @return spacing between components - */ - public int getSpacing() { - return ((HBoxLayout) getLayout()).getSpacing(); - } - - /** - * Sets the spacing between components. Spacing is applied between components only, - * not to the top or bottom of the container. - * - * @param spacing new spacing value - */ - public void setSpacing(int spacing) { - int oldValue = getSpacing(); - ((HBoxLayout) getLayout()).setSpacing(spacing); - firePropertyChange(SPACING_PROPERTY, oldValue, spacing); - revalidate(); - } - - public int getHorizontalAlignment() { - return ((HBoxLayout) getLayout()).getHorizontalAlignment(); - } - - public void setHorizontalAlignment(int horizontalAlignment) { - int oldValue = getHorizontalAlignment(); - ((HBoxLayout) getLayout()).setHorizontalAlignment(horizontalAlignment); - firePropertyChange(HORIZONTAL_ALIGNMENT_PROPERTY, oldValue, horizontalAlignment); - revalidate(); - } - - public int getVerticalAlignment() { - return ((HBoxLayout) getLayout()).getVerticalAlignment(); - } - - public void setVerticalAlignment(int verticalAlignment) { - int oldValue = getVerticalAlignment(); - ((HBoxLayout) getLayout()).setVerticalAlignment(verticalAlignment); - firePropertyChange(VERTICAL_ALIGNMENT_PROPERTY, oldValue, verticalAlignment); - revalidate(); - } - - public Insets getMargin() { - return margin; - } - - public void setMargin(Insets margin) { - Insets oldValue = this.margin; - this.margin = (Insets) margin.clone(); - firePropertyChange(MARGIN_PROPERTY, oldValue, margin); - } - - @Override - public Insets getInsets() { - Insets result = super.getInsets(); - if (margin != null) { - result.top += margin.top; - result.left += margin.left; - result.right += margin.right; - result.bottom += margin.bottom; - } - return result; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBoxBeanInfo.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBoxBeanInfo.java deleted file mode 100644 index 4302590..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBoxBeanInfo.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.beans.SimpleBeanInfo; - -public class HBoxBeanInfo extends SimpleBeanInfo { - - @Override - public BeanInfo[] getAdditionalBeanInfo() { - try { - return new BeanInfo[]{Introspector.getBeanInfo(JPanel.class)}; - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - } - - @Override - public PropertyDescriptor[] getPropertyDescriptors() { - try { - PropertyDescriptor spacing = new PropertyDescriptor("spacing", HBox.class); - spacing.setBound(true); - - PropertyDescriptor margin = new PropertyDescriptor("margin", HBox.class); - margin.setBound(true); - - PropertyDescriptor horizontalAlignment = new PropertyDescriptor("horizontalAlignment", HBox.class); - horizontalAlignment.setBound(true); - horizontalAlignment.setValue("enumerationValues", new Object[]{ - "left", SwingConstants.LEFT, "SwingConstants.LEFT", - "center", SwingConstants.CENTER, "SwingConstants.CENTER", - "right", SwingConstants.RIGHT, "SwingConstants.RIGHT" - }); - - PropertyDescriptor verticalAlignment = new PropertyDescriptor("verticalAlignment", HBox.class); - verticalAlignment.setBound(true); - verticalAlignment.setValue("enumerationValues", new Object[]{ - "top", SwingConstants.TOP, "SwingConstants.TOP", - "middle", SwingConstants.CENTER, "SwingConstants.CENTER", - "bottom", SwingConstants.BOTTOM, "SwingConstants.BOTTOM" - }); - - return new PropertyDescriptor[]{spacing, margin, horizontalAlignment, verticalAlignment}; - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBoxLayout.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBoxLayout.java deleted file mode 100644 index fff4baf..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBoxLayout.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.SwingConstants; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Insets; -import java.awt.LayoutManager; - -/** - * Horizontal box layout. The layout rules followed by this class are quite different than the core BoxLayout class, - * and in general represent a more useful algorithm. - * - * @author Ethan Nicholas - */ -public class HBoxLayout implements LayoutManager { - - private int spacing = 6; - - private int horizontalAlignment = SwingConstants.LEFT; - - private int verticalAlignment = SwingConstants.TOP; - - public int getSpacing() { - return spacing; - } - - public void setSpacing(int spacing) { - this.spacing = spacing; - } - - public int getHorizontalAlignment() { - return horizontalAlignment; - } - - public void setHorizontalAlignment(int horizontalAlignment) { - this.horizontalAlignment = horizontalAlignment; - } - - public int getVerticalAlignment() { - return verticalAlignment; - } - - public void setVerticalAlignment(int verticalAlignment) { - this.verticalAlignment = verticalAlignment; - } - - @Override - public void addLayoutComponent(String name, Component comp) { - } - - @Override - public void layoutContainer(Container parent) { - Insets insets = parent.getInsets(); - int parentHeight = parent.getSize().height - insets.top - insets.bottom; - int count = parent.getComponentCount(); - Dimension preferredSize = parent.getPreferredSize(); - int x; - switch (horizontalAlignment) { - case SwingConstants.LEFT: - x = insets.left; - break; - case SwingConstants.CENTER: - x = insets.left + (parent.getWidth() - preferredSize.width) / 2; - break; - case SwingConstants.RIGHT: - x = insets.left + (parent.getWidth() - preferredSize.width); - break; - default: - throw new IllegalArgumentException("invalid horizontal alignment: " + horizontalAlignment); - } - - for (int i = 0; i < count; i++) { - Component component = parent.getComponent(i); - Dimension childPreferredSize = component.getPreferredSize(); - int height = Math.min(childPreferredSize.height, parentHeight); - int y; - switch (verticalAlignment) { - case SwingConstants.TOP: - y = insets.top; - break; - case SwingConstants.CENTER: - y = insets.top + (parentHeight - childPreferredSize.height) / 2; - break; - case SwingConstants.BOTTOM: - y = insets.top + (parentHeight - childPreferredSize.height); - break; - default: - throw new IllegalArgumentException("invalid vertical alignment: " + verticalAlignment); - } - component.setBounds(x, y, childPreferredSize.width, height); - x += childPreferredSize.width + spacing; - } - } - - @Override - public Dimension minimumLayoutSize(Container parent) { - int width = (parent.getComponentCount() - 1) * spacing; - int height = 0; - for (int i = parent.getComponentCount() - 1; i >= 0; i--) { - Dimension minimumSize = parent.getComponent(i).getMinimumSize(); - width += minimumSize.width; - height = Math.max(height, minimumSize.height); - } - Insets insets = parent.getInsets(); - return new Dimension(width + insets.left + insets.right, height + insets.top + insets.bottom); - } - - @Override - public Dimension preferredLayoutSize(Container parent) { - int width = (parent.getComponentCount() - 1) * spacing; - int height = 0; - for (int i = parent.getComponentCount() - 1; i >= 0; i--) { - Dimension preferredSize = parent.getComponent(i).getPreferredSize(); - width += preferredSize.width; - height = Math.max(height, preferredSize.height); - } - Insets insets = parent.getInsets(); - return new Dimension(width + insets.left + insets.right, height + insets.top + insets.bottom); - } - - @Override - public void removeLayoutComponent(Component comp) { - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/Item.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/Item.java deleted file mode 100644 index c62737b..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/Item.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.event.SwingPropertyChangeSupport; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.util.ArrayList; -import java.util.List; - -// This needs to be split into two classes, Item and TreeItem - -/** - * An item in a component such as <code>JComboBox</code> or <code>JTree</code>. The <code>Item</code> - * class corresponds to the <code><item></code> tag in JAXX source files. - */ -public class Item { - - public static final String LABEL_PROPERTY = "label"; - - public static final String VALUE_PROPERTY = "value"; - - public static final String SELECTED_PROPERTY = "selected"; - - private String id; - - private String label; - - private Object value; - - private boolean selected; - - private List<Item> children; - - private Item parent; - - private PropertyChangeSupport propertyChangeSupport; - - /** - * Creates a new Item. This should only be called from compiled JAXX files. - * - * @param id the item's ID - * @param label the string that should be used to represent the item visually - * @param value the item's actual value - * @param selected <code>true</code> if the item should be selected by default - */ - public Item(String id, String label, Object value, boolean selected) { - this.id = id; - this.label = label; - this.value = value; - this.selected = selected; - } - - /** - * Returns this item's ID. - * - * @return the JAXX ID attribute - */ - public String getId() { - return id; - } - - /** - * Returns the string that should be used to represent the item at display time. If <code>null</code>, - * <code>String.valueOf(getValue())</code> will be used instead. - * - * @return this item's display string - * @see #setLabel - */ - public String getLabel() { - return label; - } - - /** - * Sets the item's display string. If <code>null, String.valueOf(getValue())</code> will be used instead. - * - * @param label the new display string - * @see #getLabel - */ - public void setLabel(String label) { - String oldLabel = this.label; - this.label = label; - firePropertyChange(LABEL_PROPERTY, oldLabel, label); - } - - /** - * Returns the item's actual value as it appears in the component's model. The <code>Item</code> itself is not - * visible from the model, only the value. - * - * @return the item's value - * @see #setValue - */ - public Object getValue() { - return value; - } - - /** - * Sets the item's value as it appears in the component's model. The <code>Item</code> itself is not - * visible from the model, only the value. - * - * @param value the new value - * @see #getValue - */ - public void setValue(Object value) { - Object oldValue = this.value; - this.value = value; - firePropertyChange(VALUE_PROPERTY, oldValue, value); - } - - /** - * Returns <code>true</code> if this item is currently selected. This is a bound property. - * - * @return <code>true</code> if item is selected - * @see #setSelected - */ - public boolean isSelected() { - return selected; - } - - /** - * Sets the item's selection state. This is a bound property. - * - * @param selected the new selection state - * @see #isSelected - */ - public void setSelected(boolean selected) { - boolean oldSelected = this.selected; - this.selected = selected; - firePropertyChange(SELECTED_PROPERTY, oldSelected, selected); - } - - /** - * Adds a new child node (Items can be nested in trees). - * - * @param item the new child item - */ - public void addChild(Item item) { - if (children == null) { - children = new ArrayList<Item>(); - } - children.add(item); - item.parent = this; - } - - /** - * Remove child node a new child node - * - * @param item to remove - */ - public void removeChild(Item item) { - if (children != null) { - children.remove(item); - } - } - - /** - * Remove all childs nodes - * - * @param items list of items to remove - */ - public void removeChilds(List<Item> items) { - if (children != null) { - children.removeAll(items); - } - } - - /** - * Returns a list of this item's children. - * - * @return a list of all nested child nodes - */ - public List<Item> getChildren() { - if (children == null) { - children = new ArrayList<Item>(); - } - return children; - } - - /** - * Returns the <code>Item</code> containing this <code>Item</code>, or <code>null</code> for a top-level - * <code>Item</code>. - * - * @return the item parent (or null) - */ - public Item getParent() { - return parent; - } - - /** - * Set the parent of this item - * - * @param parent the item parent (or null) - */ - public void setParent(Item parent) { - this.parent = parent; - } - - private PropertyChangeSupport getPropertyChangeSupport() { - if (propertyChangeSupport == null) { - propertyChangeSupport = new SwingPropertyChangeSupport(this); - } - return propertyChangeSupport; - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - getPropertyChangeSupport().addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String property, PropertyChangeListener listener) { - getPropertyChangeSupport().addPropertyChangeListener(property, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - getPropertyChangeSupport().removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String property, PropertyChangeListener listener) { - getPropertyChangeSupport().removePropertyChangeListener(property, listener); - } - - protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { - if (propertyChangeSupport != null) { - getPropertyChangeSupport().firePropertyChange(propertyName, oldValue, newValue); - } - } - - @Override - public String toString() { - return getClass().getName() + "[" + value + "]"; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java deleted file mode 100644 index 125ec3e..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.AbstractButton; -import javax.swing.ButtonGroup; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.event.EventListenerList; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.util.Enumeration; - -public class JAXXButtonGroup extends ButtonGroup { - - public static final String SELECTED_VALUE_PROPERTY = "selectedValue"; - - public static final String BUTTON8GROUP_CLIENT_PROPERTY = "$buttonGroup"; - - public static final String VALUE_CLIENT_PROPERTY = "$value"; - - public static final String SELECTED_TIP_CLIENT_PROPERTY = "$selected.toolTipText"; - - public static final String NOT_SELECTED_TIP_CLIENT_PROPERTY = "$not.selected.toolTipText"; - - protected EventListenerList listenerList = new EventListenerList(); - - private PropertyChangeSupport propertyChangeSupport; - - private transient Object selectedValue; - - protected boolean useToolTipText; - - protected transient ChangeEvent changeEvent = new ChangeEvent(this); - - private transient ChangeListener changeListener = new ChangeListener() { - - @Override - public void stateChanged(ChangeEvent e) { - updateSelectedValue(); - if (useToolTipText) { - updateToolTipText(); - } - } - }; - - private static final long serialVersionUID = 1L; - - @Override - public void add(AbstractButton button) { - super.add(button); - button.addChangeListener(changeListener); - updateSelectedValue(); - } - - @Override - public void remove(AbstractButton button) { - super.remove(button); - button.removeChangeListener(changeListener); - updateSelectedValue(); - } - - public void updateSelectedValue() { - Enumeration<AbstractButton> e = getElements(); - while (e.hasMoreElements()) { - AbstractButton button = e.nextElement(); - if (button.isSelected()) { - Object buttonValue = button.getClientProperty(VALUE_CLIENT_PROPERTY); - if (buttonValue != getSelectedValue()) { - setSelectedValue(buttonValue); - } - } - } - } - - public void updateToolTipText() { - Enumeration<AbstractButton> e = getElements(); - while (e.hasMoreElements()) { - AbstractButton button = e.nextElement(); - String key = button.isSelected() ? SELECTED_TIP_CLIENT_PROPERTY : NOT_SELECTED_TIP_CLIENT_PROPERTY; - button.setToolTipText((String) button.getClientProperty(key)); - } - } - - public boolean isUseToolTipText() { - return useToolTipText; - } - - public Object getSelectedValue() { - return selectedValue; - } - - public AbstractButton getSelectedButton() { - Enumeration<AbstractButton> e = getElements(); - while (e.hasMoreElements()) { - AbstractButton button = e.nextElement(); - if (button.isSelected()) { - return button; - } - } - return null; - } - - public AbstractButton getButton(Object value) { - Enumeration<AbstractButton> e = getElements(); - while (e.hasMoreElements()) { - AbstractButton button = e.nextElement(); - Object buttonValue = button.getClientProperty(VALUE_CLIENT_PROPERTY); - if (value.equals(buttonValue)) { - return button; - } - } - return null; - } - - public void setSelectedValue(Object value) { - Object oldValue = getSelectedValue(); - this.selectedValue = value; - firePropertyChange(oldValue); - } - - public void setUseToolTipText(boolean useToolTipText) { - this.useToolTipText = useToolTipText; - } - - public void setSelectedButton(Object value) { - setSelectedValue(value); - if (value == null) { - Enumeration<AbstractButton> e = getElements(); - while (e.hasMoreElements()) { - AbstractButton button = e.nextElement(); - setSelected(button.getModel(), false); - } - return; - } - - Enumeration<AbstractButton> e = getElements(); - while (e.hasMoreElements()) { - AbstractButton button = e.nextElement(); - Object buttonValue = button.getClientProperty(VALUE_CLIENT_PROPERTY); - if (value.equals(buttonValue)) { - button.setSelected(true); - break; - } - } - } - - protected PropertyChangeSupport getPropertyChangeSupport() { - if (propertyChangeSupport == null) { - propertyChangeSupport = new PropertyChangeSupport(this); - } - return propertyChangeSupport; - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - getPropertyChangeSupport().addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String property, PropertyChangeListener listener) { - getPropertyChangeSupport().addPropertyChangeListener(property, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - getPropertyChangeSupport().removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String property, PropertyChangeListener listener) { - getPropertyChangeSupport().removePropertyChangeListener(property, listener); - } - - private void firePropertyChange(Object oldValue) { - if (propertyChangeSupport != null) { - getPropertyChangeSupport().firePropertyChange(SELECTED_VALUE_PROPERTY, - oldValue, getSelectedValue()); - } - fireStateChanged(); - } - - /** - * Adds a <code>ChangeListener</code> to the button. - * - * @param l the listener to be added - */ - public void addChangeListener(ChangeListener l) { - listenerList.add(ChangeListener.class, l); - } - - /** - * Removes a ChangeListener from the button. - * - * @param l the listener to be removed - */ - public void removeChangeListener(ChangeListener l) { - listenerList.remove(ChangeListener.class, l); - } - - /** - * Returns an array of all the <code>ChangeListener</code>s added - * to this AbstractButton with addChangeListener(). - * - * @return all of the <code>ChangeListener</code>s added or an empty - * array if no listeners have been added - * @since 1.4 - */ - public ChangeListener[] getChangeListeners() { - return listenerList.getListeners(ChangeListener.class); - } - - /** - * Notifies all listeners that have registered interest for - * notification on this event type. The event instance - * is lazily created. - * - * @see EventListenerList - */ - protected void fireStateChanged() { - // Guaranteed to return a non-null array - Object[] listeners = listenerList.getListenerList(); - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == ChangeListener.class) { - // Lazily create the event: - if (changeEvent == null) { - changeEvent = new ChangeEvent(this); - } - ((ChangeListener) listeners[i + 1]).stateChanged(changeEvent); - } - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXComboBox.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXComboBox.java deleted file mode 100644 index dc44c2e..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXComboBox.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.AbstractListModel; -import javax.swing.ComboBoxModel; -import javax.swing.DefaultListCellRenderer; -import javax.swing.JComboBox; -import javax.swing.JList; -import javax.swing.ListModel; -import java.awt.Component; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public class JAXXComboBox extends JComboBox { - - private static final long serialVersionUID = 1L; - - public class JAXXComboBoxModel extends AbstractListModel implements ComboBoxModel { - - private List<Item> items; - - private Object selectedItem; - - private static final long serialVersionUID = -8940733376638766414L; - - public JAXXComboBoxModel(List<Item> items) { - this.items = items; - - PropertyChangeListener listener = new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent e) { - if (e.getPropertyName().equals(Item.SELECTED_PROPERTY)) { - Item item = (Item) e.getSource(); - int itemIndex = JAXXComboBoxModel.this.items.indexOf(item); - // TODO: fix cut-and-pasting badness - int[] oldSelection = new int[]{getSelectedIndex()}; - int[] newSelection; - int index = -1; - for (int i = 0; i < oldSelection.length; i++) { - if (oldSelection[i] == itemIndex) { - index = i; - break; - } - } - if (item.isSelected()) { - if (index != -1) // it was already selected - { - return; - } - newSelection = new int[oldSelection.length + 1]; - System.arraycopy(oldSelection, 0, newSelection, 0, oldSelection.length); - newSelection[newSelection.length - 1] = itemIndex; - } else { - if (index == -1) // it already wasn't selected - { - return; - } - newSelection = new int[oldSelection.length - 1]; - System.arraycopy(oldSelection, 0, newSelection, 0, index); - System.arraycopy(oldSelection, index + 1, newSelection, index, oldSelection.length - 1 - index); - } - if (newSelection.length > 0) { - setSelectedIndex(newSelection[0]); - } - } else { - // TODO: more cut-and-pasting badness - for (int i = 0; i < getSize(); i++) { - if (getElementAt(i) == ((Item) e.getSource()).getValue()) { - fireContentsChanged(JAXXComboBoxModel.this, i, i); - if (getSelectedIndex() == i) { - fireItemStateChanged(new ItemEvent(JAXXComboBox.this, ItemEvent.ITEM_STATE_CHANGED, getElementAt(i), ItemEvent.DESELECTED)); - } - return; - } - } - } - } - }; - for (Item item : items) { - item.addPropertyChangeListener(listener); - } - } - - public List<Item> getItems() { - return items; - } - - @Override - public Object getElementAt(int i) { - return items.get(i).getValue(); - } - - @Override - public int getSize() { - return items.size(); - } - - @Override - public Object getSelectedItem() { - return selectedItem; - } - - @Override - public void setSelectedItem(Object selectedItem) { - if (this.selectedItem != null && !this.selectedItem.equals(selectedItem) || - this.selectedItem == null && selectedItem != null) { - this.selectedItem = selectedItem; - fireContentsChanged(this, -1, -1); - } - } - } - - public JAXXComboBox() { - setRenderer(new DefaultListCellRenderer() { - - private static final long serialVersionUID = 1L; - - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - ListModel model = list.getModel(); - if (model instanceof JAXXComboBoxModel) { - List/*<Item>*/ items = ((JAXXComboBoxModel) model).items; - Item item = null; - if (index == -1) { - for (Object item1 : items) { - Item testItem = (Item) item1; - if (testItem.getValue() == value) { - item = testItem; - break; - } - } - } else { - item = (Item) items.get(index); - } - - if (item != null) { - String label = item.getLabel(); - if (label != null) { - value = label; - } - } - } - return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - } - }); - - addItemListener(new ItemListener() { - - @Override - public void itemStateChanged(ItemEvent e) { - ListModel model = getModel(); - if (model instanceof JAXXComboBoxModel) { - List<Item> items = ((JAXXComboBoxModel) model).items; - for (int i = items.size() - 1; i >= 0; i--) { - boolean selected = getSelectedIndex() == i; - Item item = items.get(i); - if (selected != item.isSelected()) { - item.setSelected(selected); - } - } - } - } - }); - } - - /** - * Fill a combo box model with some datas, and select after all the given object - * - * @param data data ot inject in combo - * @param select the object to select in combo after reflling his model - * @param methodName method to invoke to display data's name - */ - public void fillComboBox(Collection<?> data, Object select, String methodName) { - // prepare method to use - Method m; - try { - m = select.getClass().getMethod(methodName); - m.setAccessible(true); - } catch (NoSuchMethodException e) { - throw new IllegalArgumentException("could not find method " + methodName + " on " + select.getClass()); - } - - List<Item> items = new ArrayList<Item>(); - for (Object o : data) { - boolean selected = o.equals(select); - try { - items.add(new Item(o.toString(), (String) m.invoke(o), o, selected)); - } catch (IllegalAccessException e) { - // shoudl never happen ? - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - // shoudl never happen ? - throw new RuntimeException(e); - } - } - setItems(items); - } - - // this way we can keep it marked protected and still allow code in this file to call it - - @Override - protected void fireItemStateChanged(ItemEvent e) { - super.fireItemStateChanged(e); - } - - public void setItems(List<Item> items) { - setModel(new JAXXComboBoxModel(items)); - List<Integer> selectedIndexList = new ArrayList<Integer>(); - for (int i = 0; i < items.size(); i++) { - if (items.get(i).isSelected()) { - selectedIndexList.add(i); - } - } - int[] selectedIndices = new int[selectedIndexList.size()]; - for (int i = 0; i < selectedIndexList.size(); i++) { - selectedIndices[i] = selectedIndexList.get(i); - } - if (selectedIndices.length > 0) { - setSelectedIndex(selectedIndices[0]); - } - } - - public List<Item> getItems() { - if (getModel() instanceof JAXXComboBoxModel) { - return ((JAXXComboBoxModel) getModel()).getItems(); - } - return null; - } - - public void setSelectedItem(Item item) { - //TC-20092004 Anomalie #73 fix npe when want to call with a null - // value - super.setSelectedItem(item == null ? null : item.getValue()); - } - - public Item getSelectedJaxxItem() { - Object selected = super.getSelectedItem(); - return findItem(selected); - } - - public Item findItem(Object value) { - List<Item> items = getItems(); - if (items != null) { - for (Item i : items) { - if (i.getValue().equals(value)) { - return i; - } - } - } - return null; - } - - public void addItem(Item item) { - List<Item> items = getItems(); - if (items != null) { - items.add(item); - setItems(items); - } - } - - public void addAllItems(Collection<Item> itemsToAdd) { - List<Item> items = getItems(); - if (items != null) { - items.addAll(itemsToAdd); - setItems(items); - } - } - - public void removeItem(Item item) { - List<Item> items = getItems(); - if (items != null) { - items.remove(item); - setItems(items); - } - } - - public void removeAllItems(Collection<Item> itemsToRemove) { - List<Item> items = getItems(); - if (items != null) { - items.removeAll(itemsToRemove); - setItems(items); - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXList.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXList.java deleted file mode 100644 index eb6b720..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXList.java +++ /dev/null @@ -1,414 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.AbstractListModel; -import javax.swing.DefaultListCellRenderer; -import javax.swing.JList; -import javax.swing.ListModel; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import java.awt.Component; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public class JAXXList extends JList { - - private static final long serialVersionUID = 1L; - - public class JAXXListModel extends AbstractListModel { - - private List<Item> items; - - private static final long serialVersionUID = -1598924187490122036L; - - public JAXXListModel(List<Item> items) { - this.items = items; - - PropertyChangeListener listener = new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent e) { - if (e.getPropertyName().equals(Item.SELECTED_PROPERTY)) { - Item item = (Item) e.getSource(); - int itemIndex = JAXXListModel.this.items.indexOf(item); - int[] oldSelection = getSelectedIndices(); - int[] newSelection; - int index = -1; - for (int i = 0; i < oldSelection.length; i++) { - if (oldSelection[i] == itemIndex) { - index = i; - break; - } - } - if (item.isSelected()) { - if (index != -1) // it was already selected - { - return; - } - newSelection = new int[oldSelection.length + 1]; - System.arraycopy(oldSelection, 0, newSelection, 0, oldSelection.length); - newSelection[newSelection.length - 1] = itemIndex; - } else { - if (index == -1) // it already wasn't selected - { - return; - } - newSelection = new int[oldSelection.length - 1]; - System.arraycopy(oldSelection, 0, newSelection, 0, index); - System.arraycopy(oldSelection, index + 1, newSelection, index, oldSelection.length - 1 - index); - } - setSelectedIndices(newSelection); - } else { - for (int i = 0; i < getSize(); i++) { - if (getElementAt(i) == ((Item) e.getSource()).getValue()) { - fireContentsChanged(JAXXListModel.this, i, i); - if (isSelectedIndex(i)) { - fireSelectionValueChanged(i, i, false); - } - return; - } - } - } - } - }; - for (Item item : items) { - item.addPropertyChangeListener(listener); - } - } - - public List<Item> getItems() { - return items; - } - - @Override - public Object getElementAt(int i) { - return items.get(i).getValue(); - } - - @Override - public int getSize() { - return items.size(); - } - } - - public JAXXList() { - setCellRenderer(new DefaultListCellRenderer() { - - private static final long serialVersionUID = 1L; - - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - ListModel model = list.getModel(); - if (model instanceof JAXXListModel) { - Item item = ((JAXXListModel) model).items.get(index); - String label = item.getLabel(); - if (label != null) { - value = label; - } - } - return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - } - }); - - addListSelectionListener(new ListSelectionListener() { - - @Override - public void valueChanged(ListSelectionEvent e) { - ListModel model = getModel(); - if (model instanceof JAXXListModel) { - List<Item> items = ((JAXXListModel) model).items; - for (int i = items.size() - 1; i >= 0; i--) { - boolean selected = isSelectedIndex(i); - Item item = items.get(i); - if (selected != item.isSelected()) { - item.setSelected(selected); - } - } - } - } - }); - } - - // this way we can keep it marked protected and still allow code in this file to call it - - @Override - protected void fireSelectionValueChanged(int firstIndex, int lastIndex, boolean isAdjusting) { - super.fireSelectionValueChanged(firstIndex, lastIndex, isAdjusting); - } - - public void setItems(List<Item> items) { - setModel(new JAXXListModel(items)); - List<Integer> selectedIndexList = new ArrayList<Integer>(); - for (int i = 0; i < items.size(); i++) { - if (items.get(i).isSelected()) { - selectedIndexList.add(i); - } - } - int[] selectedIndices = new int[selectedIndexList.size()]; - for (int i = 0; i < selectedIndexList.size(); i++) { - selectedIndices[i] = selectedIndexList.get(i); - } - setSelectedIndices(selectedIndices); - } - - public List<Item> getItems() { - if (getModel() instanceof JAXXListModel) { - return ((JAXXListModel) getModel()).getItems(); - } - return null; - } - - public void setSelectedValue(Object value) { - super.setSelectedValue(value, true); - } - - /** - * Set the selected Objects - * - * @param values Objects must be selected in the list - */ - public void setSelectedValues(Object[] values) { - if (values != null) { - List<Integer> selectedIndices = new ArrayList<Integer>(); - ListModel model = getModel(); - for (int i = 0; i < model.getSize(); i++) { - Object o = model.getElementAt(i); - for (Object value : values) { - if (o.equals(value)) { - selectedIndices.add(i); - break; - } - } - } - int[] ints = new int[selectedIndices.size()]; - for (int i = 0; i < ints.length; i++) { - ints[i] = selectedIndices.get(i).intValue(); - } - setSelectedIndices(ints); - } else { - // No selection if values is null - setSelectedIndex(-1); - } - } - - public void setSelectedItem(Item item) { - super.setSelectedValue(item.getValue(), true); - } - - public void setSelectedItems(List<Item> itemsToSelect) { - if (itemsToSelect != null) { - List<Item> items = getItems(); - int[] indices = new int[itemsToSelect.size()]; - int i = 0; - for (Item item : itemsToSelect) { - indices[i] = items.indexOf(item); - i++; - } - super.setSelectedIndices(indices); - } - } - - public Item getSelectedItem() { - Object selected = super.getSelectedValue(); - return findItem(selected); - } - - public List<Item> getSelectedItems() { - Object[] selected = super.getSelectedValues(); - java.util.List<Item> itemsSelected = new ArrayList<Item>(); - for (Object s : selected) { - itemsSelected.add(findItem(s)); - } - return itemsSelected; - } - - public Item findItem(Object value) { - List<Item> items = getItems(); - if (items != null) { - for (Item i : items) { - if (i.getValue().equals(value)) { - return i; - } - } - } - return null; - } - - public void addItem(Item item) { - List<Item> items = getItems(); - if (items != null) { - items.add(item); - setItems(items); - } - } - - public void addAllItems(Collection<Item> itemsToAdd) { - List<Item> items = getItems(); - if (items != null) { - items.addAll(itemsToAdd); - setItems(items); - } - } - - public void removeItem(Item item) { - List<Item> items = getItems(); - if (items != null) { - items.remove(item); - setItems(items); - } - } - - public void removeAllItems(Collection<Item> itemsToRemove) { - List<Item> items = getItems(); - if (items != null) { - items.removeAll(itemsToRemove); - setItems(items); - } - } - - /** - * Fill a list model with some datas, and select after all the given object - * - * @param data data ot inject in combo - * @param selects the objects to select in list after reflling his model - */ - public void fillList(Collection<?> data, Collection<?> selects) { - if (selects == null) { - selects = java.util.Collections.EMPTY_LIST; - } - List<Item> items = new ArrayList<Item>(); - for (Object o : data) { - boolean selected = false; - for (Object select : selects) { - if (selected = o.equals(select)) { - break; - } - } - items.add(new Item(o.toString(), o.toString(), o, selected)); - } - setItems(items); - } - - /** - * Fill a list model with some datas, and select after all the given object - * - * @param data data ot inject in combo - * @param select object to select in list after reflling his model - */ - public void fillList(Collection<?> data, Object select) { - List<Item> items = new ArrayList<Item>(); - for (Object o : data) { - boolean selected = o.equals(select); - items.add(new Item(o.toString(), o.toString(), o, selected)); - } - setItems(items); - } - - /** - * Fill a list model with some datas, and select after all the given object - * - * @param data data ot inject in combo - * @param select object to select in list after reflling his model - * @param methodName method to invoke to display data's name - */ - public void fillList(Collection<?> data, Object select, String methodName) { - // prepare method to use - Method m = null; - - List<Item> items = new ArrayList<Item>(); - for (Object o : data) { - boolean selected = o.equals(select); - if (m == null) { - try { - m = o.getClass().getMethod(methodName); - m.setAccessible(true); - } catch (NoSuchMethodException e) { - throw new IllegalArgumentException("could not find method " + methodName + " on " + o.getClass()); - } - } - try { - items.add(new Item(o.toString(), (String) m.invoke(o), o, selected)); - } catch (SecurityException e) { - // shoudl never happen ? - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - // shoudl never happen ? - throw new RuntimeException(e); - } catch (IllegalArgumentException e) { - // shoudl never happen ? - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - // shoudl never happen ? - throw new RuntimeException(e); - } - } - setItems(items); - } - - /** - * Fill a list model with some datas, and select after all the given object - * - * @param data data ot inject in combo - * @param selects the objects to select in list after reflling his model - * @param methodName method to invoke to display data's name - */ - public void fillList(Collection<?> data, Collection<?> selects, String methodName) { - // prepare method to use - Method m = null; - - List<Item> items = new ArrayList<Item>(); - for (Object o : data) { - boolean selected = selects.contains(o); - if (m == null) { - try { - m = o.getClass().getMethod(methodName); - m.setAccessible(true); - } catch (NoSuchMethodException e) { - throw new IllegalArgumentException("could not find method " + methodName + " on " + o.getClass()); - } - } - try { - items.add(new Item(o.toString(), (String) m.invoke(o), o, selected)); - } catch (SecurityException e) { - // shoudl never happen ? - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - // shoudl never happen ? - throw new RuntimeException(e); - } catch (IllegalArgumentException e) { - // shoudl never happen ? - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - // shoudl never happen ? - throw new RuntimeException(e); - } - } - setItems(items); - } - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXTab.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXTab.java deleted file mode 100644 index 8e60bcb..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXTab.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -/** @author Tony Chemit - chemit@codelutin.com */ -public class JAXXTab extends Table { - - private static final long serialVersionUID = 1L; -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXToggleButton.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXToggleButton.java deleted file mode 100644 index 98f4672..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXToggleButton.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.JToggleButton; - -public class JAXXToggleButton extends JToggleButton { - - private static final long serialVersionUID = 1L; - - protected String glueText; - - protected String normalText; - - protected String glueTooltipText; - - protected String normalTooltipText; - - protected int normalMnemonic; - - protected int glueMnemonic; - - protected boolean _init; - - public String getGlueText() { - return glueText; - } - - public String getNormalText() { - return normalText; - } - - public String getGlueTooltipText() { - return glueTooltipText; - } - - public String getNormalTooltipText() { - return normalTooltipText; - } - - public void setGlueText(String glueText) { - this.glueText = glueText; - - } - - public void setNormalText(String normalText) { - this.normalText = normalText; - - } - - public void setGlueTooltipText(String glueTooltipText) { - this.glueTooltipText = glueTooltipText; - } - - public int getNormalMnemonic() { - return normalMnemonic; - } - - public void setNormalMnemonic(int normalMnemonic) { - this.normalMnemonic = normalMnemonic; - } - - public int getGlueMnemonic() { - return glueMnemonic; - } - - public void setGlueMnemonic(int glueMnemonic) { - this.glueMnemonic = glueMnemonic; - } - - public void setNormalTooltipText(String normalTooltipText) { - this.normalTooltipText = normalTooltipText; - if (!_init) { - init(); - _init = true; - } - } - - @Override - public void setSelected(boolean b) { - super.setSelected(b); - if (isSelected()) { - setText(getGlueText()); - setToolTipText(getGlueTooltipText()); - setMnemonic(getGlueMnemonic()); - } else { - setText(getNormalText()); - setToolTipText(getNormalTooltipText()); - setMnemonic(getNormalMnemonic()); - } - revalidate(); - } - - public void init() { - setSelected(false); - } - - /* end raw body code */ - public JAXXToggleButton() { - super(); - _init = false; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXTree.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXTree.java deleted file mode 100644 index f127ad3..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXTree.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.JTree; -import javax.swing.event.TreeModelEvent; -import javax.swing.event.TreeModelListener; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.TreeModel; -import javax.swing.tree.TreePath; -import java.awt.Component; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.ArrayList; -import java.util.List; - -public class JAXXTree extends JTree { - - private static final long serialVersionUID = 1L; - - private static final String SYNTHETIC = "<synthetic root node>"; - - public class JAXXTreeModel implements TreeModel { - - private Item root; - - private List<TreeModelListener> listeners = new ArrayList<TreeModelListener>(); - - public JAXXTreeModel(List<Item> items) { - if (items.size() == 1) { - root = items.get(0); - } else { - root = new Item(null, null, SYNTHETIC, false); - for (Item item : items) { - root.addChild(item); - } - } - - PropertyChangeListener listener = new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent e) { - if (e.getPropertyName().equals(Item.SELECTED_PROPERTY)) { - Item item = (Item) e.getSource(); - if (item.isSelected()) { - addSelectionPath(getTreePath(item)); - } else { - removeSelectionPath(getTreePath(item)); - } - } else { - Item item = (Item) e.getSource(); - boolean root = item.getParent() == null; - TreePath path = !root ? getTreePath(item.getParent()) : null; - fireTreeNodesChanged(new TreeModelEvent(JAXXTreeModel.this, path, - !root ? new int[]{item.getParent().getChildren().indexOf(item)} : null, - new Object[]{item.getValue()})); - } - } - }; - addPropertyChangeListener(root, listener); - } - - private void addPropertyChangeListener(Item item, PropertyChangeListener listener) { - item.addPropertyChangeListener(listener); - List<Item> children = item.getChildren(); - for (Item aChildren : children) { - addPropertyChangeListener(aChildren, listener); - } - } - - @Override - public void addTreeModelListener(TreeModelListener listener) { - listeners.add(listener); - } - - - /* This is an inefficient implementation, but hand-coded tree structures are unlikely to contain - enough nodes for that to really matter. This could be sped up with caching. */ - public Item findItem(Object value) { - return findItem(root, value); - } - - private Item findItem(Item node, Object value) { - if (node.getValue() == value) { - return node; - } else { - List<Item> children = node.getChildren(); - for (Item aChildren : children) { - Item result = findItem(aChildren, value); - if (result != null) { - return result; - } - } - return null; - } - } - - private TreePath getTreePath(Item node) { - List<Object> path = new ArrayList<Object>(); - while (node != null) { - path.add(0, node.getValue()); - node = node.getParent(); - } - return new TreePath(path.toArray()); - } - - @Override - public Object getChild(Object parent, int index) { - Item node = findItem(parent); - return node.getChildren().get(index).getValue(); - } - - @Override - public int getChildCount(Object parent) { - Item node = findItem(parent); - if (node == null) { - return 0; - } - return node.getChildren().size(); - } - - @Override - public int getIndexOfChild(Object parent, Object child) { - Item node = findItem(parent); - List<Item> children = node.getChildren(); - for (int i = 0, j = children.size(); i < j; i++) { - if (children.get(i).getValue() == child) { - return i; - } - } - return -1; - } - - @Override - public Object getRoot() { - return root.getValue(); - } - - public Item getRootItem() { - return root; - } - - @Override - public boolean isLeaf(Object node) { - Item item = findItem(node); - return item != null && item.getChildren().size() == 0; - } - - @Override - public void removeTreeModelListener(TreeModelListener listener) { - listeners.remove(listener); - } - - public void fireTreeNodesChanged(TreeModelEvent e) { - for (TreeModelListener listener : listeners) { - listener.treeNodesChanged(e); - } - } - - @Override - public void valueForPathChanged(TreePath path, Object newValue) { - } - } - - public JAXXTree(TreeModel model) { - super(model); - } - - public JAXXTree() { - setCellRenderer(new DefaultTreeCellRenderer() { - - private static final long serialVersionUID = 1L; - - @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { - TreeModel model = tree.getModel(); - if (model instanceof JAXXTreeModel) { - Item item = ((JAXXTreeModel) model).findItem(value); - if (item != null) { - String label = item.getLabel(); - if (label != null) { - value = label; - } - } - } - return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); - } - }); - - addTreeSelectionListener(new TreeSelectionListener() { - - @Override - public void valueChanged(TreeSelectionEvent e) { - TreeModel model = getModel(); - if (model instanceof JAXXTreeModel) { - scan((JAXXTreeModel) model, ((JAXXTreeModel) model).root); - } - } - - private void scan(JAXXTreeModel model, Item item) { - TreePath path = model.getTreePath(item); - if (item.isSelected() != isPathSelected(path)) { - item.setSelected(!item.isSelected()); - } - List<Item> children = item.getChildren(); - for (Item aChildren : children) { - scan(model, aChildren); - } - } - }); - } - - public void setItem(Item items) { - List<Item> newItems = new ArrayList<Item>(); - newItems.add(items); - setItems(newItems); - } - - public void setItems(List<Item> items) { - // Create model - JAXXTreeModel model = new JAXXTreeModel(items); - if (model.getRoot() != null) { - setRootVisible(model.getRoot() != SYNTHETIC); - } - // Atach model - setModel(model); - - // Appli selected items - if (items != null) { - List<TreePath> treePathSelected = new ArrayList<TreePath>(); - for (Item i : items) { - if (i.isSelected()) { - treePathSelected.add(model.getTreePath(i)); - } - } - setSelectionPaths(convertToTreePathArray(treePathSelected.toArray())); - } - } - - public Object getSelectionValue() { - TreePath selectionPath = getSelectionPath(); - return selectionPath != null ? selectionPath.getLastPathComponent() : null; - } - - public Item getRootItem() { - if (getModel() instanceof JAXXTreeModel) { - return ((JAXXTreeModel) getModel()).getRootItem(); - } - return null; - } - - protected TreePath[] convertToTreePathArray(Object[] datas) { - TreePath[] params = new TreePath[datas.length]; - System.arraycopy(datas, 0, params, 0, datas.length); - return params; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/JTables.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/JTables.java deleted file mode 100644 index f5d93c6..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/JTables.java +++ /dev/null @@ -1,117 +0,0 @@ -package jaxx.runtime.swing; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.JTable; - -/** - * Some usefull methods on {@link JTable}. - * - * Created on 12/4/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.18 - */ -public class JTables { - - /** Logger. */ - private static final Log log = LogFactory.getLog(JTables.class); - - public static void selectFirstCellOnFirstRowAndStopEditing(JTable table) { - - // select first cell - doSelectCell(table, 0, 0); - - if (table.isEditing()) { - - // but no edit it - table.getCellEditor().stopCellEditing(); - } - } - - public static void selectFirstCellOnLastRow(JTable table) { - - // select first cell - doSelectCell(table, table.getRowCount() - 1, 0); - } - - public static void selectFirstCellOnRow(JTable table, int row, boolean stopEdit) { - - // select first cell - doSelectCell(table, row, 0); - - if (stopEdit && table.isEditing()) { - - table.getCellEditor().stopCellEditing(); - } - } - - public static void doSelectCell(JTable table, - int rowIndex, - int columnIndex) { - - int rowCount = table.getRowCount(); - if (rowCount == 0) { - - // no row, can not selected any cell - if (log.isWarnEnabled()) { - log.warn("No row in table, can not select any cell"); - } - return; - } - int columnCount = table.getColumnCount(); - if (columnCount == 0) { - - // no column, can not selected any cell - if (log.isWarnEnabled()) { - log.warn("No column in table, can not select any cell"); - } - return; - } - if (columnIndex > columnCount) { - if (log.isWarnEnabled()) { - log.warn(String.format("ColumnIndex: %s is more than columnCount %s", columnIndex, columnCount)); - } - columnIndex = columnCount - 1; - } - if (columnIndex < 0) { - columnIndex = 0; - } - if (rowIndex >= rowCount) { - if (log.isWarnEnabled()) { - log.warn(String.format("RowIndex: %s is more than rowCount %s", rowIndex, rowCount)); - } - rowIndex = rowCount - 1; - } - if (rowIndex < 0) { - rowIndex = 0; - } - - table.setColumnSelectionInterval(columnIndex, columnIndex); - table.setRowSelectionInterval(rowIndex, rowIndex); - table.editCellAt(rowIndex, columnIndex); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/OneClicListSelectionModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/OneClicListSelectionModel.java deleted file mode 100644 index e88f0af..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/OneClicListSelectionModel.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.JList; -import javax.swing.ListModel; -import javax.swing.ListSelectionModel; -import javax.swing.event.ListSelectionListener; -import java.util.Arrays; - -/** - * @author Tony Chemit - chemit@codelutin.com - * @since 1.5 - */ -public class OneClicListSelectionModel implements ListSelectionModel { - - /** Logger */ - static private Log log = LogFactory.getLog(OneClicListSelectionModel.class); - - protected ListSelectionModel delegate; - - protected final ListModel model; - - private boolean[] _states; - - /** - * Convinient method to install a new {@link OneClicListSelectionModel} on - * a given {@link JList}. - * - * @param list the list onwhcih install the selection model - * @since 2.5.4 - */ - public static void installModel(JList list) { - OneClicListSelectionModel newModel = new OneClicListSelectionModel(list); - list.setSelectionModel(newModel); - } - - public OneClicListSelectionModel(JList list) { - this.delegate = list.getSelectionModel(); - this.model = list.getModel(); - delegate.clearSelection(); - } - - public OneClicListSelectionModel(ListSelectionModel delegate, ListModel model) { - this.delegate = delegate; - this.model = model; - delegate.clearSelection(); - } - - protected boolean[] getStates(int selectedIndex) { - int max = model.getSize(); - if (_states == null || _states.length != max) { - _states = new boolean[max]; - } else { - Arrays.fill(_states, false); - } - for (int i = 0; i < max; i++) { - _states[i] = i != selectedIndex && delegate.isSelectedIndex(i); - } - return _states; - } - - @Override - public void setSelectionInterval(int index0, int index1) { - if (index0 != index1) { - // not a single selection (come from a click) - // use default behaviour - delegate.setSelectionInterval(index0, index1); - return; - } - delegate.setValueIsAdjusting(true); - - try { - int max = model.getSize(); - - if (log.isDebugEnabled()) { - log.debug("single [index:" + index0 + "] [selected:" + isSelectedIndex(index0) + "] [size:" + max + "] [anchor:" + delegate.getAnchorSelectionIndex() + "] [lead:" + delegate.getLeadSelectionIndex() + "]"); - } - - if (!isSelectedIndex(index0)) { - // select it - delegate.addSelectionInterval(index0, index1); - return; - } - if (max == index0) { - // last selected index, so can directly remove it - delegate.removeIndexInterval(index0, index0); - return; - } - - // must recompute the selection removing only the index0 item - boolean[] state = getStates(index0); - - if (log.isDebugEnabled()) { - log.debug("state : " + Arrays.toString(state)); - } - delegate.clearSelection(); - for (int i = 0; i < max; i++) { - if (state[i]) { - delegate.addSelectionInterval(i, i); - } - } - } finally { - delegate.setValueIsAdjusting(false); - } - } - - @Override - public void addSelectionInterval(int index0, int index1) { - delegate.addSelectionInterval(index0, index1); - } - - @Override - public void removeSelectionInterval(int index0, int index1) { - delegate.removeSelectionInterval(index0, index1); - } - - @Override - public int getMinSelectionIndex() { - return delegate.getMinSelectionIndex(); - } - - @Override - public int getMaxSelectionIndex() { - return delegate.getMaxSelectionIndex(); - } - - @Override - public boolean isSelectedIndex(int index) { - return delegate.isSelectedIndex(index); - } - - @Override - public int getAnchorSelectionIndex() { - return delegate.getAnchorSelectionIndex(); - } - - @Override - public void setAnchorSelectionIndex(int index) { - delegate.setAnchorSelectionIndex(index); - } - - @Override - public int getLeadSelectionIndex() { - return delegate.getLeadSelectionIndex(); - } - - @Override - public void setLeadSelectionIndex(int index) { - delegate.setLeadSelectionIndex(index); - } - - @Override - public void clearSelection() { - delegate.clearSelection(); - } - - @Override - public boolean isSelectionEmpty() { - return delegate.isSelectionEmpty(); - } - - @Override - public void insertIndexInterval(int index, int length, boolean before) { - delegate.insertIndexInterval(index, length, before); - } - - @Override - public void removeIndexInterval(int index0, int index1) { - delegate.removeIndexInterval(index0, index1); - } - - @Override - public void setValueIsAdjusting(boolean valueIsAdjusting) { - delegate.setValueIsAdjusting(valueIsAdjusting); - } - - @Override - public boolean getValueIsAdjusting() { - return delegate.getValueIsAdjusting(); - } - - @Override - public void setSelectionMode(int selectionMode) { - delegate.setSelectionMode(selectionMode); - } - - @Override - public int getSelectionMode() { - return delegate.getSelectionMode(); - } - - @Override - public void addListSelectionListener(ListSelectionListener x) { - delegate.addListSelectionListener(x); - } - - @Override - public void removeListSelectionListener(ListSelectionListener x) { - delegate.removeListSelectionListener(x); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/Spacer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/Spacer.java deleted file mode 100644 index b87dff2..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/Spacer.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.JComponent; - -public class Spacer extends JComponent { - - private static final long serialVersionUID = 1L; -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/TabInfo.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/TabInfo.java deleted file mode 100644 index 8bc9821..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/TabInfo.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.event.SwingPropertyChangeSupport; -import java.awt.Color; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; - -public class TabInfo { - - public static String BACKGROUND_PROPERTY = "background"; - - public static String TAB_COMPONENT_PROPERTY = "tabComponent"; - - public static String TAB_COMPONENT_STR_PROPERTY = "tabComponentStr"; - - public static String DISABLED_ICON_PROPERTY = "disabledIcon"; - - public static String DISPLAYED_MNEMONIC_INDEX_PROPERTY = "displayedMnemonicIndex"; - - public static String ENABLED_PROPERTY = "enabled"; - - public static String FOREGROUND_PROPERTY = "foreground"; - - public static String ICON_PROPERTY = "icon"; - - public static String MNEMONIC_PROPERTY = "mnemonic"; - - public static String TITLE_PROPERTY = "title"; - - public static String TOOL_TIP_TEXT_PROPERTY = "toolTipText"; - - private String id; - - private Color background; - - private Icon disabledIcon; - - private int displayedMnemonicIndex = -1; - - private boolean enabled = true; - - private Color foreground; - - private Icon icon; - - private int mnemonic = -1; - - private String title; - - private String toolTipText; - - private JComponent tabComponent; - - private String tabComponentStr; - - private PropertyChangeSupport propertyChangeSupport; - - public TabInfo() { - } - - public TabInfo(String id) { - this.id = id; - } - - public String getId() { - return id; - } - - public Color getBackground() { - return background; - } - - public void setBackground(Color background) { - Color oldValue = this.background; - this.background = background; - firePropertyChange(BACKGROUND_PROPERTY, oldValue, background); - } - - public Icon getDisabledIcon() { - return disabledIcon; - } - - public void setDisabledIcon(Icon disabledIcon) { - Icon oldValue = this.disabledIcon; - this.disabledIcon = disabledIcon; - firePropertyChange(DISABLED_ICON_PROPERTY, oldValue, disabledIcon); - } - - public int getDisplayedMnemonicIndex() { - return displayedMnemonicIndex; - } - - public void setDisplayedMnemonicIndex(int displayedMnemonicIndex) { - int oldValue = this.displayedMnemonicIndex; - this.displayedMnemonicIndex = displayedMnemonicIndex; - firePropertyChange(DISPLAYED_MNEMONIC_INDEX_PROPERTY, oldValue, displayedMnemonicIndex); - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - boolean oldValue = this.enabled; - this.enabled = enabled; - firePropertyChange(ENABLED_PROPERTY, oldValue, enabled); - } - - public Color getForeground() { - return foreground; - } - - public void setForeground(Color foreground) { - Color oldValue = this.foreground; - this.foreground = foreground; - firePropertyChange(FOREGROUND_PROPERTY, oldValue, foreground); - } - - public Icon getIcon() { - return icon; - } - - public void setIcon(Icon icon) { - Icon oldValue = this.icon; - this.icon = icon; - firePropertyChange(ICON_PROPERTY, oldValue, icon); - } - - public int getMnemonic() { - return mnemonic; - } - - public void setMnemonic(int mnemonic) { - int oldValue = this.mnemonic; - this.mnemonic = mnemonic; - firePropertyChange(MNEMONIC_PROPERTY, oldValue, mnemonic); - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - String oldValue = this.title; - this.title = title; - firePropertyChange(TITLE_PROPERTY, oldValue, title); - } - - public String getToolTipText() { - return toolTipText; - } - - public void setToolTipText(String toolTipText) { - String oldValue = this.toolTipText; - this.toolTipText = toolTipText; - firePropertyChange(TOOL_TIP_TEXT_PROPERTY, oldValue, toolTipText); - } - - public JComponent getTabComponent() { - return tabComponent; - } - - public void setTabComponent(JComponent tabComponent) { - JComponent oldValue = this.tabComponent; - this.tabComponent = tabComponent; - firePropertyChange(TAB_COMPONENT_PROPERTY, oldValue, tabComponent); - } - - - public String getTabComponentStr() { - return tabComponentStr; - } - - public void setTabComponentStr(String tabComponentStr) { - String oldValue = this.tabComponentStr; - this.tabComponentStr = tabComponentStr; - firePropertyChange(TAB_COMPONENT_STR_PROPERTY, oldValue, tabComponent); - } - - private PropertyChangeSupport getPropertyChangeSupport() { - if (propertyChangeSupport == null) { - propertyChangeSupport = new SwingPropertyChangeSupport(this); - } - return propertyChangeSupport; - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - getPropertyChangeSupport().addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String property, PropertyChangeListener listener) { - getPropertyChangeSupport().addPropertyChangeListener(property, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - getPropertyChangeSupport().removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String property, PropertyChangeListener listener) { - getPropertyChangeSupport().removePropertyChangeListener(property, listener); - } - - protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { - if (propertyChangeSupport != null) { - getPropertyChangeSupport().firePropertyChange(propertyName, oldValue, newValue); - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/TabInfoPropertyChangeListener.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/TabInfoPropertyChangeListener.java deleted file mode 100644 index 0229b3e..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/TabInfoPropertyChangeListener.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.Icon; -import javax.swing.JTabbedPane; -import java.awt.Color; -import java.awt.Component; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -public class TabInfoPropertyChangeListener implements PropertyChangeListener { - - private JTabbedPane tabs; - - private int tabIndex; - - public TabInfoPropertyChangeListener(JTabbedPane tabs, int tabIndex) { - this.tabs = tabs; - this.tabIndex = tabIndex; - } - - @Override - public void propertyChange(PropertyChangeEvent e) { - String name = e.getPropertyName(); - if (name.equals(TabInfo.TITLE_PROPERTY)) { - tabs.setTitleAt(tabIndex, (String) e.getNewValue()); - } else if (name.equals(TabInfo.TOOL_TIP_TEXT_PROPERTY)) { - tabs.setToolTipTextAt(tabIndex, (String) e.getNewValue()); - } else if (name.equals(TabInfo.FOREGROUND_PROPERTY)) { - tabs.setForegroundAt(tabIndex, (Color) e.getNewValue()); - } else if (name.equals(TabInfo.BACKGROUND_PROPERTY)) { - tabs.setBackgroundAt(tabIndex, (Color) e.getNewValue()); - } else if (name.equals(TabInfo.MNEMONIC_PROPERTY)) { - tabs.setMnemonicAt(tabIndex, (Integer) e.getNewValue()); - } else if (name.equals(TabInfo.DISPLAYED_MNEMONIC_INDEX_PROPERTY)) { - tabs.setDisplayedMnemonicIndexAt(tabIndex, (Integer) e.getNewValue()); - } else if (name.equals(TabInfo.ICON_PROPERTY)) { - tabs.setIconAt(tabIndex, (Icon) e.getNewValue()); - } else if (name.equals(TabInfo.DISABLED_ICON_PROPERTY)) { - tabs.setDisabledIconAt(tabIndex, (Icon) e.getNewValue()); - } else if (name.equals(TabInfo.TAB_COMPONENT_PROPERTY)) { - tabs.setTabComponentAt(tabIndex, (Component) e.getNewValue()); - } else if (name.equals(TabInfo.ENABLED_PROPERTY)) { - tabs.setEnabledAt(tabIndex, (Boolean) e.getNewValue()); - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/Table.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/Table.java deleted file mode 100644 index b93d36b..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/Table.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.JPanel; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.LayoutManager; - -/** - * Panel which uses a {@link GridBagLayout} by default. - * - * @author Ethan Nicholas - */ -public class Table extends JPanel { - - private static final long serialVersionUID = 1L; - - public static final Insets DEFAULT_INSETS = new Insets(3, 3, 3, 3); - - private GridBagConstraints tableConstraints = new GridBagConstraints(); - - private GridBagConstraints rowConstraints; - - private GridBagConstraints cellConstraints; - - public Table() { - super.setLayout(new GridBagLayout()); - - tableConstraints.insets = DEFAULT_INSETS; - } - - @Override - public void setLayout(LayoutManager layout) { - // do nothing - } - - public GridBagConstraints getTableConstraints() { - return tableConstraints; - } - - public GridBagConstraints getRowConstraints() { - return rowConstraints; - } - - public GridBagConstraints getCellConstraints() { - return cellConstraints; - } - - public void newRow() { - tableConstraints.gridy++; - rowConstraints = (GridBagConstraints) tableConstraints.clone(); - } - - public void newCell() { - rowConstraints.gridx++; - cellConstraints = (GridBagConstraints) rowConstraints.clone(); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBox.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBox.java deleted file mode 100644 index 46841b9..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBox.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.JPanel; -import java.awt.Insets; - -/** - * Panel which uses a {@link VBoxLayout} by default. - * - * @author Ethan Nicholas - */ -public class VBox extends JPanel { - - private static final long serialVersionUID = 1L; - - public static final String SPACING_PROPERTY = "spacing"; - - public static final String MARGIN_PROPERTY = "margin"; - - public static final String HORIZONTAL_ALIGNMENT_PROPERTY = "horizontalAlignment"; - - public static final String VERTICAL_ALIGNMENT_PROPERTY = "verticalAlignment"; - - private Insets margin; - - public VBox() { - super(new VBoxLayout()); - } - - /** - * Returns the spacing between components, in pixels. Spacing is applied between components only, - * not to the top or bottom of the container. - * - * @return spacing between components - */ - public int getSpacing() { - return ((VBoxLayout) getLayout()).getSpacing(); - } - - /** - * Sets the spacing between components. Spacing is applied between components only, - * not to the top or bottom of the container. - * - * @param spacing new spacing value - */ - public void setSpacing(int spacing) { - int oldValue = getSpacing(); - ((VBoxLayout) getLayout()).setSpacing(spacing); - firePropertyChange(SPACING_PROPERTY, oldValue, spacing); - revalidate(); - } - - public int getHorizontalAlignment() { - return ((VBoxLayout) getLayout()).getHorizontalAlignment(); - } - - public void setHorizontalAlignment(int horizontalAlignment) { - int oldValue = getHorizontalAlignment(); - ((VBoxLayout) getLayout()).setHorizontalAlignment(horizontalAlignment); - firePropertyChange(HORIZONTAL_ALIGNMENT_PROPERTY, oldValue, horizontalAlignment); - revalidate(); - } - - public int getVerticalAlignment() { - return ((VBoxLayout) getLayout()).getVerticalAlignment(); - } - - public void setVerticalAlignment(int verticalAlignment) { - int oldValue = getVerticalAlignment(); - ((VBoxLayout) getLayout()).setVerticalAlignment(verticalAlignment); - firePropertyChange(VERTICAL_ALIGNMENT_PROPERTY, oldValue, verticalAlignment); - revalidate(); - } - - public Insets getMargin() { - return margin; - } - - public void setMargin(Insets margin) { - Insets oldValue = this.margin; - this.margin = (Insets) margin.clone(); - firePropertyChange(MARGIN_PROPERTY, oldValue, margin); - } - - @Override - public Insets getInsets() { - Insets result = super.getInsets(); - if (margin != null) { - result.top += margin.top; - result.left += margin.left; - result.right += margin.right; - result.bottom += margin.bottom; - } - return result; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBoxBeanInfo.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBoxBeanInfo.java deleted file mode 100644 index 95633e5..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBoxBeanInfo.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.beans.SimpleBeanInfo; - -public class VBoxBeanInfo extends SimpleBeanInfo { - - @Override - public BeanInfo[] getAdditionalBeanInfo() { - try { - return new BeanInfo[]{Introspector.getBeanInfo(JPanel.class)}; - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - } - - @Override - public PropertyDescriptor[] getPropertyDescriptors() { - try { - PropertyDescriptor spacing = new PropertyDescriptor("spacing", VBox.class); - spacing.setBound(true); - - PropertyDescriptor margin = new PropertyDescriptor("margin", VBox.class); - margin.setBound(true); - - PropertyDescriptor horizontalAlignment = new PropertyDescriptor("horizontalAlignment", VBox.class); - horizontalAlignment.setBound(true); - horizontalAlignment.setValue("enumerationValues", new Object[]{ - "left", SwingConstants.LEFT, "SwingConstants.LEFT", - "center", SwingConstants.CENTER, "SwingConstants.CENTER", - "right", SwingConstants.RIGHT, "SwingConstants.RIGHT" - }); - - PropertyDescriptor verticalAlignment = new PropertyDescriptor("verticalAlignment", VBox.class); - verticalAlignment.setBound(true); - verticalAlignment.setValue("enumerationValues", new Object[]{ - "top", SwingConstants.TOP, "SwingConstants.TOP", - "middle", SwingConstants.CENTER, "SwingConstants.CENTER", - "bottom", SwingConstants.BOTTOM, "SwingConstants.BOTTOM" - }); - - return new PropertyDescriptor[]{spacing, margin, horizontalAlignment, verticalAlignment}; - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBoxLayout.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBoxLayout.java deleted file mode 100644 index a063939..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBoxLayout.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.SwingConstants; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Insets; -import java.awt.LayoutManager; - -/** - * Vertical box layout. The layout rules followed by this class are quite different than the core BoxLayout class, - * and in general represent a more useful algorithm. - * - * @author Ethan Nicholas - */ -public class VBoxLayout implements LayoutManager { - - private int spacing = 6; - - private int horizontalAlignment = SwingConstants.LEFT; - - private int verticalAlignment = SwingConstants.TOP; - - public int getSpacing() { - return spacing; - } - - public void setSpacing(int spacing) { - this.spacing = spacing; - } - - public int getHorizontalAlignment() { - return horizontalAlignment; - } - - public void setHorizontalAlignment(int horizontalAlignment) { - this.horizontalAlignment = horizontalAlignment; - } - - public int getVerticalAlignment() { - return verticalAlignment; - } - - public void setVerticalAlignment(int verticalAlignment) { - this.verticalAlignment = verticalAlignment; - } - - @Override - public void addLayoutComponent(String name, Component comp) { - } - - @Override - public void layoutContainer(Container parent) { - Insets insets = parent.getInsets(); - int parentWidth = parent.getSize().width - insets.left - insets.right; - int count = parent.getComponentCount(); - Dimension preferredSize = parent.getPreferredSize(); - int y; - switch (verticalAlignment) { - case SwingConstants.TOP: - y = insets.top; - break; - case SwingConstants.CENTER: - y = insets.top + (parent.getHeight() - preferredSize.height) / 2; - break; - case SwingConstants.BOTTOM: - y = insets.top + (parent.getHeight() - preferredSize.height); - break; - default: - throw new IllegalArgumentException("invalid vertical alignment: " + verticalAlignment); - } - - for (int i = 0; i < count; i++) { - Component component = parent.getComponent(i); - Dimension childPreferredSize = component.getPreferredSize(); - int width = Math.min(childPreferredSize.width, parentWidth); - int x; - switch (horizontalAlignment) { - case SwingConstants.LEFT: - x = insets.left; - break; - case SwingConstants.CENTER: - x = insets.left + (parentWidth - childPreferredSize.width) / 2; - break; - case SwingConstants.RIGHT: - x = insets.left + (parentWidth - childPreferredSize.width); - break; - default: - throw new IllegalArgumentException("invalid horizontal alignment: " + horizontalAlignment); - } - component.setBounds(x, y, width, childPreferredSize.height); - y += childPreferredSize.height + spacing; - } - } - - @Override - public Dimension minimumLayoutSize(Container parent) { - int width = 0; - int height = (parent.getComponentCount() - 1) * spacing; - for (int i = parent.getComponentCount() - 1; i >= 0; i--) { - Dimension minimumSize = parent.getComponent(i).getMinimumSize(); - width = Math.max(width, minimumSize.width); - height += minimumSize.height; - } - Insets insets = parent.getInsets(); - return new Dimension(width + insets.left + insets.right, height + insets.top + insets.bottom); - } - - @Override - public Dimension preferredLayoutSize(Container parent) { - int width = 0; - int height = (parent.getComponentCount() - 1) * spacing; - for (int i = parent.getComponentCount() - 1; i >= 0; i--) { - Dimension preferredSize = parent.getComponent(i).getPreferredSize(); - width = Math.max(width, preferredSize.width); - height += preferredSize.height; - } - Insets insets = parent.getInsets(); - return new Dimension(width + insets.left + insets.right, height + insets.top + insets.bottom); - } - - @Override - public void removeLayoutComponent(Component comp) { - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ActionExecutor.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ActionExecutor.java deleted file mode 100644 index 8b4b64f..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ActionExecutor.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.application; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.util.ReflectUtil; - -import javax.swing.SwingWorker; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.Date; -import java.util.HashSet; -import java.util.Set; - -/** - * Executor of {@link ActionWorker}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.1 - */ -public abstract class ActionExecutor { - - /** Logger */ - private static final Log log = - LogFactory.getLog(ActionExecutor.class); - - /** current tasks */ - protected final Set<ActionWorker<?, ?>> tasks = - new HashSet<ActionWorker<?, ?>>(); - - /** the listener of running action */ - protected final PropertyChangeListener workerListener; - - /** - * Hook when a action is about to start. - * - * @param source the action worker containing the action to perform - */ - public abstract void onActionStart(ActionWorker<?, ?> source); - - /** - * Hook when a action has failed. - * - * @param source the action worker containing the action to perform - */ - public abstract void onActionFail(ActionWorker<?, ?> source); - - /** - * Hook when a action has been canceled. - * - * @param source the action worker containing the action to perform - */ - public abstract void onActionCancel(ActionWorker<?, ?> source); - - /** - * Hook when a action has end with no failure or cancel. - * - * @param source the action worker containing the action to perform - */ - public abstract void onActionEnd(ActionWorker<?, ?> source); - - /** - * Hook atfer action is consumed. - * - * @param source the action worker containing the action to perform - */ - public abstract void onAfterAction(ActionWorker<?, ?> source); - - public ActionExecutor() { - workerListener = new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (log.isDebugEnabled()) { - log.debug("action " + evt.getSource() + " property " + - evt.getPropertyName() + " changed <" + - evt.getOldValue() + " - " + evt.getNewValue() + - '>'); - } - - if ("state".equals(evt.getPropertyName())) { - ActionWorker<?, ?> source = (ActionWorker<?, ?>) evt.getSource(); - SwingWorker.StateValue state = - (SwingWorker.StateValue) evt.getNewValue(); - - if (state == SwingWorker.StateValue.STARTED) { - // starting new action - - onActionStart(source); - return; - } - - if (state == SwingWorker.StateValue.DONE) { - // on rend la main au thread pour qu'il attende une - // prochaine operation - - ActionWorker.ActionStatus status = source.getStatus(); - if (log.isDebugEnabled()) { - log.debug("Action [" + source.getActionLabel() + - "] status = " + status); - } - try { - switch (status) { - - case OK: - onActionEnd(source); - break; - case CANCEL: - onActionCancel(source); - break; - case FAIL: - onActionFail(source); - break; - } - } finally { - tasks.remove(source); - onAfterAction(source); - } - } - } - } - }; - } - - /** - * Add an new action to perform. - * - * @param actionLabel the name of the action to perform - * @param action the action to perform - * @return the worker that will launch the action - */ - public ActionWorker<?, ?> addAction(String actionLabel, Runnable action) { - - ActionWorker<?, ?> worker; - if (action instanceof ActionWorker) { - - worker = (ActionWorker<?, ?>) action; - } else { - - worker = new ActionWorker(actionLabel, action); - } - worker.addPropertyChangeListener(workerListener); - tasks.add(worker); - worker.execute(); - return worker; - } - - /** - * Ask the thread to stop. - * - * It will finish all incoming files (but will not accept more tasks). - * - * <b>Note:</b> The method does not return until all tasks are not - * consumed. - * - * @throws InterruptedException if something wrong while waiting end of - * executor - */ - public void terminatesAndWaits() throws InterruptedException { - - if (log.isDebugEnabled()) { - log.debug("Executor " + this + " is terminating..."); - } - - // ask executor to terminate - for (ActionWorker<?, ?> task : tasks) { - task.cancel(true); - } - - if (log.isDebugEnabled()) { - log.debug("Executor " + this + " is terminated at " + new Date()); - } - } - - public int getNbActions() { - return getTasks().size(); - } - - public Set<ActionWorker<?, ?>> getTasks() { - return tasks; - } - - /** - * Creates a runnable instance (via a Proxy) to a method given by his name - * ({@code methodName}) to invoke on {@code methodcontainer} with given - * {@code arguments}. - * - * This is a great feature to create runnable code with a real context. - * - * @param methodContainer the container of the method to invoke - * @param methodName the name of the method to invoke - * @param arguments parameters to pass to method to invke. - * @return the proxy instance - */ - public Runnable createRunnable(final Object methodContainer, - String methodName, - final Object... arguments) { - - // find method - - Class<?> klass = methodContainer.getClass(); - final Method targetMethod = ReflectUtil.getDeclaredMethod(klass, - methodName, - true, - arguments - ); - targetMethod.setAccessible(true); - Runnable result; - - // create runnable proxy - - result = (Runnable) Proxy.newProxyInstance( - getClass().getClassLoader(), - new Class<?>[]{Runnable.class}, - new InvocationHandler() { - - @Override - public Object invoke(Object proxy, - Method method, - Object[] args) { - String methodName = method.getName(); - - if ("run".equals(methodName)) { - try { - if (log.isDebugEnabled()) { - log.debug("will invoke run method"); - } - return targetMethod.invoke(methodContainer, arguments); - } catch (IllegalAccessException e) { - throw new RuntimeException( - "could not invoke on container " + - methodContainer, e); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - } - if (methodName.equals("toString")) { - return toString(); - } - if (methodName.equals("equals")) { - return equals(args[0]); - } - if (methodName.equals("hashCode")) { - return hashCode(); - } - return null; - } - } - ); - return result; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ActionWorker.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ActionWorker.java deleted file mode 100644 index 46535cf..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ActionWorker.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.application; - -import com.google.common.base.Preconditions; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.util.StringUtil; - -import javax.swing.SwingWorker; -import java.util.concurrent.Callable; - -/** - * Action worker to execute a incoming action. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.1 - */ -public class ActionWorker<R, P> extends SwingWorker<R, P> { - - /** Logger */ - private static final Log log = LogFactory.getLog(ActionWorker.class); - - protected final String actionLabel; - - protected Callable<R> target; - - protected ActionStatus status; - - protected Exception error; - - protected long startTime; - - protected long endTime; - - public ActionWorker(String actionLabel) { - this.actionLabel = actionLabel; - } - - public ActionWorker(String actionLabel, Runnable target) { - this.target = new RunnableBridge<R>(target); - this.actionLabel = actionLabel; - } - - public Callable<R> getTarget() { - return target; - } - - public void setTarget(Runnable target) { - setTarget(new RunnableBridge<R>(target)); - } - - /** - * Set the target to execute. - * - * @param target the target to execute - * @since 2.5.1 - */ - public void setTarget(Callable<R> target) { - this.target = target; - } - - @Override - protected R doInBackground() throws Exception { - Preconditions.checkNotNull(target != null, "Targe field can not be null here."); - startTime = System.nanoTime(); - if (log.isDebugEnabled()) { - log.debug("Action [" + getActionLabel() + "] is starting..."); - } - R result = null; - try { - - result = getTarget().call(); - } catch (Exception e) { - error = e; - } finally { - if (log.isDebugEnabled()) { - log.debug("Action [" + getActionLabel() + "] is ending..."); - } - } - return result; - } - - public boolean isFailed() { - return (isDone() || isCancelled()) && error != null; - } - - public Exception getError() { - return error; - } - - public ActionStatus getStatus() { - return status; - } - - public String getActionLabel() { - return actionLabel; - } - - @Override - protected void done() { - super.done(); - endTime = System.nanoTime(); - if (error != null) { - status = ActionStatus.FAIL; - } else if (isCancelled()) { - status = ActionStatus.CANCEL; - } else { - status = ActionStatus.OK; - } - if (log.isDebugEnabled()) { - log.debug("Action [" + getActionLabel() + "] ends with status : " + status + " in " + getTime()); - } - } - - public String getTime() { - return StringUtil.convertTime(endTime - startTime); - } - - public long getStartTime() { - return startTime; - } - - public long getEndTime() { - return endTime; - } - - /** State of a running action */ - public enum ActionStatus { - OK, - CANCEL, - FAIL - } - - /** - * Transform a {@link Runnable} into a {@link Callable}. - * - * @param <R> type of return (used to maintain generic checks in this class). - * @since 2.5.1 - */ - private static class RunnableBridge<R> implements Callable<R> { - - private final Runnable target; - - public RunnableBridge(Runnable target) { - this.target = target; - } - - @Override - public R call() throws Exception { - target.run(); - return null; - } - } - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ApplicationRunner.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ApplicationRunner.java deleted file mode 100644 index 2c7614b..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ApplicationRunner.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.application; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Simple application runner which authorize to reload an application. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.1 - */ -public abstract class ApplicationRunner { - - /** Logger */ - private static Log log = LogFactory.getLog(ApplicationRunner.class); - - private static final Object lock = new Object(); - - private static ApplicationRunner runner; - - public static ApplicationRunner getRunner() { - if (runner == null) { - throw new IllegalStateException("No runner initialized"); - } - return runner; - } - - public static void lock() throws InterruptedException { - synchronized (lock) { - // on arrete le thread principal - // pour rendre la main a la methode main - lock.wait(); - } - } - - public static void unlock() { - synchronized (lock) { - // on arrete le thread principal - // pour rendre la main a la methode main - lock.notifyAll(); - } - } - - /** arguments given to runner at launch time */ - protected final String[] args; - - /** flag to reload the runner when closing it */ - protected boolean reload; - - /** the runner to start application */ - protected final Runnable runnable; - - protected long startingTime; - - protected Exception error; - - /** - * To execute some code only once. - * - * This code will not be re-execute when reloading the runner. - */ - protected abstract void initOnce(); - - /** - * Hook to init runner. - * - * @throws Exception if any problem - */ - protected abstract void onInit() throws Exception; - - /** - * Hook to start runner. - * - * @throws Exception if any problem - */ - protected abstract void onStart() throws Exception; - - /** - * Hook to close runner. - * - * @param reload if reload was asked - * @throws Exception if any problme - */ - protected abstract void onClose(boolean reload) throws Exception; - - /** - * Hook to shutdown launcher - * - * @throws Exception if any problem - */ - protected abstract void onShutdown() throws Exception; - - /** - * Hook to shutdown launcher when an exception occurs on clsoing. - * - * @param ex the error catched while closing launcher - */ - protected abstract void onShutdown(Exception ex); - - /** - * Hook when an error occurs in runner. - * - * @param e the error catched - */ - protected abstract void onError(Exception e); - - protected ApplicationRunner(String... args) { - runner = this; - this.args = args; - - initOnce(); - - runnable = new Runnable() { - @Override - public void run() { - startingTime = System.nanoTime(); - try { - - onInit(); - - onStart(); - - } catch (Exception e) { - error = e; - onError(e); - unlock(); - } - } - }; - - Thread shutdownHook = new Thread(new Runnable() { - - @Override - public void run() { - try { - - //onClose(false); - onShutdown(); - - } catch (Exception e) { - error = e; - onShutdown(e); - } - } - }, "ShutDown " + getClass().getSimpleName()); - - Runtime.getRuntime().addShutdownHook(shutdownHook); - } - - public boolean isReload() { - return reload; - } - - public void setReload(boolean reload) { - this.reload = reload; - } - - protected Thread mainThread; - - public final void launch() { - - // au demarrage le reload est toujours desactive - reload = false; - - // preparation du thread de l'application principale - // que l'on démarre - mainThread = new Thread(runnable, getClass().getSimpleName()); - mainThread.start(); - - try { - - // on attend que l'application se termine ou demande un redémarrage - lock(); - - // on va libérer le runner - log.info("Application [" + mainThread + "] is closing..."); - - } catch (InterruptedException e) { - if (log.isErrorEnabled()) { - log.error(mainThread + " was interrupted for reason " + e.getMessage(), e); - } - } finally { - - close(); - - } - } - - public final void close() { - boolean doReload = isReload(); - - try { - - // fermeture du runner - onClose(doReload); - - if (doReload) { - - // redemarrage du runner - - if (log.isInfoEnabled()) { - log.info("Will reload application"); - } - - System.runFinalization(); - - launch(); - } - - } catch (Exception e) { - onError(e); - } finally { - if (!doReload) { - if (log.isDebugEnabled()) { - log.debug("Will shutdown application ..."); - } - - unlock(); - - // force to shutdown - Runtime.getRuntime().exit(0); - } - } - } - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/BooleanCellEditor.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/BooleanCellEditor.java deleted file mode 100644 index 89f6618..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/BooleanCellEditor.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.editor; - -import java.awt.Component; -import javax.swing.AbstractCellEditor; -import javax.swing.Icon; -import javax.swing.JCheckBox; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableCellRenderer; -import org.jdesktop.swingx.JXTable; - -/** - * @author Tony Chemit - chemit@codelutin.com - * @since 1.5 - */ -public class BooleanCellEditor extends AbstractCellEditor implements TableCellRenderer, TableCellEditor { - - private static final long serialVersionUID = 1L; - - protected TableCellRenderer rendererDelegate; - protected TableCellEditor editorDelegate; - - protected Icon icon; - - public BooleanCellEditor(TableCellRenderer delegate) { - this(delegate, null); - } - - public BooleanCellEditor(TableCellRenderer delegate, Icon icon) { - this.rendererDelegate = delegate; - this.editorDelegate = new JXTable.BooleanEditor(); - this.icon = icon; - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - JComponent rendered = (JComponent) rendererDelegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - if (rendered instanceof JCheckBox) { - JCheckBox checkBox = (JCheckBox)rendered; - checkBox.setHorizontalAlignment(JLabel.CENTER); - checkBox.setVerticalTextPosition(JLabel.TOP); - checkBox.setBorderPainted(true); - checkBox.setIcon(icon); - } - return rendered; - } - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - return editorDelegate.getTableCellEditorComponent(table, value, isSelected, row, column); - } - - @Override - public Object getCellEditorValue() { - return editorDelegate.getCellEditorValue(); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/ClassCellEditor.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/ClassCellEditor.java deleted file mode 100644 index 5b37baf..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/ClassCellEditor.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.editor; - -import org.apache.commons.beanutils.Converter; -import org.nuiton.converter.ConverterUtil; - -import javax.swing.DefaultCellEditor; -import javax.swing.JTable; -import javax.swing.JTextField; -import javax.swing.event.CellEditorListener; -import javax.swing.table.TableCellEditor; -import java.awt.Component; -import java.util.EventObject; - -/** - * A class cell editor (fork from comandline project). - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class ClassCellEditor implements TableCellEditor { - - protected TableCellEditor delegate; - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - - String valStr; - - if (value instanceof Class<?>) { - valStr = ((Class<?>) value).getName(); - } else { - valStr = (value + "").trim(); - if (valStr.equals("null")) { - valStr = ""; - } else if (valStr.startsWith("class ")) { - valStr = valStr.substring(6); - } - } - Component comp; - comp = getDelegate().getTableCellEditorComponent(table, valStr, isSelected, row, column); - return comp; - } - - @Override - public Object getCellEditorValue() { - Object o = !hasDelegate() ? null : delegate.getCellEditorValue(); - if (o == null) { - return null; - } - Converter converter = ConverterUtil.getConverter(Class.class); - - try { - if (converter != null) { - return converter.convert(Class.class, o); - } - o = Class.forName(o + ""); - } catch (Exception e) { - o = null; - } - return o; - } - - @Override - public boolean isCellEditable(EventObject anEvent) { - return !hasDelegate() || delegate.isCellEditable(anEvent); - } - - @Override - public boolean shouldSelectCell(EventObject anEvent) { - return hasDelegate() && delegate.shouldSelectCell(anEvent); - } - - @Override - public boolean stopCellEditing() { - return !hasDelegate() || delegate.stopCellEditing(); - } - - @Override - public void cancelCellEditing() { - if (hasDelegate()) { - delegate.cancelCellEditing(); - } - } - - @Override - public void addCellEditorListener(CellEditorListener l) { - if (hasDelegate()) { - delegate.addCellEditorListener(l); - } - } - - @Override - public void removeCellEditorListener(CellEditorListener l) { - if (hasDelegate()) { - delegate.removeCellEditorListener(l); - } - } - - protected TableCellEditor getDelegate() { - if (delegate == null) { - delegate = new DefaultCellEditor(new JTextField()); - } - return delegate; - } - - protected boolean hasDelegate() { - return delegate != null; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/ColorCellEditor.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/ColorCellEditor.java deleted file mode 100644 index b1a2e18..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/ColorCellEditor.java +++ /dev/null @@ -1,128 +0,0 @@ -package jaxx.runtime.swing.editor; -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import javax.swing.AbstractCellEditor; -import javax.swing.JButton; -import javax.swing.JColorChooser; -import javax.swing.JDialog; -import javax.swing.JTable; -import javax.swing.table.TableCellEditor; -import java.awt.Color; -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -/** - * A {@link Color} cell editor. - * - * @author Matthieu Allon - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.4 - */ -public class ColorCellEditor extends AbstractCellEditor - implements TableCellEditor, - ActionListener { - - private static final long serialVersionUID = 1L; - - protected Color currentColor; - - protected JButton button; - - protected JColorChooser colorChooser; - - protected JDialog dialog; - - protected static final String EDIT = "edit"; - - public ColorCellEditor() { - //Set up the editor (from the table's point of view), - //which is a button. - //This button brings up the color chooser dialog, - //which is the editor from the user's point of view. - button = new JButton(); - button.setActionCommand(EDIT); - button.addActionListener(this); - button.setBorderPainted(false); - - //Set up the dialog that the button brings up. - colorChooser = new JColorChooser(); - dialog = JColorChooser.createDialog(button, - "", - true, //modal - colorChooser, - this, //OK button handler - null); //no CANCEL button handler - } - - /** - * Handles events from the editor button and from - * the dialog's OK button. - */ - @Override - public void actionPerformed(ActionEvent e) { - if (EDIT.equals(e.getActionCommand())) { - //The user has clicked the cell, so - //bring up the dialog. - button.setBackground(currentColor); - colorChooser.setColor(currentColor); - dialog.setVisible(true); - - //Make the renderer reappear. - fireEditingStopped(); - - } else { //User pressed dialog's "OK" button. - currentColor = colorChooser.getColor(); - } - } - - @Override - public Color getCellEditorValue() { - //String currentColorHexa = toHex(currentColor.getRed(), currentColor.getGreen(), currentColor.getBlue()); - return currentColor; - } - - protected static String toHex(int r, int g, int b) { - return "#" + toBrowserHexValue(r) + toBrowserHexValue(g) + toBrowserHexValue(b); - } - - protected static String toBrowserHexValue(int number) { - StringBuilder builder = new StringBuilder(Integer.toHexString(number & 0xff)); - while (builder.length() < 2) { - builder.append("0"); - } - return builder.toString().toUpperCase(); - } - - - @Override - public Component getTableCellEditorComponent(JTable table, - Object value, - boolean isSelected, - int row, - int column) { - currentColor = (Color) value; - button.setBackground(currentColor); - return button; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/EnumEditor.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/EnumEditor.java deleted file mode 100644 index 1b99aa4..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/EnumEditor.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -/* - * *##% - * JAXX Runtime - * Copyright (C) 2008 - 2009 CodeLutin - * - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * ##%* */ -package jaxx.runtime.swing.editor; - -import org.nuiton.util.ReflectUtil; - -import javax.swing.JComboBox; -import java.util.EnumSet; -import java.util.Iterator; - -/** - * Une éditeur d'enum. - * - * @param <E> le type d'enumeration a editer. - * @author Tony Chemit - chemit@codelutin.com - * @since 1.6.0 - */ -public class EnumEditor<E extends Enum<E>> extends JComboBox { - - private static final long serialVersionUID = 2L; - - /** Type of enumeration */ - protected Class<E> type; - - /** - * Creates a {@link EnumEditor} for the given enumeration {@code type}, with - * all values of enumeration. - * - * @param type type of enumeration - * @param <E> generci type of enumeration - * @return the instanciated editor - */ - public static <E extends Enum<E>> EnumEditor<E> newEditor(Class<E> type) { - return new EnumEditor<E>(type); - } - - - /** - * Creates a {@link EnumEditor} for the given enumeration {@code type}, with - * all values of enumeration which {@code ordinal} is strictly lower than - * the given {@code maxOrdinal}. - * - * @param type type of enumeration - * @param maxOrdinal the upper (strict) bound of ordinal values allowed - * @param <E> generic type of enumeration - * @return the instanciated editor - */ - public static <E extends Enum<E>> EnumEditor<E> newEditor(Class<E> type, - int maxOrdinal) { - return new EnumEditor<E>(type, maxOrdinal); - } - - /** - * Creates a {@link EnumEditor} for the given enumeration {@code type}, with - * all given {@code universe} values of enumeration. - * - * @param universe enumerations to put in editor - * @param <E> generci type of enumeration - * @return the instanciated editor - */ - public static <E extends Enum<E>> EnumEditor<E> newEditor(E... universe) { - return new EnumEditor<E>(universe); - } - - public EnumEditor(Class<E> type) { - super(buildModel(type)); - this.type=type; - } - - public EnumEditor(Class<E> type, int maxOrdinal) { - super(buildModel(type, maxOrdinal)); - this.type=type; - } - - public EnumEditor(E... universe) { - super(universe); - } - - @Override - public E getSelectedItem() { - return (E) super.getSelectedItem(); - } - - public Class<E> getType() { - return type; - } - - protected static <E extends Enum<E>> Object[] buildModel(Class<E> type) { - Class<E> enumClass = ReflectUtil.getEnumClass(type); - EnumSet<E> result = EnumSet.allOf(enumClass); - return result.toArray(new Object[result.size()]); - } - - - protected static <E extends Enum<E>> Object[] buildModel(Class<E> type, - int maxOrdinal) { - Class<E> enumClass = ReflectUtil.getEnumClass(type); - EnumSet<E> result = EnumSet.allOf(enumClass); - Iterator<E> itr = result.iterator(); - while (itr.hasNext()) { - E e = itr.next(); - if (e.ordinal() > maxOrdinal) { - itr.remove(); - } - } - return result.toArray(new Object[result.size()]); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/LocaleEditor.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/LocaleEditor.java deleted file mode 100644 index 2238611..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/LocaleEditor.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.editor; - -import org.nuiton.i18n.I18n; -import org.nuiton.i18n.I18nStore; - -import javax.swing.JComboBox; -import java.util.Locale; - -/** - * A {@link Locale} editor. - * - * use the static method to have an instance of editor - * {@link #newEditor(Locale...)} - * - * If no locale is given to this method, it will go and seek via - * {@link I18nStore#getLocales()} all loaded locales in i18n system - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.6.0 - */ -public class LocaleEditor extends JComboBox { - - /** serialVersionUID */ - private static final long serialVersionUID = -6777873426011538807L; - - protected Locale[] type; - - public static LocaleEditor newEditor(Locale... type) { - return new LocaleEditor(type); - } - - public LocaleEditor(Locale... type) { - super(buildModel(type)); - } - - @Override - public Locale getSelectedItem() { - return (Locale) super.getSelectedItem(); - } - - protected static Locale[] buildModel(Locale... type) { - if (type.length > 0) { - return type; - } - // get availables locales registred in I18n system - type = I18n.getStore().getLocales(); - return type; - } - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/MyDefaultCellEditor.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/MyDefaultCellEditor.java deleted file mode 100644 index fa9f2dc..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/MyDefaultCellEditor.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.editor; - -import javax.swing.DefaultCellEditor; -import javax.swing.Icon; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JTable; -import javax.swing.JTextField; -import javax.swing.table.TableCellEditor; -import java.awt.Component; - -/** - * @author Tony Chemit - chemit@codelutin.com - * @since 1.5 - */ -public class MyDefaultCellEditor extends DefaultCellEditor { - - private static final long serialVersionUID = 1L; - - public static TableCellEditor newTextEditor() { - return new MyDefaultCellEditor(new JTextField()); - } - - public static TableCellEditor newBooleanEditor() { - return new MyDefaultCellEditor(new JCheckBox()); - } - - public static TableCellEditor newListEditor() { - return newListEditor(new JComboBox()); - } - - public static TableCellEditor newListEditor(JComboBox editor) { - return new MyDefaultCellEditor(editor); - } - - public static TableCellEditor newEnumEditor(EnumEditor<?> editor) { - return new MyDefaultCellEditor(editor) { - - private static final long serialVersionUID = 1L; - - @Override - public Object getCellEditorValue() { - Object value = super.getCellEditorValue(); - if (value != null) { - value = ((Enum) value).ordinal(); - } else { - value = -1; - } - return value; - } - }; - } - - public static TableCellEditor newBooleanEditor(Icon icon) { - return new MyDefaultCellEditor(new JCheckBox(icon)); - } - - public static TableCellEditor newBooleanEditor(Icon icon, boolean requireSelect) { - TableCellEditor cellEditor = newBooleanEditor(icon); - ((MyDefaultCellEditor) cellEditor).setRequireSelect(requireSelect); - return cellEditor; - } - - public static TableCellEditor newBooleanEditor(boolean requireSelect) { - TableCellEditor cellEditor = newBooleanEditor(); - ((MyDefaultCellEditor) cellEditor).setRequireSelect(requireSelect); - return cellEditor; - } - - protected boolean requireSelect = true; - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - if (!isSelected && requireSelect) { - // force to have select the cell before editing, a way to not modify edition for nothing... - return null; - } - return super.getTableCellEditorComponent(table, value, isSelected, row, column); - } - - public boolean isRequireSelect() { - return requireSelect; - } - - public void setRequireSelect(boolean requireSelect) { - this.requireSelect = requireSelect; - } - - protected MyDefaultCellEditor(JTextField textField) { - super(textField); - setClickCountToStart(1); - } - - protected MyDefaultCellEditor(JCheckBox checkBox) { - super(checkBox); - setClickCountToStart(1); - } - - protected MyDefaultCellEditor(JComboBox comboBox) { - super(comboBox); - setClickCountToStart(1); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpBroker.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpBroker.java deleted file mode 100644 index 0e5b28f..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpBroker.java +++ /dev/null @@ -1,613 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.help; - -import com.google.common.base.Preconditions; -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.awt.visitor.BuildTreeVisitor; -import jaxx.runtime.awt.visitor.ComponentTreeNode; -import jaxx.runtime.awt.visitor.GetCompopentAtPointVisitor; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.help.CSH; -import javax.help.HelpBroker; -import javax.help.HelpSet; -import javax.help.plaf.basic.BasicCursorFactory; -import javax.swing.AbstractButton; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import java.applet.Applet; -import java.awt.AWTEvent; -import java.awt.ActiveEvent; -import java.awt.Component; -import java.awt.Container; -import java.awt.Cursor; -import java.awt.EventQueue; -import java.awt.Frame; -import java.awt.MenuComponent; -import java.awt.Point; -import java.awt.Toolkit; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.net.URL; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Locale; -import java.util.Map; -import java.util.Vector; - -/** - * La classe pour encapsuler l'aide de l'application. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.4 - */ -public class JAXXHelpBroker { - - public static final String JAXX_CONTEXT_ENTRY = "jaxxcontext"; - - /** Logger */ - static private Log log = LogFactory.getLog(JAXXHelpBroker.class); - - /** name of helpset */ - protected final String helpsetName; - - /** default id to use if none given */ - protected final String defaultID; - - /** help key */ - protected final String helpKey; - - /** helpset to use */ - protected HelpSet helpset; - - /** help broker */ - protected HelpBroker helpBroker; - - /** current locale used */ - protected Locale locale; - - /** cache of cursors modified when in context-sensitive mode */ - protected Hashtable<Component, Cursor> cursors; - - /** cursor to use in context-sensitive mode */ - protected Cursor onItemCursor; - - /** cache of component which cursor have been modified */ - protected final Map<Component, String> cache; - - /** help ui handler */ - protected JAXXHelpUIHandler handler; - - public JAXXHelpBroker(String helpsetName, String helpKey, String defaultID, JAXXHelpUIHandler handler) { - this(null, helpsetName, helpKey, defaultID, handler); - } - - public JAXXHelpBroker(Locale locale, String helpsetName, String helpKey, String defaultID, JAXXHelpUIHandler handler) { - if (helpsetName == null) { - throw new NullPointerException("parameter helpsetName can not be null!"); - } - if (handler == null) { - throw new NullPointerException("handler can not be null"); - } - this.locale = locale; - this.helpsetName = helpsetName; - this.helpKey = helpKey; - this.defaultID = defaultID; - this.handler = handler; - this.cache = new HashMap<Component, String>(); - } - - public void prepareUI(JAXXObject c) { - if (c == null) { - throw new NullPointerException("parameter c can not be null!"); - } - - // l'ui doit avoir un boutton showHelp - AbstractButton help = getShowHelpButton(c); - - if (help == null) { - // no showHelp button - return; - } - - // attach context to button - if (log.isDebugEnabled()) { - log.debug("attach context to showhelp button " + c); - } - help.putClientProperty(JAXX_CONTEXT_ENTRY, c); - - // add tracking action - ActionListener listener = getShowHelpAction(); - if (log.isDebugEnabled()) { - log.debug("adding tracking action " + listener); - } - help.addActionListener(listener); - - if (log.isDebugEnabled()) { - log.debug("done for " + c); - } - - - getHelpBroker().enableHelpKey(((Component) c), getDefaultID(), getHelpset()); - } - - public void showHelp(JAXXContext context, String helpId) { - getHandler().showHelp(context, this, helpId); - } - - public JAXXHelpUIHandler getHandler() { - return handler; - } - - public HelpBroker getHelpBroker() { - if (helpBroker == null) { - helpBroker = getHelpset().createHelpBroker(); - } - return helpBroker; - } - - public String getHelpKey() { - return helpKey; - } - - public HelpSet getHelpset() { - if (helpset == null) { - try { - ClassLoader cl = getClass().getClassLoader(); - URL url = HelpSet.findHelpSet(cl, helpsetName, locale); - helpset = new HelpSet(cl, url); - } catch (Exception ee) { - throw new IllegalStateException("could not find help set " + helpsetName + " for reason " + ee.getMessage(), ee); - } - } - return helpset; - } - - public String getHelpsetName() { - return helpsetName; - } - - public String getDefaultID() { - return defaultID; - } - - public void setLocale(Locale locale) { - this.locale = locale; - // need to reload helpset and helpbroker - helpset = null; - helpBroker = null; - getHelpset(); - getHelpBroker(); - } - - public void showHelpSet() { - if (log.isDebugEnabled()) { - log.debug(this); - } - new CSH.DisplayHelpFromSource(getHelpBroker()); - } - - public void installUI(Component comp, String helpId) { - CSH.setHelpIDString(comp, helpId); - if (log.isDebugEnabled()) { - log.debug(helpId + " : " + comp.getName()); - } - cache.put(comp, helpId); - } - - public class ShowHelpForTrackedComponentAction implements ActionListener { - - @Override - public void actionPerformed(ActionEvent e) { - AbstractButton source = (AbstractButton) e.getSource(); - - JAXXContext context = (JAXXContext) source.getClientProperty(JAXX_CONTEXT_ENTRY); - - // prepare cursor - onItemCursor = (Cursor) UIManager.get("HelpOnItemCursor"); - - if (onItemCursor == null) { - onItemCursor = BasicCursorFactory.getOnItemCursor(); - UIManager.put("HelpOnItemCursor", onItemCursor); - } - Preconditions.checkNotNull(onItemCursor, "A cursor is missing (add HelpOnItemCursor cursor in UIManager)."); - Vector<?> topComponents = null; - cursors = null; - - if (onItemCursor != null) { - cursors = new Hashtable<Component, Cursor>(); - topComponents = getTopContainers(source); - for (Object topComponent : topComponents) { - setAndStoreCursors((Container) topComponent, onItemCursor); - } - } - - // get the tracked component - Component comp = null; - try { - MouseEvent event = getMouseEvent(); - if (event == null) { - // tracking canceled - return; - } - comp = (Component) event.getSource(); - if (log.isDebugEnabled()) { - log.debug("component traking " + comp.getName() + " : " + comp.getClass().getName()); - } - comp = getDeppestComponent(comp, event); - if (log.isDebugEnabled()) { - log.debug("deepest component " + comp.getName() + " : " + comp.getClass().getName()); - } - } finally { - // restore the old cursors - if (topComponents != null) { - for (Object topComponent : topComponents) { - resetAndRestoreCursors((Container) topComponent); - } - } - cursors = null; - } - - String helpID = findHelpId(comp); - showHelp(context, helpID); - } - } - - protected AbstractButton getShowHelpButton(JAXXObject c) { - return (AbstractButton) c.getObjectById("showHelp"); - } - - protected ActionListener getShowHelpAction() { - return new ShowHelpForTrackedComponentAction(); - } - - protected Component getDeppestComponent(Component mouseComponent, MouseEvent event) { - ComponentTreeNode tree = BuildTreeVisitor.buildTree(mouseComponent); - - Point point = event.getLocationOnScreen(); - - Component component = GetCompopentAtPointVisitor.get(tree, point); - if (log.isDebugEnabled()) { - log.debug("Component at (" + point + "): " + component); - } - return component; -// return SwingUtil.getDeepestObjectAt(mouseComponent, event.getX(), event.getY()); - } - - public String findHelpId(Component comp) { - String helpID = CSH.getHelpIDString(comp); - if (defaultID.equals(helpID)) { - String id = cache.get(comp); - // on verifie qu'on est bien sur sur le bon id - if (helpID.equals(id)) { - // ok - return helpID; - } - if (log.isDebugEnabled()) { - log.debug("will try to find better id for comp : " + comp.getName()); - } - // on est pas sur le bon id - // on recherche parmis les parents - helpID = findExtactHelpId(comp); - } - if (log.isInfoEnabled()) { - log.info("helpID " + helpID + " for comp " + comp.getName() + " : " + comp.getClass().getName()); - } - return helpID; - } - - protected String findExtactHelpId(Component comp) { - Container parent = comp.getParent(); - while (parent != null) { - String id = cache.get(parent); - if (id == null) { - // ce container n'a pas d'id - // on va directement sur le parent - parent = parent.getParent(); - continue; - } - // le parent possède un id - // on utilise cet id - return id; - } - // on a pas trouve d'id - // on retourne l'id par defaut - return defaultID; - } - - //------------------------------------------------------------------------- - //--- Copy CSH code but with accessible modifiers and little improvments - //------------------------------------------------------------------------- - /* - * Get all top level containers to change it's cursors - */ - - protected Vector<?> getTopContainers(Object source) { - // This method is used to obtain all top level components of application - // for which the changing of cursor to question mark is wanted. - // Method Frame.getFrames() is used to get list of Frames and - // Frame.getOwnedWindows() method on elements of the list - // returns all Windows, Dialogs etc. It works correctly in application. - // Problem is in applets. There is no way how to get reference to applets - // from elsewhere than applet itself. So, if request for CSH (this means - // pressing help button or select help menu item) does't come from component - // in a Applet, cursor for applets is not changed to question mark. Only for - // Frames, Windows and Dialogs is cursor changed properly. - - Vector<Component> containers = new Vector<Component>(); - Component topComponent = null; - topComponent = getRoot(source); - if (topComponent instanceof Applet) { - try { - Enumeration<Applet> applets = ((Applet) topComponent).getAppletContext().getApplets(); - while (applets.hasMoreElements()) { - containers.add(applets.nextElement()); - } - } catch (NullPointerException npe) { - containers.add(topComponent); - } - } - Frame frames[] = Frame.getFrames(); - for (Frame frame : frames) { - Window[] windows = frame.getOwnedWindows(); - Collections.addAll(containers, windows); - if (!containers.contains(frame)) { - containers.add(frame); - } - } - return containers; - } - - protected Component getRoot(Object comp) { - Object parent = comp; - while (parent != null) { - comp = parent; - if (comp instanceof MenuComponent) { - parent = ((MenuComponent) comp).getParent(); - } else if (comp instanceof Component) { - if (comp instanceof Window) { - break; - } - if (comp instanceof Applet) { - break; - } - parent = ((Component) comp).getParent(); - } else { - break; - } - } - if (comp instanceof Component) { - return ((Component) comp); - } - return null; - } - - /* - * Set the cursor for a component and its children. - * Store the old cursors for future resetting - */ - - protected void setAndStoreCursors(Component comp, Cursor cursor) { - if (comp == null) { - return; - } - if (cache.containsKey(comp)) { - Cursor compCursor = comp.getCursor(); - if (compCursor != cursor) { - cursors.put(comp, compCursor); - if (log.isDebugEnabled()) { - log.debug("set cursor on " + comp); - } - comp.setCursor(cursor); - } - } - - if (comp instanceof Container) { - Component component[] = ((Container) comp).getComponents(); - for (Component aComponent : component) { - setAndStoreCursors(aComponent, cursor); - } - } - } - - /* - * Actually restore the cursor for a component and its children - */ - - protected void resetAndRestoreCursors(Component comp) { - if (comp == null) { - return; - } - Cursor oldCursor = cursors.get(comp); - if (oldCursor != null) { - log.debug("restored cursor " + oldCursor + " on " + comp); - comp.setCursor(oldCursor); - } - if (comp instanceof Container) { - Component component[] = ((Container) comp).getComponents(); - for (Component aComponent : component) { - resetAndRestoreCursors(aComponent); - } - } - } - - /** - * Context Sensitive Event Tracking - * - * Creates a new EventDispatchThread from which to dispatch events. This - * method returns when stopModal is invoked. - * - * @return MouseEvent The mouse event occurred. Null if - * cancelled on an undetermined object. - */ - public static MouseEvent getMouseEvent() { - // Should the cursor change to a quesiton mark here or - // require the user to change the cursor externally to this method? - // The problem is that each component can have it's own cursor. - // For that reason it might be better to have the user change the - // cusor rather than us. - - // To track context-sensitive events get the event queue and process - // the events the same way EventDispatchThread does. Filter out - // ContextSensitiveEvents SelectObject & Cancel (MouseDown & ???). - // Note: This code only handles mouse events. Accessiblity might - // require additional functionality or event trapping - - // If the eventQueue can't be retrieved, the thread gets interrupted, - // or the thread isn't a instanceof EventDispatchThread then return - // a null as we won't be able to trap events. - try { - if (EventQueue.isDispatchThread()) { - EventQueue eq = null; - - // Find the eventQueue. If we can't get to it then just return - // null since we won't be able to trap any events. - - try { - eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); - } catch (Exception ee) { - log.debug(ee); - } - - // Safe guard - if (eq == null) { - return null; - } - - int eventNumber = -1; - - // Process the events until an object has been selected or - // the context-sensitive search has been canceled. - while (true) { - // This is essentially the body of EventDispatchThread - // modified to trap context-senstive events and act - // appropriately - eventNumber++; - AWTEvent event = eq.getNextEvent(); - Object src = event.getSource(); - // can't call eq.dispatchEvent - // so I pasted it's body here - - if (log.isDebugEnabled()) { - log.debug(event); - } - - // Not sure if I should suppress ActiveEvents or not - // Modal dialogs do. For now we will not suppress the - // ActiveEvent events - - if (event instanceof ActiveEvent) { - ((ActiveEvent) event).dispatch(); - continue; - } - - if (src instanceof Component) { - // Trap the context-sensitive events here - if (event instanceof KeyEvent) { - KeyEvent e = (KeyEvent) event; - // if this is the cancel key then exit - // otherwise pass all other keys up - if (e.getKeyCode() == KeyEvent.VK_CANCEL || - e.getKeyCode() == KeyEvent.VK_ESCAPE) { - e.consume(); - return null; - } else { - e.consume(); - // dispatchEvent(event); - } - } else if (event instanceof MouseEvent) { - MouseEvent e = (MouseEvent) event; - int eID = e.getID(); - - if ((eID == MouseEvent.MOUSE_CLICKED || - eID == MouseEvent.MOUSE_PRESSED || - eID == MouseEvent.MOUSE_RELEASED) && - SwingUtilities.isRightMouseButton(e)) { - // cancel tracking - e.consume(); - if (log.isDebugEnabled()) { - log.debug("tracking canceled!!!"); - } - return null; - } - - if ((eID == MouseEvent.MOUSE_CLICKED || - eID == MouseEvent.MOUSE_PRESSED || - eID == MouseEvent.MOUSE_RELEASED) && - SwingUtilities.isLeftMouseButton(e)) { - if (eID == MouseEvent.MOUSE_CLICKED) { - if (eventNumber == 0) { - dispatchEvent(event); - continue; - } - } - e.consume(); - return e; - } else { - e.consume(); - } - } else { - dispatchEvent(event); - } - } else if (src instanceof MenuComponent) { - if (event instanceof InputEvent) { - ((InputEvent) event).consume(); - } - } else { - log.error("unable to dispatch event: " + event); - } - } - } - } catch (InterruptedException e) { - if (log.isDebugEnabled()) { - log.debug(e); - } - } - if (log.isDebugEnabled()) { - log.debug("Fall Through code"); - } - return null; - } - - protected static void dispatchEvent(AWTEvent event) { - Object src = event.getSource(); - if (event instanceof ActiveEvent) { - // This could become the sole method of dispatching in time. - ((ActiveEvent) event).dispatch(); - } else if (src instanceof Component) { - ((Component) src).dispatchEvent(event); - } else if (src instanceof MenuComponent) { - ((MenuComponent) src).dispatchEvent(event); - } else { - log.error("unable to dispatch event: " + event); - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpUI.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpUI.java deleted file mode 100644 index 7736f87..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpUI.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.help; - -import java.awt.Component; - -/** - * Contract to be added on JAXXObject which wants to use javax help. - * - * @param <B> type of broker. - * @author Tony Chemit - chemit@codelutin.com - * @see JAXXHelpBroker - * @since 1.3 - */ -public interface JAXXHelpUI<B extends JAXXHelpBroker> { - - B getBroker(); - - void registerHelpId(B broker, Component component, String helpId); - - void showHelp(String helpId); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpUIHandler.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpUIHandler.java deleted file mode 100644 index 4316991..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpUIHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.help; - -import jaxx.runtime.JAXXContext; - -/** @author Tony Chemit - chemit@codelutin.com */ -public interface JAXXHelpUIHandler { - - void showHelp(JAXXContext context, JAXXHelpBroker broker, String helpID); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/AbstractGenericListSelectionModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/AbstractGenericListSelectionModel.java deleted file mode 100644 index d1dd614..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/AbstractGenericListSelectionModel.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.model; - -import com.google.common.collect.Lists; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.util.Collection; -import java.util.List; -import javax.swing.DefaultListSelectionModel; -import javax.swing.event.EventListenerList; - -/** - * @author Sylvain Lletellier - */ -public abstract class AbstractGenericListSelectionModel<B> extends DefaultListSelectionModel { - - public static final String PROPERTY_SELECTED_VALUE = "selectedValues"; - - protected EventListenerList listenerList = new EventListenerList(); - protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this); - - protected List<B> selectedValues; - - public AbstractGenericListSelectionModel() { - this.selectedValues = Lists.newArrayList(); - } - - public B getSelectedValue() { - return selectedValues.get(0); - } - - public List<B> getSelectedValues() { - return Lists.newArrayList(selectedValues); - } - - public void setSelectedValues(List<B> selectedValues) { - this.selectedValues = selectedValues; - } - - protected void unSelectItems(Collection<B> values) { - Collection<B> oldValue = Lists.newArrayList(selectedValues); - for (B value : values) { - int index = selectedValues.indexOf(value); - removeSelectionIntervalWithoutFire(index, index); - } - fireSelectionRemoved(values); - firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); - } - - protected void unSelectItem(B value) { - Collection<B> oldValue = Lists.newArrayList(selectedValues); - int index = selectedValues.indexOf(value); - removeSelectionIntervalWithoutFire(index, index); - - fireSelectionRemoved(Lists.newArrayList(value)); - firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); - } - - public void addSelectedItem(B toSelect) { - Collection<B> oldValue = Lists.newArrayList(selectedValues); - selectedValues.add(toSelect); - int index = selectedValues.indexOf(toSelect); - super.addSelectionInterval(index, index); - - fireSelectionAdded(Lists.newArrayList(toSelect)); - firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); - } - - public boolean hasSelectedIndex() { - return !selectedValues.isEmpty(); - } - - @Override - public void addSelectionInterval(int index0, int index1) { - Collection<B> oldValue = Lists.newArrayList(selectedValues); - - addSelectionIntervalWithFire(index0, index1); - super.addSelectionInterval(index0, index1); - - Collection<B> newValue = Lists.newArrayList(selectedValues); - newValue.removeAll(oldValue); - fireSelectionAdded(newValue); - firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); - } - - @Override - public void setSelectionInterval(int index0, int index1) { - Collection<B> oldValue = Lists.newArrayList(selectedValues); - selectedValues.clear(); - addSelectionIntervalWithFire(index0, index1); - super.setSelectionInterval(index0, index1); - - Collection<B> newValue = Lists.newArrayList(selectedValues); - newValue.removeAll(oldValue); - fireSelectionAdded(newValue); - firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); - } - - @Override - public void removeSelectionInterval(int index0, int index1) { - Collection<B> oldValue = Lists.newArrayList(selectedValues); - removeSelectionIntervalWithoutFire(index0, index1); - - Collection<B> newValue = Lists.newArrayList(selectedValues); - newValue.removeAll(oldValue); - fireSelectionRemoved(newValue); - firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); - } - - protected void removeSelectionIntervalWithoutFire(int index0, int index1) { - if (index0 > index1) { - int tmp = index1; - index1 = index0; - index0 = tmp; - } - for (int i=index0;i<=index1;i++) { - if (selectedValues.size() > i && i != -1) { - selectedValues.remove(i); - } - } - super.removeSelectionInterval(index0, index1); - } - - protected void addSelectionIntervalWithFire(int index0, int index1) { - if (index0 > index1) { - int tmp = index1; - index1 = index0; - index0 = tmp; - } - for (int i=index0;i<=index1;i++) { - - if (getSize() > i && i != -1) { - B value = getValueAt(i); - selectedValues.add(value); - } - } - } - - public abstract int getSize(); - - public abstract B getValueAt(int i); - - @Override - public void clearSelection() { - Collection<B> oldValue = Lists.newArrayList(selectedValues); - selectedValues.clear(); - super.clearSelection(); - - fireSelectionRemoved(oldValue); - firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); - } - - @Override - public int getSelectionMode() { - return MULTIPLE_INTERVAL_SELECTION; - } - - protected void fireValuesAdded(Collection<B> values) { - if (values.isEmpty()) { - return; - } - Object[] listeners = listenerList.getListenerList(); - GenericListEvent<B> e = null; - - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == GenericListListener.class) { - if (e == null) { - e = new GenericListEvent<B>(this, values); - } - ((GenericListListener)listeners[i+1]).valuesAdded(e); - } - } - } - - protected void fireValuesRemoved(Collection<B> values) { - if (values.isEmpty()) { - return; - } - Object[] listeners = listenerList.getListenerList(); - GenericListEvent<B> e = null; - - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == GenericListListener.class) { - if (e == null) { - e = new GenericListEvent<B>(this, values); - } - ((GenericListListener)listeners[i+1]).valuesRemoved(e); - } - } - } - - protected void fireSelectionAdded(Collection<B> selectedValues) { - if (selectedValues.isEmpty()) { - return; - } - Object[] listeners = listenerList.getListenerList(); - GenericListEvent<B> e = null; - - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == GenericListListener.class) { - if (e == null) { - e = new GenericListEvent<B>(this, selectedValues); - } - ((GenericListListener)listeners[i+1]).selectionAdded(e); - } - } - } - - protected void fireSelectionRemoved(Collection<B> selectedValues) { - if (selectedValues.isEmpty()) { - return; - } - Object[] listeners = listenerList.getListenerList(); - GenericListEvent<B> e = null; - - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == GenericListListener.class) { - if (e == null) { - e = new GenericListEvent<B>(this, selectedValues); - } - ((GenericListListener)listeners[i+1]).selectionAdded(e); - } - } - } - - public void addGenericListListener(GenericListListener l) { - listenerList.add(GenericListListener.class, l); - } - - public void removeGenericListListener(GenericListListener l) { - listenerList.remove(GenericListListener.class, l); - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - pcs.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { - pcs.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - pcs.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { - pcs.removePropertyChangeListener(propertyName, listener); - } - - protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { - pcs.firePropertyChange(propertyName, oldValue, newValue); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/AbstractSelectionListModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/AbstractSelectionListModel.java deleted file mode 100644 index ee9b0be..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/AbstractSelectionListModel.java +++ /dev/null @@ -1,32 +0,0 @@ -package jaxx.runtime.swing.model; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -/** - * Created on 8/7/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since XXX - */ -public class AbstractSelectionListModel { -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/ComboBoxModel2.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/ComboBoxModel2.java deleted file mode 100644 index 17887a9..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/ComboBoxModel2.java +++ /dev/null @@ -1,50 +0,0 @@ -package jaxx.runtime.swing.model; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import javax.swing.ComboBoxModel; - -/** - * A new comboBox model that add supports for {@link WillChangeSelectedItemListener}. - * - * Created on 8/7/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.10 - */ -public interface ComboBoxModel2 extends ComboBoxModel { - - /** - * Adds a listener to the list that's notified each time the selected item should be changed. - * - * @param l the <code>ListDataListener</code> to be added - */ - void addWillChangeSelectedItemListener(WillChangeSelectedItemListener l); - - /** - * Adds a listener to the list that's notified each time the selected item should be changed. - * - * @param l the <code>ListDataListener</code> to be removed - */ - void removeWillChangeSelectedItemListener(WillChangeSelectedItemListener l); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/ComboBoxSelectionEvent.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/ComboBoxSelectionEvent.java deleted file mode 100644 index 35852b2..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/ComboBoxSelectionEvent.java +++ /dev/null @@ -1,69 +0,0 @@ -package jaxx.runtime.swing.model; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import java.io.Serializable; -import java.util.EventObject; - -/** - * Created on 8/7/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.10 - */ -public class ComboBoxSelectionEvent extends EventObject { - - private static final long serialVersionUID = 1L; - - /** - * The current selected item in comboBox. - */ - protected final Serializable currentSelectedItem; - - /** - * The item to selected in comboBox. - */ - protected final Serializable nextSelectedItem; - - /** - * Constructs a ComboBoxSelectionEvent object. - * - * @param source the Object that originated the event - * (typically <code>this</code>) - * @param currentSelectedItem the current selected item in comboBox - * @param nextSelectedItem the item to selected in comboBox. - */ - public ComboBoxSelectionEvent(Object source, Serializable currentSelectedItem, Serializable nextSelectedItem) { - super(source); - this.currentSelectedItem = currentSelectedItem; - this.nextSelectedItem = nextSelectedItem; - } - - public Serializable getCurrentSelectedItem() { - return currentSelectedItem; - } - - public Serializable getNextSelectedItem() { - return nextSelectedItem; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListEvent.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListEvent.java deleted file mode 100644 index 85586f2..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListEvent.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.model; - -import java.util.Collection; -import java.util.EventObject; - -/** - * @author Sylvain Lletellier - */ -public class GenericListEvent<B> extends EventObject { - - protected Collection<B> values; - - public GenericListEvent(Object source, Collection<B> values) { - super(source); - this.values = values; - } - - public Collection<B> getValues() { - return values; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListListener.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListListener.java deleted file mode 100644 index d1f469d..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListListener.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.model; - -import java.util.EventListener; - -/** - * @author Sylvain Lletellier - */ -public interface GenericListListener extends EventListener { - - void valuesAdded(GenericListEvent event); - - void valuesRemoved(GenericListEvent event); - - void selectionAdded(GenericListEvent event); - - void selectionRemoved(GenericListEvent event); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListModel.java deleted file mode 100644 index b0514b3..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListModel.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.model; - -import com.google.common.collect.Lists; -import java.util.Collection; -import java.util.List; -import javax.swing.ComboBoxModel; -import javax.swing.DefaultListModel; -import javax.swing.event.ListDataEvent; -import javax.swing.event.ListDataListener; - -/** - * @author Sylvain Lletellier - */ -public class GenericListModel<B> extends GenericListSelectionModel<B> implements ComboBoxModel { - - public GenericListModel() { - super(new DefaultListModel()); - } - - public GenericListModel(Collection<B> values) { - this(); - setElements(values); - } - - public void setElements(Collection<B> values) { - Collection<B> oldValues = getElements(); - Collection<B> oldSelectedValues = getSelectedValues(); - clearSelection(); - fireSelectionRemoved(oldSelectedValues); - - clearElements(); - fireValuesRemoved(oldValues); - - for (B value : values) { - getListModel().addElement(value); - } - - fireSelectionAdded(values); - } - - public void clearElements() { - Collection<B> elements = getElements(); - getListModel().clear(); - - fireValuesRemoved(elements); - } - - public Collection<B> getElements() { - int size = getListModel().getSize(); - Collection<B> result = Lists.newArrayList(); - for (int i=0;i<size;i++) { - result.add((B) getListModel().get(i)); - } - return result; - } - - public void addElement(int index, B valueToAdd) { - getListModel().add(index, valueToAdd); - - fireValuesAdded(Lists.newArrayList(valueToAdd)); - } - - public void addElement(B valueToAdd) { - getListModel().addElement(valueToAdd); - - fireValuesAdded(Lists.newArrayList(valueToAdd)); - } - - public void addElements(Collection<B> valuesToAdd) { - for (B value : valuesToAdd) { - getListModel().addElement(value); - } - - fireValuesAdded(valuesToAdd); - } - - public void removeElements(Collection<B> values) { - for (B value : values) { - getListModel().removeElement(value); - } - unSelectItems(values); - - fireValuesRemoved(values); - } - - @Override - public void setSelectedItem(Object anItem) { - List<B> oldValue = getSelectedValues(); - fireSelectionRemoved(oldValue); - - setSelectedValues(Lists.newArrayList((B) anItem)); - - List<B> newValues = getSelectedValues(); - fireSelectionAdded(newValues); - fireContentsChanged(this, -1, -1); - firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, newValues); - } - - @Override - public B getSelectedItem() { - List<B> selectedValues = getSelectedValues(); - if (selectedValues.isEmpty()) { - return null; - } - return selectedValues.get(0); - } - - @Override - public int getSize() { - return getListModel().size(); - } - - @Override - public Object getElementAt(int index) { - return getListModel().get(index); - } - - @Override - public void addListDataListener(ListDataListener l) { - getListModel().addListDataListener(l); - } - - @Override - public void removeListDataListener(ListDataListener l) { - getListModel().removeListDataListener(l); - } - - protected void fireContentsChanged(Object source, int index0, int index1) { - Object[] listeners = getListModel().getListDataListeners(); - ListDataEvent e = null; - - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == ListDataListener.class) { - if (e == null) { - e = new ListDataEvent(source, ListDataEvent.CONTENTS_CHANGED, index0, index1); - } - ((ListDataListener)listeners[i+1]).contentsChanged(e); - } - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListSelectionModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListSelectionModel.java deleted file mode 100644 index 2e3e58e..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListSelectionModel.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.model; - -import javax.swing.DefaultListModel; - -/** - * @author Sylvain Lletellier - */ -public class GenericListSelectionModel<B> extends AbstractGenericListSelectionModel<B> { - - protected DefaultListModel listModel; - - public GenericListSelectionModel(DefaultListModel listModel) { - super(); - this.listModel = listModel; - } - - public DefaultListModel getListModel() { - return listModel; - } - - @Override - public int getSize() { - return listModel.size(); - } - - @Override - public B getValueAt(int i) { - return (B)listModel.getElementAt(i); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxDefaultComboBoxModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxDefaultComboBoxModel.java deleted file mode 100644 index f56bda5..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxDefaultComboBoxModel.java +++ /dev/null @@ -1,219 +0,0 @@ -package jaxx.runtime.swing.model; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.collections4.CollectionUtils; - -import javax.swing.AbstractListModel; -import javax.swing.DefaultComboBoxModel; -import javax.swing.MutableComboBoxModel; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Vector; - -/** - * To replace the {@link DefaultComboBoxModel} which used {@link Vector}. - * - * Add some new methods to {@link #addAllElements(Collection)} or - * {@link #setAllElements(Collection)}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.10 - */ -public class JaxxDefaultComboBoxModel<E> extends AbstractListModel implements MutableComboBoxModel, Serializable, ComboBoxModel2 { - - private static final long serialVersionUID = 1L; - - protected List<E> delegate; - - protected E selectedObject; - - public JaxxDefaultComboBoxModel() { - delegate = new ArrayList<E>(); - } - - public JaxxDefaultComboBoxModel(E... items) { - delegate = new ArrayList<E>(items.length); - - int i, c; - for (i = 0, c = items.length; i < c; i++) - delegate.add(items[i]); - - if (getSize() > 0) { - selectedObject = getElementAt(0); - } - } - - public JaxxDefaultComboBoxModel(Collection<E> v) { - delegate = new ArrayList<E>(v); - - if (getSize() > 0) { - selectedObject = getElementAt(0); - } - } - - @Override - public void setSelectedItem(Object anObject) { - if ((selectedObject != null && !selectedObject.equals(anObject)) || - selectedObject == null && anObject != null) { - - try { - fireSelectedItemWillChanged(selectedObject, anObject); - } catch (WillChangeSelectedItemVetoException e) { - // was not allowed to change selected item - return; - } - selectedObject = (E) anObject; - fireContentsChanged(this, -1, -1); - } - } - - public int getIndexOf(E anObject) { - return delegate.indexOf(anObject); - } - - - public void setAllElements(Collection<E> objects) { - removeAllElements(); - addAllElements(objects); - } - - public void addAllElements(Collection<E> objects) { - if (CollectionUtils.isNotEmpty(objects)) { - int firstIndex = delegate.size(); - this.delegate.addAll(objects); - int lastIndex = delegate.size() - 1; - if (lastIndex > -1) { - fireIntervalAdded(this, firstIndex, lastIndex); - } - } - } - - /** Empties the list. */ - public void removeAllElements() { - if (delegate.size() > 0) { - int firstIndex = 0; - int lastIndex = delegate.size() - 1; - delegate.clear(); - selectedObject = null; - fireIntervalRemoved(this, firstIndex, lastIndex); - } else { - selectedObject = null; - } - } - - @Override - public E getSelectedItem() { - return selectedObject; - } - - @Override - public int getSize() { - return delegate.size(); - } - - @Override - public E getElementAt(int index) { - E result; - - if (index >= 0 && index < delegate.size()) { - result = delegate.get(index); - } else { - result = null; - } - return result; - } - - @Override - public void addElement(Object anObject) { - delegate.add((E) anObject); - fireIntervalAdded(this, delegate.size() - 1, delegate.size() - 1); - if (delegate.size() == 1 && selectedObject == null && anObject != null) { - setSelectedItem(anObject); - } - } - - @Override - public void insertElementAt(Object anObject, int index) { - delegate.add(index, (E) anObject); - fireIntervalAdded(this, index, index); - } - - @Override - public void removeElementAt(int index) { - if (getElementAt(index) == selectedObject) { - if (index == 0) { - setSelectedItem(getSize() == 1 ? null : getElementAt(index + 1)); - } else { - setSelectedItem(getElementAt(index - 1)); - } - } - - delegate.remove(index); - - fireIntervalRemoved(this, index, index); - } - - @Override - public void removeElement(Object anObject) { - int index = delegate.indexOf(anObject); - if (index != -1) { - removeElementAt(index); - } - } - - @Override - public void addWillChangeSelectedItemListener(WillChangeSelectedItemListener l) { - listenerList.add(WillChangeSelectedItemListener.class, l); - } - - @Override - public void removeWillChangeSelectedItemListener(WillChangeSelectedItemListener l) { - listenerList.remove(WillChangeSelectedItemListener.class, l); - } - - /** - * Notifies all listeners that have registered interest for - * notification on this event type. The event instance - * is lazily created using the <code>currentSelectedItem</code> and <code>newSelectedItem</code> parameter. - */ - public void fireSelectedItemWillChanged(Object currentSelectedItem, - Object newSelectedItem) throws WillChangeSelectedItemVetoException { - // Guaranteed to return a non-null array - Object[] listeners = listenerList.getListenerList(); - ComboBoxSelectionEvent e = null; - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == WillChangeSelectedItemListener.class) { - // Lazily create the event: - if (e == null) - e = new ComboBoxSelectionEvent(this, (Serializable)currentSelectedItem, (Serializable) newSelectedItem); - ((WillChangeSelectedItemListener) listeners[i + 1]). - selectedItemWillChanged(e); - } - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxDefaultListModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxDefaultListModel.java deleted file mode 100644 index 51dd52f..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxDefaultListModel.java +++ /dev/null @@ -1,618 +0,0 @@ -package jaxx.runtime.swing.model; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.collect.Lists; -import org.apache.commons.collections4.CollectionUtils; - -import javax.swing.AbstractListModel; -import javax.swing.DefaultListModel; -import java.util.ArrayList; -import java.util.Collection; -import java.util.NoSuchElementException; -import java.util.Vector; - -/** - * To replace the {@link DefaultListModel} which used {@link Vector}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.10 - */ -public class JaxxDefaultListModel<E> extends AbstractListModel { - - private static final long serialVersionUID = 1L; - - protected ArrayList<E> delegate = new ArrayList<E>(); - - protected boolean valueIsAdjusting; - - public boolean isValueIsAdjusting() { - return valueIsAdjusting; - } - - public void setValueIsAdjusting(boolean valueIsAdjusting) { - this.valueIsAdjusting = valueIsAdjusting; - } - - public ArrayList<E> toList() { - return Lists.newArrayList(delegate); - } - - /** - * Returns the number of components in this list. - * - * This method is identical to <code>size</code>, which implements the - * <code>List</code> interface defined in the 1.2 Collections framework. - * This method exists in conjunction with <code>setSize</code> so that - * <code>size</code> is identifiable as a JavaBean property. - * - * @return the number of components in this list - * @see #size() - */ - @Override - public int getSize() { - return delegate.size(); - } - - /** - * Returns the component at the specified index. - * <blockquote> - * <b>Note:</b> Although this method is not deprecated, the preferred - * method to use is <code>get(int)</code>, which implements the - * <code>List</code> interface defined in the 1.2 Collections framework. - * </blockquote> - * - * @param index an index into this list - * @return the component at the specified index - * @throws ArrayIndexOutOfBoundsException if the <code>index</code> - * is negative or greater than the current size of this - * list - * @see #get(int) - */ - @Override - public E getElementAt(int index) { - return delegate.get(index); - } - -// /** -// * Copies the components of this list into the specified array. -// * The array must be big enough to hold all the objects in this list, -// * else an <code>IndexOutOfBoundsException</code> is thrown. -// * -// * @param anArray the array into which the components get copied -// * @see Vector#copyInto(Object[]) -// */ -// public void copyInto(Object anArray[]) { -// delegate.copyInto(anArray); -// } - - /** - * Trims the capacity of this list to be the list's current size. - * - * @see Vector#trimToSize() - */ - public void trimToSize() { - delegate.trimToSize(); - } - - /** - * Increases the capacity of this list, if necessary, to ensure - * that it can hold at least the number of components specified by - * the minimum capacity argument. - * - * @param minCapacity the desired minimum capacity - * @see Vector#ensureCapacity(int) - */ - public void ensureCapacity(int minCapacity) { - delegate.ensureCapacity(minCapacity); - } - - /** - * Sets the size of this list. - * - * @param newSize the new size of this list - * @see Vector#setSize(int) - */ - public void setSize(int newSize) { - int oldSize = delegate.size(); - delegate.ensureCapacity(newSize); - if (oldSize > newSize) { - fireIntervalRemoved(this, newSize, oldSize - 1); - } else if (oldSize < newSize) { - fireIntervalAdded(this, oldSize, newSize - 1); - } - } - - /** - * Returns the current capacity of this list. - * - * @return the current capacity - * @see Vector#capacity() - */ - public int capacity() { - return delegate.size(); - } - - /** - * Returns the number of components in this list. - * - * @return the number of components in this list - * @see Vector#size() - */ - public int size() { - return delegate.size(); - } - - /** - * Tests whether this list has any components. - * - * @return <code>true</code> if and only if this list has - * no components, that is, its size is zero; - * <code>false</code> otherwise - * @see Vector#isEmpty() - */ - public boolean isEmpty() { - return delegate.isEmpty(); - } - -// /** -// * Returns an enumeration of the components of this list. -// * -// * @return an enumeration of the components of this list -// * @see Vector#elements() -// */ -// public Enumeration<E> elements() { -// return delegate.iterator().elements(); -// } - - /** - * Tests whether the specified object is a component in this list. - * - * @param elem an object - * @return <code>true</code> if the specified object - * is the same as a component in this list - * @see Vector#contains(Object) - */ - public boolean contains(E elem) { - return delegate.contains(elem); - } - - /** - * Searches for the first occurrence of <code>elem</code>. - * - * @param elem an object - * @return the index of the first occurrence of the argument in this - * list; returns <code>-1</code> if the object is not found - * @see Vector#indexOf(Object) - */ - public int indexOf(E elem) { - return delegate.indexOf(elem); - } - - /** - * Searches for the first occurrence of <code>elem</code>, beginning - * the search at <code>index</code>. - * - * @param elem an desired component - * @param index the index from which to begin searching - * @return the index where the first occurrence of <code>elem</code> - * is found after <code>index</code>; returns <code>-1</code> - * if the <code>elem</code> is not found in the list - * @see Vector#indexOf(Object, int) - */ - public int indexOf(E elem, int index) { - return delegate.indexOf(elem); - } - - /** - * Returns the index of the last occurrence of <code>elem</code>. - * - * @param elem the desired component - * @return the index of the last occurrence of <code>elem</code> - * in the list; returns <code>-1</code> if the object is not found - * @see Vector#lastIndexOf(Object) - */ - public int lastIndexOf(E elem) { - return delegate.lastIndexOf(elem); - } - - /** - * Searches backwards for <code>elem</code>, starting from the - * specified index, and returns an index to it. - * - * @param elem the desired component - * @param index the index to start searching from - * @return the index of the last occurrence of the <code>elem</code> - * in this list at position less than <code>index</code>; - * returns <code>-1</code> if the object is not found - * @see Vector#lastIndexOf(Object, int) - */ - public int lastIndexOf(E elem, int index) { - return delegate.lastIndexOf(elem); - } - - /** - * Returns the component at the specified index. - * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index - * is negative or not less than the size of the list. - * <blockquote> - * <b>Note:</b> Although this method is not deprecated, the preferred - * method to use is <code>get(int)</code>, which implements the - * <code>List</code> interface defined in the 1.2 Collections framework. - * </blockquote> - * - * @param index an index into this list - * @return the component at the specified index - * @see #get(int) - * @see Vector#elementAt(int) - */ - public E elementAt(int index) { - return delegate.get(index); - } - - /** - * Returns the first component of this list. - * Throws a <code>NoSuchElementException</code> if this - * vector has no components. - * - * @return the first component of this list - * @see Vector#firstElement() - */ - public E firstElement() { - if (isEmpty()) { - throw new NoSuchElementException(); - } - return delegate.get(0); - } - - /** - * Returns the last component of the list. - * Throws a <code>NoSuchElementException</code> if this vector - * has no components. - * - * @return the last component of the list - * @see Vector#lastElement() - */ - public E lastElement() { - if (isEmpty()) { - throw new NoSuchElementException(); - } - return delegate.get(delegate.size() - 1); - } - - /** - * Sets the component at the specified <code>index</code> of this - * list to be the specified element. The previous component at that - * position is discarded. - * - * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index - * is invalid. - * <blockquote> - * <b>Note:</b> Although this method is not deprecated, the preferred - * method to use is <code>set(int,Object)</code>, which implements the - * <code>List</code> interface defined in the 1.2 Collections framework. - * </blockquote> - * - * @param element what the component is to be set to - * @param index the specified index - * @see #set(int, Object) - * @see Vector#setElementAt(Object, int) - */ - public void setElementAt(E element, int index) { - delegate.set(index, element); - if (!isValueIsAdjusting()) { - fireContentsChanged(this, index, index); - } - } - - /** - * Deletes the component at the specified index. - * - * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index - * is invalid. - * <blockquote> - * <b>Note:</b> Although this method is not deprecated, the preferred - * method to use is <code>remove(int)</code>, which implements the - * <code>List</code> interface defined in the 1.2 Collections framework. - * </blockquote> - * - * @param index the index of the object to remove - * @see #remove(int) - * @see Vector#removeElementAt(int) - */ - public void removeElementAt(int index) { - delegate.remove(index); - if (!isValueIsAdjusting()) { - fireIntervalRemoved(this, index, index); - } - } - - /** - * Inserts the specified element as a component in this list at the - * specified <code>index</code>. - * - * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index - * is invalid. - * <blockquote> - * <b>Note:</b> Although this method is not deprecated, the preferred - * method to use is <code>add(int,Object)</code>, which implements the - * <code>List</code> interface defined in the 1.2 Collections framework. - * </blockquote> - * - * @param element the component to insert - * @param index where to insert the new component - * @throws ArrayIndexOutOfBoundsException if the index was invalid - * @see #add(int, Object) - * @see Vector#insertElementAt(Object, int) - */ - public void insertElementAt(E element, int index) { - delegate.add(index, element); - if (!isValueIsAdjusting()) { - fireIntervalAdded(this, index, index); - } - } - - /** - * Adds the specified component to the end of this list. - * - * @param element the component to be added - * @see Vector#addElement(Object) - */ - public void addElement(E element) { - int index = delegate.size(); - delegate.add(element); - if (!isValueIsAdjusting()) { - fireIntervalAdded(this, index, index); - } - } - - /** - * Removes the first (lowest-indexed) occurrence of the argument - * from this list. - * - * @param obj the component to be removed - * @return <code>true</code> if the argument was a component of this - * list; <code>false</code> otherwise - * @see Vector#removeElement(Object) - */ - public boolean removeElement(E obj) { - int index = indexOf(obj); - boolean rv = delegate.remove(obj); - if (index >= 0) { - if (!isValueIsAdjusting()) { - fireIntervalRemoved(this, index, index); - } - } - return rv; - } - - - /** - * Removes all components from this list and sets its size to zero. - * <blockquote> - * <b>Note:</b> Although this method is not deprecated, the preferred - * method to use is <code>clear</code>, which implements the - * <code>List</code> interface defined in the 1.2 Collections framework. - * </blockquote> - * - * @see #clear() - * @see Vector#removeAllElements() - */ - public void removeAllElements() { - int index1 = delegate.size() - 1; - delegate.clear(); - if (index1 >= 0) { - if (!isValueIsAdjusting()) { - fireIntervalRemoved(this, 0, index1); - } - } - } - - @Override - public String toString() { - return delegate.toString(); - } - - - /* The remaining methods are included for compatibility with the - * Java 2 platform Vector class. - */ - - /** - * Returns an array containing all of the elements in this list in the - * correct order. - * - * @return an array containing the elements of the list - * @see Vector#toArray() - */ - public Object[] toArray() { - return delegate.toArray(); - } - - /** - * Returns the element at the specified position in this list. - * - * Throws an <code>ArrayIndexOutOfBoundsException</code> - * if the index is out of range - * (<code>index < 0 || index >= size()</code>). - * - * @param index index of element to return - */ - public E get(int index) { - return delegate.get(index); - } - - /** - * Replaces the element at the specified position in this list with the - * specified element. - * - * Throws an <code>ArrayIndexOutOfBoundsException</code> - * if the index is out of range - * (<code>index < 0 || index >= size()</code>). - * - * @param index index of element to replace - * @param element element to be stored at the specified position - * @return the element previously at the specified position - */ - public E set(int index, E element) { - E rv = delegate.set(index, element); - if (!isValueIsAdjusting()) { - fireContentsChanged(this, index, index); - } - return rv; - } - - /** - * Inserts the specified element at the specified position in this list. - * - * Throws an <code>ArrayIndexOutOfBoundsException</code> if the - * index is out of range - * (<code>index < 0 || index > size()</code>). - * - * @param index index at which the specified element is to be inserted - * @param element element to be inserted - */ - public void add(int index, E element) { - delegate.add(index, element); - if (!isValueIsAdjusting()) { - fireIntervalAdded(this, index, index); - } - } - - public void setAllElements(Collection<E> objects) { - removeAllElements(); - addAllElements(objects); - } - - public void addAllElements(Collection<E> elements) { - if (CollectionUtils.isNotEmpty(elements)) { - - int firstIndex = delegate.size(); - this.delegate.addAll(elements); - int lastIndex = delegate.size() - 1; - if (lastIndex > -1) { - if (!isValueIsAdjusting()) { - fireIntervalAdded(this, firstIndex, lastIndex); - } - } - } - } - - public void removeAllElements(Collection<E> elements) { - if (CollectionUtils.isNotEmpty(elements)) { - - int firstIndex = 0; - int lastIndex = delegate.size(); - this.delegate.removeAll(elements); - if (lastIndex > -1) { - if (!isValueIsAdjusting()) { - fireContentsChanged(this, firstIndex, lastIndex); - } - } - } - } - - /** - * Removes the element at the specified position in this list. - * Returns the element that was removed from the list. - * - * Throws an <code>ArrayIndexOutOfBoundsException</code> - * if the index is out of range - * (<code>index < 0 || index >= size()</code>). - * - * @param index the index of the element to removed - * @return the element previously at the specified position - */ - public E remove(int index) { - E rv = delegate.remove(index); - if (!isValueIsAdjusting()) { - fireIntervalRemoved(this, index, index); - } - return rv; - } - - /** - * Removes all of the elements from this list. The list will - * be empty after this call returns (unless it throws an exception). - */ - public void clear() { - int index1 = delegate.size() - 1; - delegate.clear(); - if (index1 >= 0) { - if (!isValueIsAdjusting()) { - fireIntervalRemoved(this, 0, index1); - } - } - } - - /** - * Deletes the components at the specified range of indexes. - * The removal is inclusive, so specifying a range of (1,5) - * removes the component at index 1 and the component at index 5, - * as well as all components in between. - * - * Throws an <code>ArrayIndexOutOfBoundsException</code> - * if the index was invalid. - * Throws an <code>IllegalArgumentException</code> if - * <code>fromIndex > toIndex</code>. - * - * @param fromIndex the index of the lower end of the range - * @param toIndex the index of the upper end of the range - * @see #remove(int) - */ - public void removeRange(int fromIndex, int toIndex) { - if (fromIndex > toIndex) { - throw new IllegalArgumentException("fromIndex must be <= toIndex"); - } - for (int i = toIndex; i >= fromIndex; i--) { - delegate.remove(i); - } - if (!isValueIsAdjusting()) { - fireIntervalRemoved(this, fromIndex, toIndex); - } - } - - public void refresh() { - if (!isEmpty()) { - - if (!isValueIsAdjusting()) { - fireContentsChanged(this, 0, getSize() - 1); - } - } - } - - public void refresh(int size) { - - if (!isValueIsAdjusting()) { - fireContentsChanged(this, 0, size); - } - - } - - /* - public void addAll(Collection c) { - } - - public void addAll(int index, Collection c) { - }*/ -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxFilterableComboBoxModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxFilterableComboBoxModel.java deleted file mode 100644 index fffc405..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxFilterableComboBoxModel.java +++ /dev/null @@ -1,235 +0,0 @@ -package jaxx.runtime.swing.model; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Predicate; -import com.google.common.collect.Lists; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.decorator.JXPathDecorator; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.regex.Pattern; - -/** - * ComboBoxModel which can filter the elements displayed in the popup. - * - * @author Kevin Morin - morin@codelutin.com - * @since 2.5.12 - */ -public class JaxxFilterableComboBoxModel<E> extends JaxxDefaultComboBoxModel<E> { - - private static final long serialVersionUID = 1L; - - /** Logger. */ - private static final Log log = LogFactory.getLog(JaxxFilterableComboBoxModel.class); - - public static final Character DEFAULT_WILDCARD_CHARACTER = '*'; - - protected List<E> filteredItems = Lists.newArrayList(); - - protected String filterText; - - protected Character wildcardCharacter = DEFAULT_WILDCARD_CHARACTER; - - /** the decorator of data */ - protected JXPathDecorator<E> decorator; - - protected List<Predicate<E>> filters = Lists.newArrayList(); - - public JaxxFilterableComboBoxModel() { - super(); - } - - public JaxxFilterableComboBoxModel(E... items) { - delegate = new ArrayList<E>(items.length); - - int i, c; - for (i = 0, c = items.length; i < c; i++) - delegate.add(items[i]); - - } - - public JaxxFilterableComboBoxModel(Collection<E> v) { - delegate = new ArrayList<E>(v); - } - - @Override - public int getIndexOf(E anObject) { - return filteredItems.indexOf(anObject); - } - - @Override - public void addAllElements(Collection<E> objects) { - super.addAllElements(objects); - refilter(); - } - - /** Empties the list. */ - @Override - public void removeAllElements() { - super.removeAllElements(); - refilter(); - } - - @Override - public int getSize() { - return filteredItems.size(); - } - - @Override - public E getElementAt(int index) { - E result; - - synchronized (this) { - if (index >= 0 && index < filteredItems.size()) { - result = filteredItems.get(index); - } else { - result = null; - } - } - - return result; - } - - @Override - public void addElement(Object anObject) { - super.addElement(anObject); - refilter(); - } - - @Override - public void insertElementAt(Object anObject, int index) { - super.insertElementAt(anObject, index); - refilter(); - } - - @Override - public void removeElementAt(int index) { - super.removeElementAt(index); - refilter(); - } - - @Override - public void removeElement(Object anObject) { - super.removeElement(anObject); - refilter(); - } - - public String getFilterText() { - return filterText; - } - - public void setFilterText(String filterText) { - this.filterText = filterText; - refilter(); - } - - public Character getWildcardCharacter() { - return wildcardCharacter; - } - - public void setWildcardCharacter(Character wildcardCharacter) { - this.wildcardCharacter = wildcardCharacter; - refilter(); - - } - - public JXPathDecorator<E> getDecorator() { - return decorator; - } - - public void setDecorator(JXPathDecorator<E> decorator) { - this.decorator = decorator; - } - - public void addFilter(Predicate<E> filter) { - filters.add(filter); - refilter(); - } - - public void removeFilter(Predicate<E> filter) { - filters.remove(filter); - refilter(); - } - - public void clearFilters() { - filters.clear(); - refilter(); - } - - public void refreshFilteredElements() { - refilter(); - } - - protected void refilter() { - filteredItems.clear(); - - if ((StringUtils.isEmpty(filterText) - || wildcardCharacter != null && StringUtils.isEmpty(StringUtils.remove(filterText, wildcardCharacter))) - && filters.isEmpty()) { - filteredItems.addAll(delegate); - - } else { - Pattern pattern = null; - if (!StringUtils.isBlank(filterText)) { - String patternText= Pattern.quote(filterText); - - if (wildcardCharacter == null) { - patternText = ".*" + patternText; - - } else { - patternText = patternText.replace(wildcardCharacter.toString(), "\\E.*\\Q"); - } - pattern = Pattern.compile(patternText + ".*", Pattern.CASE_INSENSITIVE); - } - - for (E element : delegate) { - boolean addElement = true; - for (Predicate<E> filter : filters) { - addElement &= filter.apply(element); - } - String decoratedElement; - if (decorator != null) { - decoratedElement = decorator.toString(element); - } else { - decoratedElement = String.valueOf(element); - } - boolean matches = pattern == null - || pattern.matcher(decoratedElement).matches(); - if (matches && addElement) { - filteredItems.add(element); - } - } - } - - if (log.isInfoEnabled()) { - log.info("After refilter, nb items: " + getSize()); - } - - fireContentsChanged(this, 0, getSize()); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxFilterableListModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxFilterableListModel.java deleted file mode 100644 index a81989d..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/JaxxFilterableListModel.java +++ /dev/null @@ -1,259 +0,0 @@ -package jaxx.runtime.swing.model; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Predicate; -import com.google.common.collect.Lists; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.regex.Pattern; -import org.apache.commons.lang3.StringUtils; -import org.nuiton.decorator.JXPathDecorator; - -/** - * List model for filterable lists. - * - * @author Kevin Morin - morin@codelutin.com - * @since 2.5.11 - */ -public class JaxxFilterableListModel<E> extends JaxxDefaultListModel<E> { - - private static final long serialVersionUID = 1L; - - protected ArrayList<E> filteredItems = Lists.newArrayList(); - - protected String filterText; - - /** the decorator of data */ - protected JXPathDecorator<E> decorator; - - protected List<Predicate<E>> filters = Lists.newArrayList(); - - @Override - public E getElementAt(int index) { - E result; - - synchronized (this) { - if (index >= 0 && index < filteredItems.size()) { - result = filteredItems.get(index); - } else { - result = null; - } - } - return result; - } - - @Override - public E elementAt(int index) { - return getElementAt(index); - } - - @Override - public void addElement(E o) { - super.addElement(o); - refilter(); - } - - @Override - public boolean removeElement(E o) { - boolean result = super.removeElement(o); - refilter(); - return result; - } - - @Override - public int getSize() { - return filteredItems.size(); - } - - @Override - public int size() { - return filteredItems.size(); - } - - @Override - public void trimToSize() { - super.trimToSize(); - filteredItems.trimToSize(); - } - - @Override - public void ensureCapacity(int minCapacity) { - super.ensureCapacity(minCapacity); - filteredItems.ensureCapacity(minCapacity); - } - - @Override - public void setSize(int newSize) { - super.setSize(newSize); - filteredItems.ensureCapacity(newSize); - } - - @Override - public void setElementAt(E element, int index) { - super.setElementAt(element, index); - refilter(); - } - - @Override - public void removeElementAt(int index) { - super.removeElementAt(index); - refilter(); - } - - @Override - public void insertElementAt(E element, int index) { - super.insertElementAt(element, index); - refilter(); - } - - @Override - public void removeAllElements() { - super.removeAllElements(); - refilter(); - } - - @Override - public E set(int index, E element) { - E rv = super.set(index, element); - refilter(); - return rv; - } - - @Override - public void add(int index, E element) { - super.add(index, element); - refilter(); - } - - @Override - public void setAllElements(Collection<E> objects) { - super.setAllElements(objects); - refilter(); - } - - @Override - public void addAllElements(Collection<E> elements) { - super.addAllElements(elements); - refilter(); - } - - @Override - public void removeAllElements(Collection<E> elements) { - super.removeAllElements(elements); - refilter(); - } - - @Override - public E remove(int index) { - E rv = super.remove(index); - refilter(); - return rv; - } - - @Override - public void clear() { - super.clear(); - refilter(); - } - - @Override - public void removeRange(int fromIndex, int toIndex) { - super.removeRange(fromIndex, toIndex); - refilter(); - } - - public String getFilterText() { - return filterText; - } - - public void setFilterText(String filterText) { - this.filterText = filterText; - refilter(); - } - - public JXPathDecorator<E> getDecorator() { - return decorator; - } - - public void setDecorator(JXPathDecorator<E> decorator) { - this.decorator = decorator; - } - - public void addFilter(Predicate<E> filter) { - filters.add(filter); - refilter(); - } - - public void removeFilter(Predicate<E> filter) { - filters.remove(filter); - refilter(); - } - - public void clearFilters() { - filters.clear(); - refilter(); - } - - public void refreshFilteredElements() { - refilter(); - } - - protected void refilter() { - filteredItems.clear(); - - if (StringUtils.isEmpty(StringUtils.remove(filterText, '*')) - && filters.isEmpty()) { - filteredItems.addAll(delegate); - - } else { - int itemNumber = delegate.size(); - Pattern pattern = null; - if (!StringUtils.isBlank(filterText)) { - String patternText = Pattern.quote(filterText).replace("*", "\\E.*\\Q") + ".*"; - pattern = Pattern.compile(patternText, Pattern.CASE_INSENSITIVE); - } - for (int i = 0 ; i < itemNumber ; i++) { - E element = delegate.get(i); - boolean addElement = true; - for (Predicate<E> filter : filters) { - addElement &= filter.apply(element); - } - String decoratedElement; - if (decorator != null) { - decoratedElement = decorator.toString(element); - } else { - decoratedElement = String.valueOf(element); - } - boolean matches = pattern == null - || pattern.matcher(decoratedElement).matches(); - if (matches && addElement) { - filteredItems.add(element); - } - } - } - - fireContentsChanged(this, 0, getSize()); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/WillChangeSelectedItemListener.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/WillChangeSelectedItemListener.java deleted file mode 100644 index 05c26f0..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/WillChangeSelectedItemListener.java +++ /dev/null @@ -1,41 +0,0 @@ -package jaxx.runtime.swing.model; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import java.util.EventListener; - -/** - * A listener to be able to stop the change of a selected item in a - * Created on 8/7/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.10 - */ -public interface WillChangeSelectedItemListener extends EventListener { - - /** - * Invoked whenever the selected item is about to change in the comboBox. - */ - void selectedItemWillChanged(ComboBoxSelectionEvent event) throws WillChangeSelectedItemVetoException; - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/WillChangeSelectedItemVetoException.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/WillChangeSelectedItemVetoException.java deleted file mode 100644 index 053a119..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/WillChangeSelectedItemVetoException.java +++ /dev/null @@ -1,58 +0,0 @@ -package jaxx.runtime.swing.model; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -/** - * Created on 8/7/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.10 - */ -public class WillChangeSelectedItemVetoException extends Exception { - - private static final long serialVersionUID = 1L; - - /** The event that the exception was created for. */ - protected ComboBoxSelectionEvent event; - - /** - * Constructs an ExpandVetoException object with no message. - * - * @param event a ComboBoxSelectionEvent object - */ - - public WillChangeSelectedItemVetoException(ComboBoxSelectionEvent event) { - this(event, null); - } - - /** - * Constructs an ExpandVetoException object with the specified message. - * - * @param event a ComboBoxSelectionEvent object - * @param message a String containing the message - */ - public WillChangeSelectedItemVetoException(ComboBoxSelectionEvent event, String message) { - super(message); - this.event = event; - } -} \ No newline at end of file diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavBridge.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavBridge.java deleted file mode 100644 index ca5e679..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavBridge.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav; - -import javax.swing.event.TreeModelListener; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; -import java.util.EventListener; - -/** - * Contract of the bridge used by {@link NavHelper} to hold model and ui. - * - * @param <M> Type of model to bridge - * @param <N> Type of nodes of the model - * @author Tony Chemit - chemit@codelutin.com - * @since 2.1 - */ -public interface NavBridge<M, N extends NavNode<M, N>> { - - //-------------------------------------------------------------------------- - //-- Model Queries - //-------------------------------------------------------------------------- - - M getModel(); - - N getRoot(); - - boolean isLeaf(Object node); - - int getChildCount(Object parent); - - N getChild(Object parent, int index); - - int getIndexOfChild(Object parent, Object child); - - TreeNode[] getPathToRoot(TreeNode aNode); - - //-------------------------------------------------------------------------- - //-- Model modification - //-------------------------------------------------------------------------- - - void setModel(M delegate); - - void setRoot(N node); - - void insertNodeInto(N newChild, N parent, int index); - - void removeNodeFromParent(N node); - - void reload(N node); - - boolean canLoadChild(N node); - - //-------------------------------------------------------------------------- - //-- Listeners notifications - //-------------------------------------------------------------------------- - - void valueForPathChanged(TreePath path, Object newValue); - - void nodeStructureChanged(TreeNode node); - - void nodeChanged(TreeNode node); - - void nodesChanged(TreeNode node, int[] childIndices); - - void nodesWereInserted(N parent, int[] indices); - - void nodeWereInserted(N parentNode, int childIndice, N node); - - void nodesWereRemoved(TreeNode node, int[] childIndices, Object[] removedChildren); - - /** - * Notifies that the {@code node} was inserted. - * - * <b>Note:</b> The method recurses on childs (always notify parent before child) - * - * @param node node inserted - */ - void notifyNodeInserted(N node); - - /** - * Notifies that all childs nodes of {@code node} were - * inserted. - * - * <b>Note:</b> The method recurses on childs (always notify parent before child) - * - * @param node node where all childs where inserted - */ - void notifyChildNodesInserted(N node); - - //-------------------------------------------------------------------------- - //-- TreeModelListener provider - //-------------------------------------------------------------------------- - - void addTreeModelListener(TreeModelListener l); - - void removeTreeModelListener(TreeModelListener l); - - TreeModelListener[] getTreeModelListeners(); - - <T extends EventListener> T[] getListeners(Class<T> listenerType); - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavDataProvider.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavDataProvider.java deleted file mode 100644 index 47f192f..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavDataProvider.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav; - -import jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; - -/** - * Contract of provider of data. - * - * This object is used by {@link NavNodeChildLoador} to populate childs of node - * and by {@link AbstractNavTreeCellRenderer} to render nodes. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.1 - */ -public interface NavDataProvider { - - /** - * @return {@code true} is provider is enabled and can provide datas, - * {@code false} otherwise. - */ - boolean isEnabled(); - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavHelper.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavHelper.java deleted file mode 100644 index 1c9710d..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavHelper.java +++ /dev/null @@ -1,960 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav; - -import jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.event.TreeExpansionEvent; -import javax.swing.event.TreeModelEvent; -import javax.swing.event.TreeModelListener; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.event.TreeWillExpandListener; -import javax.swing.tree.TreePath; -import javax.swing.tree.TreeSelectionModel; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * Tree helper to deal with the build of trees and other usefull operations. - * - * A helper acts as an handler for a {@code tree}. It owns the {@link #getModel()} of - * the {@code #tree}. - * - * <b>Note:</b> A helper can NOT be used to manage multi-trees. - * <h2>Internal states</h2> - * <h3>Internal model</h3> - * To create the model, use method {@link #createModel(NavNode, Object...)} given a - * root node. - * - * To obtain the model, use method {@link #getModel()}. - * - * <b>Note:</b> The helper internal model can be different from the tree model, - * but must be the <b>lowest</b> model, other models must listen nicely this - * model to obtain model modification and selection notifications. - * <h3>Internal tree</h3> - * As said before, a helper matches exactly one tree. - * - * To register the tree, use method {@link #setUI(Object, boolean, TreeSelectionListener)}. - * - * To obtain the tree, use method {@link #getUI()}. - * <h3>Internal data provider</h3> - * To populate childs nodes and render nodes, we use a {@link NavDataProvider}. - * - * To register the data provider, use method {@link #setDataProvider(NavDataProvider)}. - * - * To obtain the data provider, use method {@link #getDataProvider()}. - * <h2>Internal listeners</h2> - * Several listeners are used to manage the auto-loading of nodes in model : - * <h3>{@link #expandListener}</h3> - * This listener will load node's childs before node expands if the node is not loaded. - * - * See the {@link NavNode#isLoaded()} method. - * <h3>{@link #treeModelListener}</h3> - * To listen modification of the model, it will mainly repopulate nodes when - * required. - * - * See the method {@link #populateNode(NavNode, Object[], boolean)}. - * <h3>{@link #selectionListener}</h3> - * To listen modification of the selection, it will mainly expand paths if required. - * - * This is a requirement, since childs of a node should NOT be loaded, so when - * selects a node, always check the path from root to selected node are all fully - * loaded. - * <h2>Model methods</h2> - * The helper offers some methods to modify and query the internal tree model. - * <h3>Model modification</h3> - * <ul> - * <li>{@link #createModel(NavNode, Object...)}</li> - * <li>{@link #insertNode(NavNode, NavNode)}</li> - * <li>{@link #removeNode(NavNode)}</li> - * <li>{@link #moveNode(NavNode, NavNode, int)}</li> - * <li>{@link #refreshNode(NavNode, boolean)}</li> - * <li>{@link #loadAllNodes(NavNode, NavDataProvider)}</li> - * - * </ul> - * <h3>Model selection modification</h3> - * <ul> - * <li>{@link #selectNode(NavNode)}</li> - * <li>{@link #selectNode(String...)}</li> - * <li>{@link #selectParentNode()}</li> - * </ul> - * <h3>Model query</h3> - * <ul> - * <li>{@link #findNode(NavNode, String...)}</li> - * </ul> - * <h3>Child loadors factory</h3> - * The class offers a factory of {@link NavNodeChildLoador}, use the method - * {@link #getChildLoador(Class)} to obtain the correct child loador given his type. - * - * @param <U> Type of ui to bridge - * @author Tony Chemit - chemit@codelutin.com - * @see NavNode - * @see NavNodeChildLoador - * @see AbstractNavTreeCellRenderer - * @since 2.1 - */ -public abstract class NavHelper<M, U, B extends NavBridge<M, N>, N extends NavNode<M, N>> { - - /** Logger */ - static private final Log log = LogFactory.getLog(NavHelper.class); - - //-------------------------------------------------------------------------- - //-- Methods to implement in your helper (related only to ui) - //-------------------------------------------------------------------------- - - public abstract void scrollPathToVisible(TreePath path); - - public abstract void setSelectionPath(TreePath path); - - public abstract void addSelectionPath(TreePath path); - - public abstract void addSelectionPaths(TreePath[] paths); - - public abstract void removeSelectionPath(TreePath path); - - public abstract void removeSelectionPaths(TreePath[] paths); - - public abstract TreeSelectionModel getSelectionModel(); - - public abstract boolean isExpanded(TreePath pathToExpand); - - public abstract void expandPath(TreePath pathToExpand); - - /** - * Register a new root node. - * - * If internal {@link #getModel()} does not exists, creates a new one from - * his given root {@code node}, otherwise just set the new root on the - * existing model. - * - * <b>Note:</b> As a side-effect, the model will be keep in field {@link #getModel()} - * and the {@link #treeModelListener} will be registred on this model. - * - * @param node the root node of the new model - * @param extraArgs extra args to create initial model - * @return the new model - */ - protected abstract M createModel(N node, Object... extraArgs); - - /** - * Obtains the {@link AbstractNavTreeCellRenderer} renderer of the - * registred tree. - * - * @return the renderer of the registred tree or null if no tree was - * registred nor the renderer is a {@link AbstractNavTreeCellRenderer}. - */ - public abstract AbstractNavTreeCellRenderer<M, N> getTreeCellRenderer(); - - /** - * Obtains the selected node of the registred tree. - * - * @return the selected tree or {@code null} if no registred tree nor - * selection empty. - */ - public abstract N getSelectedNode(); - - /** - * Obtains the selected nodes of the registred tree. - * - * @return the selected tree or {@code null} if no registred tree nor - * selection empty. - */ - public abstract List<N> getSelectedNodes(); - - /** - * Registers the given {@code tree} for this helper. - * - * <b>Note:</b> as a side-effect, it will register (if required) the - * {@link #expandListener} listener and (if required) the - * {@link #selectionListener}. - * <b>Note :</b> as a second side-effect, it will register the given {@code willExpandListener} (if not null) - * for the ui and do it <b>BEFORE</b> the {@link #expandListener}. The main - * idea here is to be able to block any expand (or collapse). - * - * @param tree the tree to register - * @param addExpandTreeListener a flag to add expand listener - * @param addOneClickSelectionListener a flag to expend when selection - * @param listener the optional selection listener to add - * @param willExpandListener the optional will expand listener to add <b>BEFORE</b> the default expand tree listener (if he was required) - * @since 2.1.2 - */ - public abstract void setUI(U tree, - boolean addExpandTreeListener, - boolean addOneClickSelectionListener, - TreeSelectionListener listener, - TreeWillExpandListener willExpandListener); - - - /** - * The shared bridge. - * - * A helper deals with only ONE model (this one), becuase we add some - * listeners on it, we prefer always to keep ONE instance (any way this is - * a good thing). - * - * If you want to create a new model, just creates the good root node and - * push it in this model. - * - * For example, if you wrap the shared model with a filter model... Anyway, all - * listeners of this helper apply always of THIs model. - */ - private final B bridge; - - /** the associated ui component */ - private U ui; - - /** The shared data provider used to obtain datas to populate nodes and render them. */ - protected NavDataProvider dataProvider; - - /** - * A {@link TreeWillExpandListener} used to listen when tree should expand. - * - * If so, the listener will load selected node childs if required - * (says when the {@link NavNode#isLoaded()} is sets to {@code false}). - */ - protected TreeWillExpandListener expandListener; - - /** - * pour ouvrir les fils d'un noeud que l'on vient de sélectionner pour - * éviter d'avoir à faire des doubles clics. - */ - protected TreeSelectionListener selectionListener; - - /** - * pour recharger le rendu des noeuds (et charger les fils si nécessaires) - * lors d'une modification dans le modèle de l'arbre. - */ - protected TreeModelListener treeModelListener; - - /** Cache of child loadors. */ - protected static Set<? super NavNodeChildLoador<?, ?, ?, ?, ?>> childLoadors; - - protected static Set<? super NavNodeChildLoador<?, ?, ?, ?, ?>> getChildLoadors() { - if (childLoadors == null) { - childLoadors = new HashSet<NavNodeChildLoador<?, ?, ?, ?, ?>>(); - } - return childLoadors; - } - - /** - * Obtains the {@link NavNodeChildLoador} of the given {@code type} from - * internal cache. - * - * <b>Note:</b> The loador will be instanciated if not found, and push in cache. - * - * @param type the type of loador to get - * @param <L> the type of loador to get - * @return the loador from cache - */ - @SuppressWarnings({"unchecked"}) - public static <L extends NavNodeChildLoador<?, ?, ?, ?, ?>> L getChildLoador(Class<L> type) { - Set<? super NavNodeChildLoador<?, ?, ?, ?, ?>> cache = getChildLoadors(); - NavNodeChildLoador<?, ?, ?, ?, ?> result = null; - for (Object loador : cache) { - if (type.equals(loador.getClass())) { - result = (NavNodeChildLoador<?, ?, ?, ?, ?>) loador; - break; - } - } - if (result == null) { - // add it in cache - try { - result = type.newInstance(); - cache.add(result); - if (log.isDebugEnabled()) { - log.debug("Add " + result + " in loadors cache (new size:" + cache.size() + ")."); - } - } catch (Exception e) { - throw new IllegalArgumentException("Could not instanciate loador [" + type.getName() + "]", e); - } - } - return (L) result; - } - - public NavHelper(B bridge) { - this.bridge = bridge; - - selectionListener = new TreeSelectionListener() { - - @Override - public void valueChanged(TreeSelectionEvent e) { - - if (!checkModel()) { - return; - } - - // Hack, because event.getSource for TreeTable doesnt return selectionModel - TreeSelectionModel source = getSelectionModel(); - - if (source.isSelectionEmpty()) { - - // empty selection - if (log.isDebugEnabled()) { - log.debug("Selection is empty."); - } - return; - } - - boolean debugEnabled = log.isDebugEnabled(); - boolean traceEnabled = log.isTraceEnabled(); - for (TreePath path : e.getPaths()) { - - N node = getNode(path); - if (node == null) { - - // pas de noeud selectionne - if (debugEnabled) { - log.debug("Skip for null node."); - } - continue; - } - - boolean isAdded = e.isAddedPath(path); - - TreePath pathToExpand = new TreePath(NavHelper.this.bridge.getPathToRoot(node)); - boolean pathExpanded = isExpanded(pathToExpand); - - if (traceEnabled || isAdded && debugEnabled) { - log.debug("==== Node selection ===================================="); - log.debug("node ? " + node); - log.debug("is added ? " + isAdded); - log.debug("is path expanded ? " + pathExpanded); - log.debug("is node static ? " + node.isStaticNode()); - log.debug("is node loaded ? " + node.isLoaded()); - log.debug("is node leaf ? " + node.isLeaf()); - log.debug("node nb childs ? " + node.getChildCount()); - } - - if (isAdded && !pathExpanded) { - - // ask to expand path - if (log.isDebugEnabled()) { - log.debug("expand node [" + pathToExpand + "]"); - } - expandPath(pathToExpand); - } - } - } - }; - expandListener = new TreeWillExpandListener() { - @Override - public void treeWillExpand(TreeExpansionEvent event) { - - if (!checkModel()) { - // no model - return; - } - - N source = getNode(event.getPath()); - - if (source.isLoaded()) { - - // node is already loaded, nothing to do - return; - } - - if (log.isDebugEnabled()) { - log.debug("will load childs of node [" + source + "]"); - } - // populate childs of node - source.populateChilds(getBridge(), getDataProvider()); - } - - @Override - public void treeWillCollapse(TreeExpansionEvent event) { - } - }; - - treeModelListener = new TreeModelListener() { - @Override - public void treeNodesInserted(TreeModelEvent e) { - if (!checkModel()) { - // no model - return; - } - N source = getNode(e.getTreePath()); - Object[] children = e.getChildren(); - if (log.isDebugEnabled()) { - log.debug(getMessage("inserted ", source, children)); - } - - // ask to populate children nodes - populateNode(null, children, false); - } - - @SuppressWarnings({"unchecked"}) - @Override - public void treeNodesRemoved(TreeModelEvent e) { - if (!checkModel()) { - // no model - return; - } - N source = getNode(e.getTreePath()); - Object[] children = e.getChildren(); - if (log.isDebugEnabled()) { - log.debug(getMessage("removed ", source, children)); - } - - // Invalidates nodes in renderer cache (if any) - AbstractNavTreeCellRenderer<M, N> renderer = getTreeCellRenderer(); - if (children != null && renderer != null) { - for (Object child : children) { - renderer.invalidateCache((N) child); - } - } - } - - @Override - public void treeNodesChanged(TreeModelEvent e) { - if (!checkModel()) { - // no model - return; - } - - N source = getNode(e.getTreePath()); - Object[] children = e.getChildren(); - if (log.isDebugEnabled()) { - log.debug(getMessage("changed ", source, children)); - } - - // ask to populate modified child nodes - populateNode(null, children, false); - } - - @Override - public void treeStructureChanged(TreeModelEvent e) { - if (!checkModel()) { - // no model - return; - } - N source = getNode(e.getTreePath()); - Object[] children = e.getChildren(); - if (log.isDebugEnabled()) { - log.debug(getMessage("structure changed", source, children)); - } - - // ask to populate structure modified node and nodes recursively - populateNode(source, children, true); - } - - protected String getMessage(String action, N source, Object[] children) { - StringBuilder sb = new StringBuilder(); - sb.append("==== Nodes "); - sb.append(action); - sb.append(" ================="); - sb.append("\nsource : ").append(source); - sb.append("\nnb nodes : "); - sb.append(children == null ? 0 : children.length); - if (children != null) { - int i = 0; - for (Object child : children) { - sb.append("\n ["); - sb.append(i++); - sb.append("] - "); - sb.append(child); - } - } - return sb.toString(); - } - }; - } - - /** - * Obtains the attached data provider used to populate and render nodes. - * - * @return the attached data provider - */ - protected NavDataProvider getDataProvider() { - return dataProvider; - } - - /** - * Obtains the model. - * - * @return the internal tree model or {@code null} if none was created. - */ - public M getModel() { - return bridge.getModel(); - } - - /** - * Obtains the bridge . - * - * @return the internal bridge used by helper. - */ - protected B getBridge() { - return bridge; - } - - /** - * Obtains the ui associated with model in helper. - * - * @return the ui (or {@code null} if no ui attached) - */ - public U getUI() { - return ui; - } - - public N getRootNode() { - if (!checkModel()) { - return null; - } - return bridge.getRoot(); - } - - /** - * Obtains the path of ids fro the root node to the selected node on the - * registred tree. - * - * @return the array of ids from root node to selected node. - */ - public String[] getSelectedIds() { - List<String> result = new ArrayList<String>(); - N selectedNode = getSelectedNode(); - while (selectedNode != null && !selectedNode.isRoot()) { - - result.add(selectedNode.getId()); - selectedNode = selectedNode.getParent(); - } - Collections.reverse(result); - return result.toArray(new String[result.size()]); - } - - /** - * Registers the given {@code tree} for this helper. - * - * <b>Note:</b> as a side-effect, it will register (if required) the - * {@link #expandListener} listener and the {@link #selectionListener}. - * - * @param tree the tree to register - * @param addExpandTreeListener a flag to add expand listener - */ - public void setUI(U tree, - boolean addExpandTreeListener) { - setUI(tree, addExpandTreeListener, null); - } - - /** - * Registers the given {@code tree} for this helper. - * - * <b>Note:</b> as a side-effect, it will register (if required) the - * {@link #expandListener} listener and the {@link #selectionListener}. - * - * @param tree the tree to register - * @param addExpandTreeListener a flag to add expand listener - * @param listener the optional selection listener to add - */ - public void setUI(U tree, - boolean addExpandTreeListener, - TreeSelectionListener listener) { - - setUI(tree, addExpandTreeListener, true, listener); - } - - /** - * Registers the given {@code tree} for this helper. - * - * <b>Note:</b> as a side-effect, it will register (if required) the - * {@link #expandListener} listener and (if required) the - * {@link #selectionListener}. - * - * @param tree the tree to register - * @param addExpandTreeListener a flag to add expand listener - * @param addOneClickSelectionListener a flag to expend when selection - * @param listener the optional selection listener to add - */ - public void setUI(U tree, - boolean addExpandTreeListener, - boolean addOneClickSelectionListener, - TreeSelectionListener listener) { - setUI(tree, - addExpandTreeListener, - addOneClickSelectionListener, - listener, - null - ); - } - - /** - * Registers the {@code dataProvider} for the helper. - * - * <b>Node:</b> As a side-effect, the provider will be propagate to the - * renderer of the registred tree (if any). - * - * @param dataProvider the data provider to use - */ - public void setDataProvider(NavDataProvider dataProvider) { - this.dataProvider = dataProvider; - AbstractNavTreeCellRenderer<M, N> renderer = getTreeCellRenderer(); - if (renderer != null) { - - // dispatch provider to renderer - renderer.setDataProvider(dataProvider); - } - } - - /** - * Inserts the given node to the given {@code parentNode}. - * - * The node will be added to his parent, then creation listeners will be - * fired. - * - * @param parentNode the parent node where to insert the new node * - * @param newNode the node to insert - */ - public void insertNode(N parentNode, N newNode) { - parentNode.add(newNode); - bridge.notifyNodeInserted(newNode); - } - - /** - * Inserts the given node to the given {@code parentNode}. - * - * The node will be added to his parent, then creation listeners will be - * fired. - * - * @param parentNode the parent node where to insert the new node * - * @param newNode the node to insert - * @param position position of node is inserted - */ - public void insertNode(N parentNode, N newNode, int position) { - parentNode.insert(newNode, position); - bridge.notifyNodeInserted(newNode); - } - - /** - * Removes the given {@code node} from the registred tree model and returns - * his parent. - * - * @param node the node to remove - * @return the parent node of the removed node. - */ - public N removeNode(N node) { - N parentNode = node.getParent(); - bridge.removeNodeFromParent(node); - return parentNode; - } - - /** - * Moves the given {@code node} to the new {@code position}. - * - * @param parentNode the parent node - * @param node the node to move - * @param position the new position of the node - */ - public void moveNode(N parentNode, N node, int position) { - parentNode.remove(node); - parentNode.insert(node, position); - bridge.nodeStructureChanged(parentNode); - } - - /** - * Refreshs the given {@code node}. - * - * If flag {@code deep} is set to {@code true}, then it will refresh - * recursively children nodes. - * - * <b>Note:</b>As a side-effect, evvery node involved will become - * {@code dirty}. - * - * @param node the node to refresh - * @param deep un flag pour activer la repainte de la descendance du - * noeud - * @see NavNode#isDirty() - */ - @SuppressWarnings({"unchecked"}) - public void refreshNode(N node, boolean deep) { - if (log.isDebugEnabled()) { - log.debug("Will refresh (deep ? " + deep + ") node " + node); - } - bridge.nodeChanged(node); - if (deep) { - // repaint childs nodes - Enumeration<N> e = node.children(); - while (e.hasMoreElements()) { - N child = e.nextElement(); - refreshNode(child, true); - } - } - } - - /** - * To load all nodes of a model. - * - * @param node the root node to load - * @param dataProvider the data provider used to populate nodes - */ - @SuppressWarnings({"unchecked"}) - public void loadAllNodes(N node, NavDataProvider dataProvider) { - if (!checkModel()) { - return; - } - if (!node.isLoaded()) { - node.populateChilds(getBridge(), dataProvider); - Enumeration<? extends NavNode<?, ?>> enumeration = node.children(); - while (enumeration.hasMoreElements()) { - N jaxxNode = (N) enumeration.nextElement(); - loadAllNodes(jaxxNode, dataProvider); - } - } - } - - /** - * Selects the parent of the currently selected node. - * - * <b>Note:</b> If selection is empty, then throws a NPE. - * - * @throws NullPointerException if selection is empty - */ - public void selectParentNode() throws NullPointerException { - - N node = getSelectedNode(); - - if (node == null) { - // pas de noeud selectionne - throw new NullPointerException("no selected node in context"); - } - node = node.getParent(); - - selectNode(node); - } - - /** - * Selects the given {@code node} in the registred tree. - * - * @param node the node to select - */ - public void selectNode(N node) { - if (!checkModel()) { - - // no model - return; - } - if (log.isDebugEnabled()) { - log.debug("try to select node [" + node + "]"); - } - TreePath path = new TreePath(bridge.getPathToRoot(node)); - - addSelectionPath(path); - scrollPathToVisible(path); - } - - /** - * Selects the given {@code nodes} in the registred tree. - * - * @param nodes the nodes to select - */ - public void selectNodes(List<N> nodes) { - if (!checkModel()) { - - // no model - return; - } - List<TreePath> paths = new ArrayList<TreePath>(); - for (N node : nodes) { - paths.add(new TreePath(bridge.getPathToRoot(node))); - } - addSelectionPaths(paths.toArray(new TreePath[paths.size()])); - } - - /** - * Unselects the given {@code node} in the registred tree. - * - * @param node the node to select - */ - public void unSelectNode(N node) { - if (!checkModel()) { - - // no model - return; - } - if (log.isDebugEnabled()) { - log.debug("try to select node [" + node + "]"); - } - TreePath path = new TreePath(bridge.getPathToRoot(node)); - - removeSelectionPath(path); - } - - /** - * Selects the given {@code nodes} in the registred tree. - * - * @param nodes the nodes to select - */ - public void unSelectNodes(List<N> nodes) { - if (!checkModel()) { - - // no model - return; - } - for (N node : nodes) { - unSelectNode(node); - } - } - - /** - * Selects the node described by his given {@code path} of ids. - * - * @param path the absolute path of ids from root node to node to select. - */ - public void selectNode(String... path) { - if (!checkModel()) { - - // no model - return; - } - if (log.isDebugEnabled()) { - log.debug("try to select node from ids " + Arrays.toString(path)); - } - N root = bridge.getRoot(); - N node = findNode(root, path); - if (log.isDebugEnabled()) { - log.debug("selected node [" + node + "]"); - } - if (node != null) { - selectNode(node); - } - } - - /** - * Finds a node from the given root {@code node}, applying the path given - * by {@code ids}. - * - * @param node the starting node - * @param ids the path of ids to apply on the node. - * @return the find node or {@code null} if no node matchs. - */ - public N findNode(N node, String... ids) { - if (!checkModel()) { - - // no model - return null; - } - N result = null; - for (String id : ids) { - - result = node.findNodeById(id, getBridge(), getDataProvider()); - - if (result == null) { - - // un des noeud n'a pas ete trouve, on sort - break; - } - node = result; - } - return result; - } - - /** - * Finds a node from the given root {@code node}, and return child searched - * - * @param node the starting node - * @param id id of searched child - * @return the find node or {@code null} if no node matchs. - */ - public N getChild(N node, String id) { - if (!checkModel()) { - - // no model - return null; - } - - return node.getChild(id, getBridge(), getDataProvider()); - } - - /** - * Checks if internal model was created. - * - * @return {@code true} if model was created, {@code false} otherwise. - */ - protected boolean checkModel() { - if (getModel() == null) { - - // no model set, - if (log.isWarnEnabled()) { - log.warn("No model set in " + this); - } - return false; - } - // model is set - return true; - } - - /** - * Populates nodes. - * - * If {@code node} is not {@code null}, then populate it. - * - * If {@code children} is not {@code null}, then populate them, moreover - * if {@code recurse} is set to {@code true} then do a recurse refresh on - * children. - * - * @param node the parent node to populate (optional) - * @param children the child nodes to populate (optional) - * @param recurse flag sets to {@code true} if should do recurse refresh on - * given {@code children} nodes. - */ - @SuppressWarnings({"unchecked"}) - protected void populateNode(N node, - Object[] children, - boolean recurse) { - NavDataProvider dataProvider = getDataProvider(); - if (node != null) { - if (log.isDebugEnabled()) { - log.debug("Will populate node : " + node); - } - node.populateNode(getBridge(), dataProvider, false); - } - if (children != null) { - for (Object o : children) { - N child = (N) o; - if (log.isDebugEnabled()) { - log.debug("Will populate child node : " + child); - } - child.populateNode(getBridge(), dataProvider, recurse); - } - } - } - - /** - * Convinient method to objet the casted node of a {@link TreePath}. - * - * @param path the path contaning the node. - * @return the casted node from the path. - */ - @SuppressWarnings({"unchecked"}) - protected N getNode(TreePath path) { - return (N) path.getLastPathComponent(); - } - - protected void setUI(U ui) { - this.ui = ui; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavNode.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavNode.java deleted file mode 100644 index eb9ef63..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavNode.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav; - -import jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; - -import javax.swing.tree.TreeNode; -import java.io.Serializable; - -/** - * Definition of a node with a optional {@code childLoador} to build childs of - * node. - * - * A node is identified by an {@link #getId} of an associated data of type - * {@link #getInternalClass}. - * - * <b>Note:</b> - * <p><i> While using a {@code childLoador}, we can not know before node - * was loaded the exact count of his childs. As a matter of facts, real leaf - * nodes appears at the beginning in ui as a not leaf (there is a root handler). - * When node was loaded, a leaf node will be then displayed as required. - * </i></p> - * - * <h2>Why NavNode is generic ?</h2> - * In a project, you should implements your own Node extending with one like this : - * <pre> - * class MyNode extends NavNode<MyNode> { ... } - * </pre> - * While in this class, you overrides every method with a node return type, - * co-variance you'll be able to use this code : - * <pre> - * MyNode parentNode = new MyNode(); - * MyNode node = parentNode.getFirstNode(); - * </pre> - * So for final application this generic type avoid any cast for your own node - * type, this is quite convinient. - * - * Even if in your project, you wants to have a heriarchy of nodes, this will - * still works (if you use a genercic type on your abstract nodes). - * <h2>Internal states</h2> - * <ul> - * <li><b>internalClass</b> : the type of data associated with the node</li> - * <li><b>context</b> : an optinal context to distinguish different types of - * node with same {@code internalclass}</li> - * <li><b>id</b> : id of the data associated with the node</li> - * <li><b>dirty</b> : flag sets to {@code true} when node render MUST be recomputed</li> - * <li><b>loaded</b> : flag sets to {@code true} when node was loaded</li> - * <li><b>childLoador</b> : optional loador of childs</li> - * </ul> - * <h2>Static nodes</h2> - * Some nodes do not need auto-loading, we call them {@code static nodes}. - * The method {@link #isStaticNode()} gives this state. - * - * <b>Note:</b> A static node has no {@code childLoador}. - * <h2>Node loading</h2> - * Initialy node has no data child nodes, ({@link #isLoaded()} equals - * {@code false}). - * when model requires node's childs, it can load them via method - * {@link #populateNode(NavBridge, NavDataProvider, boolean)} - * and {@link #populateChilds(NavBridge, NavDataProvider)} methods. - * <h2>Node rendering</h2> - * the {@link AbstractNavTreeCellRenderer} looks the {@link #isDirty} state to - * know when render should be (re-)compute and set back the state to {@code false}. - * - * Each time, a node is modified, the {@link #isDirty} should be set to {@code true}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.1 - */ -public interface NavNode<M, N extends NavNode<M, N>> extends Cloneable, TreeNode, Serializable { - - String getId(); - - String getContext(); - - Class<?> getInternalClass(); - - boolean isLoaded(); - - boolean isDirty(); - - /** - * Convinient method to known if the node is a {@code String} typed. - * - * @return {@code true} if the type of node if - */ - boolean isStringNode(); - - /** - * To know if the node is static. - * - * A {@code static} node has no {@code childLoador}. - * - * @return {@code true} when the node is static : says, the node has - * no {@code childLoador}. - */ - boolean isStaticNode(); - - /** - * Gets the first node form this one to the root which has a none - * {@code String} type. - * - * @return the first concrete node type - */ - N getContainerNode(); - - /** - * Given an {@code id}, obtain the child with matching id. - * - * If node is NOT {@code loaded}, then first loads it (method - * {@link #populateChilds(NavBridge, NavDataProvider)}) then do search - * on direct childs of the node recursivly. - * - * @param id the id of the researched node - * @param bridge model owner of nodes - * @param provider data provider - * @return the found node or {@code null} if not found - */ - N findNodeById(String id, - NavBridge<M, N> bridge, - NavDataProvider provider); - - /** - * Given an {@code id}, obtain the child with matching id. - * - * If node is NOT {@code loaded}, then first loads it (method - * {@link #populateChilds(NavBridge, NavDataProvider)}) then return - * on direct childs of the node. - * - * @param id the id of the researched node - * @param bridge model owner of nodes - * @param provider data provider - * @return the found node or {@code null} if not found - */ - N getChild(String id, - NavBridge<M, N> bridge, - NavDataProvider provider); - - /** - * Changes the {@link #isDirty} state. - * - * As a side effect, when a renderer will use this node, it will force to - * reload the render from the {@link NavDataProvider}. - * - * @param dirty the new dirty value - */ - void setDirty(boolean dirty); - - @Override - boolean isLeaf(); - - Object getUserObject(); - - @Override - String toString(); - - //-------------------------------------------------------------------------- - //-- Populate methods - //-------------------------------------------------------------------------- - - /** - * To populate the node. A side-effect of this method is to set {@code dirty} - * the node (renderer will recompute the render of the node). - * - * If {@code populateChilds} is set to {@code true}, then also populate - * childs of the node using the given {@code dataProvider}. - * - * @param bridge le delegate modèles content le noeud - * @param provider le provider de données - * @param populateChilds un drapeau pour charger aussi les fils du noeud courant - */ - void populateNode(NavBridge<M, N> bridge, - NavDataProvider provider, - boolean populateChilds); - - /** - * To populate childs of the node (only when a none static node). - * A side-effect of this method is to set {@code loaded} of the node. - * - * For a static node, do nothing. - * - * @param bridge model owner of the node - * @param provider data provider - */ - void populateChilds(NavBridge<M, N> bridge, NavDataProvider provider); - - //-------------------------------------------------------------------------- - //-- Overrides to use generic type as return - //-------------------------------------------------------------------------- - - boolean isRoot(); - - @Override - N getParent(); - - void add(N node); - - void remove(N node); - - void insert(N node, int position); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavNodeChildLoador.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavNodeChildLoador.java deleted file mode 100644 index 6f0c10f..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavNodeChildLoador.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.Serializable; -import java.util.List; - -/** - * Object to load childs of a node. - * - * It uses {@link NavDataProvider} in method - * {@link #loadChilds(NavBridge, NavNode, NavDataProvider)} to obtain datas - * then build childs nodes. - * - * A factory of such objects can be found in {@link NavHelper} to make - * them reusable in other places than inside a {@link NavNode} to auto-load - * childs. - * - * For example when you want to creat by hand a new node, always prefer to reuse - * a such object rathen than duplicate same code in helper... - * - * @param <T> type of data used to create nodes (can be just a String type to use only ids) - * @param <O> type of data associated with nodes - * @param <N> type of node to used (to make possible full co-variance and no cast in fal implementations). - * @author Tony Chemit - chemit@codelutin.com - * @see NavHelper - * @see NavNode - * @since 2.1 - */ -public abstract class NavNodeChildLoador<T, O, M, B extends NavBridge<M, N>, N extends NavNode<M, N>> implements Serializable { - - /** Logger. */ - static private final Log log = LogFactory.getLog(NavNodeChildLoador.class); - - private static final long serialVersionUID = 1L; - - /** Type of data of the node */ - protected final Class<O> beanType; - - protected NavNodeChildLoador(Class<O> beanType) { - this.beanType = beanType; - } - - /** - * Obtain the list of data used to create nodes. - * - * If type {@code T} is {@code O}, we directly use the data associated with nodes. - * - * @param parentClass type of parent - * @param parentId id of parent - * @param dataProvider the data provider - * @return the list of data - * @throws Exception if any problem - */ - public abstract List<T> getData(Class<?> parentClass, - String parentId, - NavDataProvider dataProvider) throws Exception; - - /** - * Hook to create a child node given his {@code data}. - * - * @param data the data of the node to create - * @param dataProvider the data provider - * @return the created node - */ - public abstract N createNode(T data, NavDataProvider dataProvider); - - /** - * Returns the type of data associated with nodes to create. - * - * @return the type of data associated with created nodes. - */ - public Class<O> getBeanType() { - return beanType; - } - - /** - * Load childs of the given {@code parentnode}. - * - * @param bridge the model owner of nodes - * @param parentNode the parent node where to insert nodes - * @param dataProvider data provider - * @throws Exception pour tout probleme de recuperation de donnees - */ - public void loadChilds(B bridge, - N parentNode, - NavDataProvider dataProvider) throws Exception { - - N containerNode = parentNode.getContainerNode(); - - List<T> datas; - if (containerNode == null) { - - // pas d'ancetre, il doit s'agir d'un premier noeud de données - // depuis le noeud root - - // recuperation des objets fils (sans connaitre de parent) - datas = getData(null, null, dataProvider); - - } else { - if (log.isDebugEnabled()) { - log.debug("search data for " + containerNode.getInternalClass() + - " : " + containerNode.getId()); - } - - // recuperation des objets fils - datas = getData(containerNode.getInternalClass(), - containerNode.getId(), - dataProvider); - } - - // on charge les fils - addChildNodes(parentNode, datas, dataProvider); - - // notifie le modele d'un ajout de noeuds - bridge.notifyChildNodesInserted(parentNode); - } - - /** - * Add childs to given {@code parentNode} using retrive {@code datas} from - * the data provider. - * - * This method is invoked by the {@link #loadChilds(NavBridge, NavNode, NavDataProvider)}. - * - * @param parentNode the node where to insert - * @param datas the data used to create node - * @param dataProvider the data provider - */ - protected void addChildNodes(N parentNode, - List<T> datas, - NavDataProvider dataProvider) { - - // creation des noeuds fils - if (datas != null) { - for (T o : datas) { - if (log.isDebugEnabled()) { - log.debug("[" + parentNode + "] Will add child node for " + o); - } - N node = createNode(o, dataProvider); - parentNode.add(node); - } - } - } - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/AbstractNavTreeCellRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/AbstractNavTreeCellRenderer.java deleted file mode 100644 index c311361..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/AbstractNavTreeCellRenderer.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav.tree; - -import jaxx.runtime.swing.nav.NavDataProvider; -import jaxx.runtime.swing.nav.NavNode; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.tree.DefaultTreeCellRenderer; -import java.util.HashMap; -import java.util.Map; - -import static org.nuiton.i18n.I18n.t; - -/** - * Le renderer abstrait (qui a toutes les methodes qui aident) pour implanter de - * vrai renderer pour les différents cas d'utilisation de l'abre de navigation. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.2 - */ -public abstract class AbstractNavTreeCellRenderer<M, N extends NavNode<M, N>> extends DefaultTreeCellRenderer { - - /** Logger */ - protected static final Log log = - LogFactory.getLog(AbstractNavTreeCellRenderer.class); - - /** source de donnée */ - protected NavDataProvider dataProvider; - - /** le cache de rendu */ - protected final Map<N, String> renderCache = new HashMap<N, String>(); - - /** - * Determines the text render of a node using the {@link #dataProvider}. - * - * @param node the node to render - * @return the text render of the node - */ - protected abstract String computeNodeText(N node); - - protected AbstractNavTreeCellRenderer() { - } - - public NavDataProvider getDataProvider() { - return dataProvider; - } - - public void setDataProvider(NavDataProvider dataProvider) { - this.dataProvider = dataProvider; - - // une nouvelle source utilisée, on vide le cache - clearCache(); - } - - public void clearCache() { - renderCache.clear(); - } - - public void invalidateCache(N node) { - renderCache.remove(node); - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - clearCache(); - } - - public String getNodeText(N node) { - if (node == null) { - return null; - } - String text; - - if (node.isDirty() || !renderCache.containsKey(node)) { - - // calculer le rendu du noeud - if (node.isStringNode()) { - text = t(node.getId()); - - } else { - - text = computeNodeText(node); - } - - if (log.isDebugEnabled()) { - log.debug("text for node [" + node + "] = <" + text + ">"); - } - - // sauvegarde dans le cache - renderCache.put(node, text); - - // le noeud est de nouveau propre - node.setDirty(false); - - } else { - - // recupération directement du rendu dans le cache - text = renderCache.get(node); - } - - return text; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeBridge.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeBridge.java deleted file mode 100644 index bfeb4fe..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeBridge.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav.tree; - -import jaxx.runtime.swing.nav.NavBridge; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.event.TreeModelListener; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; -import java.util.Enumeration; -import java.util.EventListener; - -/** - * Delegate model used to switch between tree model and tree table model api - * - * @author Sylvain Lletellier - * @since 2.1 - */ -public class NavTreeBridge<N extends NavTreeNode<N>> implements NavBridge<DefaultTreeModel, N> { - - /** Logger */ - static private final Log log = LogFactory.getLog(NavTreeBridge.class); - - /** bridge model */ - protected DefaultTreeModel model; - - /** bridge ui */ -// protected JTree ui; -// public NavTreeBridge() { -// } - - //-------------------------------------------------------------------------- - //-- Model Queries - //-------------------------------------------------------------------------- - @Override - public DefaultTreeModel getModel() { - return model; - } - - @Override - @SuppressWarnings({"unchecked"}) - public N getRoot() { - return (N) model.getRoot(); - } - - @Override - public boolean isLeaf(Object node) { - return model.isLeaf(node); - } - - @Override - public int getChildCount(Object parent) { - return model.getChildCount(parent); - } - - @Override - @SuppressWarnings({"unchecked"}) - public N getChild(Object parent, int index) { - return (N) model.getChild(parent, index); - } - - @Override - public int getIndexOfChild(Object parent, Object child) { - return model.getIndexOfChild(parent, child); - } - - @Override - public TreeNode[] getPathToRoot(TreeNode aNode) { - return model.getPathToRoot(aNode); - } - - //-------------------------------------------------------------------------- - //-- Model modification - //-------------------------------------------------------------------------- - - @Override - public void setModel(DefaultTreeModel model) { - this.model = model; - } - - @Override - public void setRoot(N node) { - model.setRoot(node); - } - - @Override - public void insertNodeInto(N newChild, N parent, int index) { - model.insertNodeInto(newChild, parent, index); - } - - @Override - public void removeNodeFromParent(N node) { - model.removeNodeFromParent(node); - } - - @Override - public void reload(N node) { - model.reload(); - } - - @Override - public boolean canLoadChild(N node) { - return true; - } - - //-------------------------------------------------------------------------- - //-- Model Listeners notifications - //-------------------------------------------------------------------------- - - @Override - public void valueForPathChanged(TreePath path, Object newValue) { - model.valueForPathChanged(path, newValue); - } - - @Override - public void nodesWereInserted(N parent, int[] indices) { - model.nodesWereInserted(parent, indices); - } - - @Override - public void nodeWereInserted(N parentNode, int childIndice, N node) { - int[] indices = new int[1]; - indices[0] = childIndice; - model.nodesWereInserted(parentNode, indices); - } - - @Override - public void nodeChanged(TreeNode node) { - model.nodeChanged(node); - } - - @Override - public void nodeStructureChanged(TreeNode node) { - model.nodeStructureChanged(node); - } - - @Override - public void nodesWereRemoved(TreeNode node, int[] childIndices, - Object[] removedChildren) { - model.nodesWereRemoved(node, childIndices, removedChildren); - } - - @Override - public void nodesChanged(TreeNode node, int[] childIndices) { - model.nodesChanged(node, childIndices); - } - - @Override - @SuppressWarnings({"unchecked"}) - public void notifyChildNodesInserted(N node) { - int count = node.getChildCount(); - if (count < 1) { - if (log.isDebugEnabled()) { - log.debug("Skip for leaf node : " + node); - } - return; - } - if (log.isDebugEnabled()) { - log.debug("Notify for node : " + node + ", " + count + " child(s) inserted."); - } - int[] indices = new int[count]; - for (int i = 0; i < count; i++) { - indices[i] = i; - } - - nodesWereInserted(node, indices); - - // recurse notify on childs - for (Enumeration<? extends NavTreeNode<?>> childs = node.children(); - childs.hasMoreElements(); ) { - N child = (N) childs.nextElement(); - notifyChildNodesInserted(child); - } - } - - @Override - public void notifyNodeInserted(N node) { - - N parent = node.getParent(); - if (parent != null) { - int indice = parent.getIndex(node); - if (log.isDebugEnabled()) { - log.debug("Notify for node : " + node + ", for parent [" + parent + "] child " + indice + " inserted."); - } - nodesWereInserted(parent, new int[]{indice}); - notifyChildNodesInserted(node); - } - } - - //-------------------------------------------------------------------------- - //-- TreeModelListener provider - //-------------------------------------------------------------------------- - - @Override - public void addTreeModelListener(TreeModelListener l) { - model.addTreeModelListener(l); - } - - @Override - public void removeTreeModelListener(TreeModelListener l) { - model.removeTreeModelListener(l); - } - - @Override - public TreeModelListener[] getTreeModelListeners() { - return model.getTreeModelListeners(); - } - - @Override - @SuppressWarnings({"unchecked"}) - public <T extends EventListener> T[] getListeners(Class<T> listenerType) { - return model.getListeners(listenerType); - } - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeHelper.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeHelper.java deleted file mode 100644 index 62a0bb6..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeHelper.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav.tree; - -import jaxx.runtime.swing.nav.NavHelper; - -import javax.swing.JTree; -import javax.swing.event.TreeSelectionListener; -import javax.swing.event.TreeWillExpandListener; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreeCellRenderer; -import javax.swing.tree.TreePath; -import javax.swing.tree.TreeSelectionModel; -import java.util.ArrayList; -import java.util.List; - -/** - * The implementation of {@link NavHelper} base on a {@link JTree} component. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.1 - */ -public class NavTreeHelper<N extends NavTreeNode<N>> extends NavHelper<DefaultTreeModel, JTree, NavTreeBridge<N>, N> { - - public NavTreeHelper() { - this(new NavTreeBridge<N>()); - } - - public NavTreeHelper(NavTreeBridge<N> bridge) { - super(bridge); - } - - @Override - public void scrollPathToVisible(TreePath path) { - getUI().scrollPathToVisible(path); - } - - @Override - public void setSelectionPath(TreePath path) { - getUI().setSelectionPath(path); - } - - @Override - public void addSelectionPaths(TreePath[] paths) { - getUI().addSelectionPaths(paths); - } - - @Override - public void addSelectionPath(TreePath path) { - getUI().addSelectionPath(path); - } - - @Override - public void removeSelectionPaths(TreePath[] path) { - getUI().removeSelectionPaths(path); - } - - @Override - public void removeSelectionPath(TreePath path) { - getUI().removeSelectionPath(path); - } - - @Override - public TreeSelectionModel getSelectionModel() { - return getUI().getSelectionModel(); - } - - @Override - public boolean isExpanded(TreePath pathToExpand) { - return getUI().isExpanded(pathToExpand); - } - - @Override - public void expandPath(TreePath pathToExpand) { - getUI().expandPath(pathToExpand); - } - - @SuppressWarnings({"unchecked"}) - @Override - public AbstractNavTreeCellRenderer<DefaultTreeModel, N> getTreeCellRenderer() { - JTree t = getUI(); - if (t == null) { - return null; - } - TreeCellRenderer r = t.getCellRenderer(); - if (r instanceof AbstractNavTreeCellRenderer) { - return (AbstractNavTreeCellRenderer<DefaultTreeModel, N>) r; - } - return null; - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getSelectedNode() { - JTree tree = getUI(); - if (tree == null) { - return null; - } - TreePath path = tree.getSelectionPath(); - N node = null; - if (path != null) { - node = (N) path.getLastPathComponent(); - } - return node; - } - - @SuppressWarnings({"unchecked"}) - @Override - public List<N> getSelectedNodes() { - JTree tree = getUI(); - if (tree == null) { - return null; - } - TreePath[] paths = tree.getSelectionPaths(); - List<N> nodes = new ArrayList<N>(); - if (paths != null) { - for (TreePath path : paths) { - if (path != null) { - nodes.add((N) path.getLastPathComponent()); - } - } - } - return nodes; - } - - @Override - public void setUI(JTree tree, - boolean addExpandTreeListener, - boolean addOneClickSelectionListener, - TreeSelectionListener listener, - TreeWillExpandListener willExpandListener) { - setUI(tree); - if (willExpandListener != null) { - tree.addTreeWillExpandListener(willExpandListener); - } - if (addExpandTreeListener) { - tree.addTreeWillExpandListener(expandListener); - } - if (listener != null) { - tree.addTreeSelectionListener(listener); - } - if (addOneClickSelectionListener) { - tree.addTreeSelectionListener(selectionListener); - } - } - - @Override - protected DefaultTreeModel createModel(N node, Object... extraArgs) { - NavTreeBridge<N> bridge = getBridge(); - DefaultTreeModel model = bridge.getModel(); - if (model == null) { - model = new DefaultTreeModel(node); - bridge.setModel(model); - bridge.addTreeModelListener(treeModelListener); - } else { - bridge.setRoot(node); - } - - // notify structure has changed - bridge.nodeStructureChanged(getRootNode()); - return model; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeNode.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeNode.java deleted file mode 100644 index 492e355..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeNode.java +++ /dev/null @@ -1,425 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav.tree; - -import jaxx.runtime.swing.nav.NavBridge; -import jaxx.runtime.swing.nav.NavDataProvider; -import jaxx.runtime.swing.nav.NavNode; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreeNode; -import java.util.Enumeration; - -/** - * Implementation of {@link NavNode} used to create in tree table - * This node extends {@link DefaultMutableTreeNode} - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.2 - */ -public class NavTreeNode<N extends NavTreeNode<N>> extends DefaultMutableTreeNode implements NavNode<DefaultTreeModel, N> { - - /** Logger */ - static private final Log log = LogFactory.getLog(NavNode.class); - - private static final long serialVersionUID = 1L; - - /** Type of data associated with the node */ - protected final Class<?> internalClass; - - /** - * Optinal context to distinguish different nodes with same - * {@link #internalClass}. - */ - protected final String context; - - /** Id of the data associated with the node. */ - protected final String id; - - /** Flag to know when renderer should (re-)compute render of the node. */ - protected boolean dirty = true; - - /** Flag to know when the none static node was loaded. */ - protected boolean loaded; - - /** Optional child loador to lazy create childs of the node. */ - protected final NavTreeNodeChildLoador<?, ?, N> childLoador; - - protected NavTreeNode(String id) { - this(String.class, id, null, null); - } - - public NavTreeNode(Class<?> internalClass, - String id, - String context, - NavTreeNodeChildLoador<?, ?, N> childLoador) { - this.internalClass = internalClass; - this.id = id; - this.context = context; - this.childLoador = childLoador; - if (isStaticNode()) { - - // A static node is always full loaded - loaded = true; - } - if (log.isDebugEnabled()) { - log.debug("new node : " + this); - } - } - - @Override - public String getId() { - return id; - } - - @Override - public String getContext() { - return context; - } - - @Override - public Class<?> getInternalClass() { - return internalClass; - } - - @Override - public boolean isLoaded() { - return loaded; - } - - @Override - public boolean isDirty() { - return dirty; - } - - @Override - public boolean isStringNode() { - return String.class.equals(internalClass); - } - - @Override - public boolean isStaticNode() { - return childLoador == null; - } - - @Override - @SuppressWarnings({"unchecked"}) - public N getContainerNode() { - if (isRoot()) { - // si on arrive sur le root, quelque chose ne va pas, - // on bloque par null, a defaut de declancher une exception - return null; - } - - if (isStringNode()) { - // on est sur un noeud de type String, donc on regarde sur le parent - return getParent().getContainerNode(); - } - - // cas final : sur un noeud de donnee + classe interne de donnee - return (N) this; - } - - @Override - @SuppressWarnings({"unchecked"}) - public N findNodeById(String id, - NavBridge<DefaultTreeModel, N> model, - NavDataProvider provider) { - if (id == null) { - - // id null ? donc rien a faire - return null; - } - if (id.equals(getId())) { - - // on a trouve le bon noeud - return (N) this; - } - - if (!isLoaded()) { - - // il faut charger les fils du noeud pour effectuer la recherche - populateChilds(model, provider); - } - - if (isLeaf()) { - - // au final le noeud est une feuille, donc ne convient pas - return null; - } - - // on recherche dans les fils - Enumeration<N> enumeration = children(); - while (enumeration.hasMoreElements()) { - N node = enumeration.nextElement(); - N nodeById = node.findNodeById(id, model, provider); - if (nodeById != null) { - return nodeById; - } - } - - // aucun des noeud fils ne convient - return null; - } - - @Override - public N getChild(String id, - NavBridge<DefaultTreeModel, N> bridge, - NavDataProvider provider) { - - if (id == null) { - - // id null ? donc rien a faire - return null; - } - - if (!isLoaded()) { - - // il faut charger les fils du noeud pour effectuer la recherche - populateChilds(bridge, provider); - } - - if (isLeaf()) { - - // au final le noeud est une feuille, donc ne convient pas - return null; - } - - // on recherche dans les fils - Enumeration<N> enumeration = children(); - while (enumeration.hasMoreElements()) { - N child = enumeration.nextElement(); - if (id.equals(child.getId())) { - return child; - } - } - - // aucun des noeud fils ne convient - return null; - } - - @Override - public void setDirty(boolean dirty) { - this.dirty = dirty; - } - - @Override - public boolean isLeaf() { - // there is two behaviours for the test : - // 1 - when the node is static, then can directly use his number of child - // to determine if node is a leaf (no child) - // 2 - when the node is dynamic, then ALWAYS says the node is NOT a leaf until - // it was loaded, otherwise the WillExpand listener will not load the childs... - // Once the node is loaded, use back the normal behaviour (count number of childs) - return isStaticNode() ? super.isLeaf() : isLoaded() && getChildCount() == 0; - } - - @Override - public Object getUserObject() { - return id; - } - - @Override - public String toString() { - return System.identityHashCode(this) + "-" + id; - } - - //-------------------------------------------------------------------------- - //-- Populate methods - //-------------------------------------------------------------------------- - - @Override - public void populateNode(NavBridge<DefaultTreeModel, N> model, - NavDataProvider provider, - boolean populateChilds) { - - // on indique que le noeud n'est plus propre - setDirty(true); - - if (populateChilds) { - - // chargement des fils - populateChilds(model, provider); - } - } - - @Override - @SuppressWarnings({"unchecked"}) - public void populateChilds(NavBridge<DefaultTreeModel, N> bridge, - NavDataProvider provider) { - if (isStaticNode()) { - - if (log.isDebugEnabled()) { - log.debug("is static node " + this); - } - - // noeud static, rien a faire - return; - } - - if (!bridge.canLoadChild((N) this)) { - - // can not load childs - if (log.isDebugEnabled()) { - log.debug("Will Skip populateChilds for node : " + this); - } - return; - } - - // chargement des noeuds fils du noeud courant - try { - if (log.isDebugEnabled()) { - log.debug("Will load childs for " + this); - } - childLoador.loadChilds((NavTreeBridge<N>) bridge, (N) this, provider); - } catch (Exception e) { - throw new RuntimeException(e.getMessage(), e); - } finally { - - // au final, on passe le noeud a l'état chargé - loaded = true; - } - } - - //-------------------------------------------------------------------------- - //-- Overrides to use generic type as return - //-------------------------------------------------------------------------- - - @SuppressWarnings({"unchecked"}) - @Override - public N getParent() { - return (N) super.getParent(); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getRoot() { - return (N) super.getRoot(); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getFirstChild() { - return (N) super.getFirstChild(); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getLastChild() { - return (N) super.getLastChild(); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getChildAfter(TreeNode aChild) { - return (N) super.getChildAfter(aChild); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getChildBefore(TreeNode aChild) { - return (N) super.getChildBefore(aChild); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getNextSibling() { - return (N) super.getNextSibling(); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getPreviousSibling() { - return (N) super.getPreviousSibling(); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getFirstLeaf() { - return (N) super.getFirstLeaf(); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getLastLeaf() { - return (N) super.getLastLeaf(); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getNextLeaf() { - return (N) super.getNextLeaf(); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getPreviousLeaf() { - return (N) super.getPreviousLeaf(); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getNextNode() { - return (N) super.getNextNode(); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getPreviousNode() { - return (N) super.getPreviousNode(); - } - - @SuppressWarnings({"unchecked"}) - public N getSharedAncestor(N aNode) { - return (N) getSharedAncestor((DefaultMutableTreeNode) aNode); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getChildAt(int index) { - return (N) super.getChildAt(index); - } - - @SuppressWarnings({"unchecked"}) - @Override - public Enumeration<N> children() { - return (Enumeration<N>) super.children(); - } - - @Override - public void add(N node) { - super.add(node); - } - - @Override - public void remove(N node) { - super.remove(node); - } - - @Override - public void insert(N node, int position) { - super.insert(node, position); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeNodeChildLoador.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeNodeChildLoador.java deleted file mode 100644 index 30a8da4..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeNodeChildLoador.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav.tree; - -import jaxx.runtime.swing.nav.NavNodeChildLoador; - -import javax.swing.tree.DefaultTreeModel; - -/** - * Implementation for tree of {@link NavNodeChildLoador} - * - * @author Sylvain Lletellier - * @since 2.2 - */ -public abstract class NavTreeNodeChildLoador<T, O, N extends NavTreeNode<N>> extends NavNodeChildLoador<T, O, DefaultTreeModel, NavTreeBridge<N>, N> { - - private static final long serialVersionUID = 1L; - - protected NavTreeNodeChildLoador(Class<O> beanType) { - super(beanType); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableBridge.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableBridge.java deleted file mode 100644 index 4d6fff1..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableBridge.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav.treetable; - -import jaxx.runtime.swing.nav.NavBridge; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.treetable.TreeTableNode; - -import javax.swing.event.TreeModelListener; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.EventListener; -import java.util.List; - -/** - * Delegate model used to switch between tree model and tree table model api - * - * @author Sylvain Lletellier - * @since 2.1 - */ -public class NavTreeTableBridge<N extends NavTreeTableNode<N>> implements NavBridge<NavTreeTableModel, N> { - - /** Logger */ - static private final Log log = LogFactory.getLog(NavTreeTableBridge.class); - - /** bridge model */ - protected NavTreeTableModel model; - - /** bridge ui */ -// protected JXTreeTable ui; - -// public NavTreeTableBridge() { -// if (log.isDebugEnabled()) { -// log.debug("New " + this); -// } -// } - - //-------------------------------------------------------------------------- - //-- Model Queries - //-------------------------------------------------------------------------- - @Override - public NavTreeTableModel getModel() { - return model; - } - - @Override - @SuppressWarnings({"unchecked"}) - public N getRoot() { - return (N) model.getRoot(); - } - - @Override - public boolean isLeaf(Object node) { - return model.isLeaf(node); - } - - @Override - public int getChildCount(Object parent) { - return model.getChildCount(parent); - } - - @Override - @SuppressWarnings({"unchecked"}) - public N getChild(Object parent, int index) { - return (N) model.getChild(parent, index); - } - - @Override - public int getIndexOfChild(Object parent, Object child) { - return model.getIndexOfChild(parent, child); - } - - @Override - public TreeNode[] getPathToRoot(TreeNode aNode) { - return model.getPathToRoot((TreeTableNode) aNode); - } - - //-------------------------------------------------------------------------- - //-- Model modification - //-------------------------------------------------------------------------- - - - @Override - public void setModel(NavTreeTableModel model) { - this.model = model; - } - - @Override - public void setRoot(N node) { - model.setRoot(node); - } - - @Override - public void insertNodeInto(N newChild, N parent, int index) { - parent.insert(newChild, index); - model.getModelSupport().fireChildAdded(getTreePath(parent), index, newChild); - } - - @Override - public void removeNodeFromParent(N node) { - N parent = node.getParent(); - int index = parent.getIndex(node); - if (index == -1) { - throw new IllegalArgumentException("Node " + node + " is not in tree"); - } - parent.remove(node); - -// It's not enougth to fire model support... -// model.getModelSupport().fireChildRemoved(path, index, node); - model.getModelSupport().fireTreeStructureChanged(getTreePath(parent)); - } - - @Override - public void reload(N node) { - model.getModelSupport().fireTreeStructureChanged(getTreePath(node)); - } - - @Override - public boolean canLoadChild(N node) { - return true; - } - - //-------------------------------------------------------------------------- - //-- Listeners notifications - //-------------------------------------------------------------------------- - - @Override - public void valueForPathChanged(TreePath path, Object newValue) { - model.valueForPathChanged(path, newValue); - } - - @Override - public void nodeStructureChanged(TreeNode node) { - model.nodeStructureChanged((NavTreeTableNode<?>) node); - } - - @Override - public void nodeChanged(TreeNode node) { - model.nodeChanged((NavTreeTableNode<?>) node); - } - - @Override - public void nodesChanged(TreeNode node, int[] childIndices) { - // changé par le node en lui meme - NavTreeTableNode<?> tableNode = (NavTreeTableNode<?>) node; - - // Extract children - Object[] children = getChildren(tableNode, childIndices); - - model.getModelSupport().fireChildrenChanged(getTreePath(tableNode), childIndices, children); - } - - @Override - public void nodesWereInserted(N parent, int[] indices) { - // Extract children - Object[] children = getChildren(parent, indices); - - model.getModelSupport().fireChildrenAdded(getTreePath(parent), indices, children); - } - - @Override - public void nodeWereInserted(N parentNode, int index, N node) { - - model.getModelSupport().fireChildAdded(getTreePath(parentNode), index, node); - } - - @Override - public void nodesWereRemoved(TreeNode node, int[] childIndices, - Object[] removedChildren) { - - model.getModelSupport().fireChildrenRemoved(getTreePath(node), - childIndices, - removedChildren); - } - - @Override - @SuppressWarnings({"unchecked"}) - public void notifyChildNodesInserted(N node) { - int count = node.getChildCount(); - if (count < 1) { - if (log.isDebugEnabled()) { - log.debug("Skip for leaf node : " + node); - } - return; - } - if (log.isDebugEnabled()) { - log.debug("Notify for node : " + node + ", " + count + " child(s) inserted."); - } - int[] indices = new int[count]; - for (int i = 0; i < count; i++) { - indices[i] = i; - } - - nodesWereInserted(node, indices); - - // recurse notify on childs - for (Enumeration<? extends NavTreeTableNode<?>> childs = node.children(); - childs.hasMoreElements(); ) { - N child = (N) childs.nextElement(); - notifyChildNodesInserted(child); - } - } - - @Override - public void notifyNodeInserted(N node) { - - N parent = node.getParent(); - if (parent != null) { - int index = parent.getIndex(node); - if (index == -1) { - throw new IllegalArgumentException("Node " + node + " is not in tree"); - } - if (log.isDebugEnabled()) { - log.debug("Notify for node : " + node + ", for parent [" + parent + "] child " + index + " inserted."); - } - nodesWereInserted(parent, new int[]{index}); - notifyChildNodesInserted(node); - } - } - - //-------------------------------------------------------------------------- - //-- TreeModelListener provider - //-------------------------------------------------------------------------- - - - @Override - public void addTreeModelListener(TreeModelListener l) { - model.addTreeModelListener(l); - } - - @Override - public void removeTreeModelListener(TreeModelListener l) { - model.removeTreeModelListener(l); - } - - @Override - public TreeModelListener[] getTreeModelListeners() { - return model.getModelSupport().getTreeModelListeners(); - } - - @Override - @SuppressWarnings({"unchecked"}) - public <T extends EventListener> T[] getListeners(Class<T> listenerType) { - TreeModelListener[] treeModelListeners = getTreeModelListeners(); - List<TreeModelListener> result = new ArrayList<TreeModelListener>(); - for (TreeModelListener listener : treeModelListeners) { - if (listener.getClass().isAssignableFrom(listenerType)) { - result.add(listener); - } - } - return (T[]) result.toArray(); - } - - // Extract children - protected Object[] getChildren(NavTreeTableNode<?> tableNode, int[] childIndices) { - - int size = childIndices.length; - Object[] children = new Object[size]; - for (int i = 0; i < size; i++) { - int index = childIndices[i]; - NavTreeTableNode<?> child = tableNode.getChildAt(index); - children[i] = child; - } - return children; - } - - // Create tree path for node in param - protected TreePath getTreePath(TreeNode node) { - return new TreePath(getPathToRoot(node)); - } - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableHelper.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableHelper.java deleted file mode 100644 index 56ed735..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableHelper.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav.treetable; - -import jaxx.runtime.swing.nav.NavHelper; -import jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.JXTreeTable; - -import javax.swing.event.TreeSelectionListener; -import javax.swing.event.TreeWillExpandListener; -import javax.swing.tree.TreePath; -import javax.swing.tree.TreeSelectionModel; -import java.util.ArrayList; -import java.util.List; - -/** - * The implementation of {@link NavHelper} based on a {@link JXTreeTable} component. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.1 - */ -public class NavTreeTableHelper<N extends NavTreeTableNode<N>> extends NavHelper<NavTreeTableModel, JXTreeTable, NavTreeTableBridge<N>, N> { - - /** Logger */ - static private final Log log = LogFactory.getLog(NavTreeTableHelper.class); - - public NavTreeTableHelper() { - super(new NavTreeTableBridge<N>()); - } - - @Override - public void scrollPathToVisible(TreePath path) { - getUI().scrollPathToVisible(path); - } - - @Override - public void setSelectionPath(TreePath path) { - getUI().getTreeSelectionModel().setSelectionPath(path); - } - - @Override - public void addSelectionPath(TreePath path) { - getUI().getTreeSelectionModel().addSelectionPath(path); - } - - @Override - public void addSelectionPaths(TreePath[] paths) { - getUI().getTreeSelectionModel().addSelectionPaths(paths); - } - - @Override - public void removeSelectionPath(TreePath path) { - getUI().getTreeSelectionModel().removeSelectionPath(path); - } - - @Override - public void removeSelectionPaths(TreePath[] paths) { - getUI().getTreeSelectionModel().removeSelectionPaths(paths); - } - - @Override - public TreeSelectionModel getSelectionModel() { - return getUI().getTreeSelectionModel(); - } - - @Override - public boolean isExpanded(TreePath pathToExpand) { - return getUI().isExpanded(pathToExpand); - } - - @Override - public void expandPath(TreePath pathToExpand) { - getUI().expandPath(pathToExpand); - } - - @Override - public AbstractNavTreeCellRenderer<NavTreeTableModel, N> getTreeCellRenderer() { - //FIXME Implements it if possible - return null; - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getSelectedNode() { - TreePath path = getSelectionModel().getSelectionPath(); - N node = null; - if (path != null) { - node = (N) path.getLastPathComponent(); - } - return node; - } - - @SuppressWarnings({"unchecked"}) - @Override - public List<N> getSelectedNodes() { - JXTreeTable tree = getUI(); - if (tree == null) { - return null; - } - TreePath[] paths = tree.getTreeSelectionModel().getSelectionPaths(); - List<N> nodes = new ArrayList<N>(); - if (paths != null) { - for (TreePath path : paths) { - if (path != null) { - nodes.add((N) path.getLastPathComponent()); - } - } - } - return nodes; - } - - @Override - public void setUI(JXTreeTable tree, - boolean addExpandTreeListener, - boolean addOneClickSelectionListener, - TreeSelectionListener listener, - TreeWillExpandListener willExpandListener) { - setUI(tree); - if (willExpandListener != null) { - tree.addTreeWillExpandListener(willExpandListener); - } - if (addExpandTreeListener) { - tree.addTreeWillExpandListener(expandListener); - } - if (listener != null) { - tree.addTreeSelectionListener(listener); - } - if (addOneClickSelectionListener) { - tree.addTreeSelectionListener(selectionListener); - } - } - - @Override - protected NavTreeTableModel createModel(N node, Object... extraArgs) { - - // must have a single extra params with delegate model - if (extraArgs.length != 1) { - throw new IllegalArgumentException("Should have exactly one extra parameter (delegate model)"); - } - if (!(extraArgs[0] instanceof NavTreeTableModel.MyDefaultTreeTableModel)) { - throw new IllegalArgumentException("extra parameter is not instance of " + NavTreeTableModel.MyDefaultTreeTableModel.class.getName()); - } - NavTreeTableModel.MyDefaultTreeTableModel delegate = (NavTreeTableModel.MyDefaultTreeTableModel) extraArgs[0]; - NavTreeTableBridge<N> bridge = getBridge(); - NavTreeTableModel model = bridge.getModel(); - if (model == null) { - model = new NavTreeTableModel(delegate); - bridge.setModel(model); -// model = new NavTreeTableBridge(tableModel); - bridge.addTreeModelListener(treeModelListener); -// ((NavTreeTableModel) model).addTreeModelListener(treeModelListener); - } - bridge.setRoot(node); - - // notify structure has changed - bridge.nodeStructureChanged(getRootNode()); - return model; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableModel.java deleted file mode 100644 index 73c7464..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableModel.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav.treetable; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.tree.TreeModelSupport; -import org.jdesktop.swingx.treetable.DefaultTreeTableModel; -import org.jdesktop.swingx.treetable.TreeTableModel; -import org.jdesktop.swingx.treetable.TreeTableNode; - -import javax.swing.event.TreeModelListener; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; - -/** - * Model of the tree table used for a jaxx tree table api. - * - * @author Sylvain Lletellier - * @since 2.2 - */ -public class NavTreeTableModel implements TreeTableModel { - - /** Logger */ - static private final Log log = LogFactory.getLog(NavTreeTableModel.class); - - /** - * Hack to acces to the modelSupport - * - * @author sletellier - * @since 2.2 - */ - public static abstract class MyDefaultTreeTableModel extends DefaultTreeTableModel { - - public TreeModelSupport getModelSupport() { - return modelSupport; - } - - public abstract String[] getColumnsNames(); - - } - - /** the delegate model */ - protected MyDefaultTreeTableModel delegate; - - public NavTreeTableModel(MyDefaultTreeTableModel delegate) { - this.delegate = delegate; - } - - @SuppressWarnings({"SuspiciousSystemArraycopy"}) - public TreeTableNode[] getPathToRoot(TreeTableNode aNode) { - if (aNode == null) { - return null; - } - TreeNode[] treeNodes = getDelegate().getPathToRoot(aNode); - NavTreeTableNode<?>[] result = new NavTreeTableNode[treeNodes.length]; - System.arraycopy(treeNodes, 0, result, 0, treeNodes.length); - return result; - } - - public void nodeStructureChanged(NavTreeTableNode<?> node) { - if (node != null) { - NavTreeTableNode<?> parentNode = node.getParent(); - if (parentNode == null || parentNode.isRoot()) { - getModelSupport().fireNewRoot(); - } else { - TreeNode[] treeNodes = getPathToRoot(parentNode); - if (treeNodes != null) { - getModelSupport().fireTreeStructureChanged(new TreePath(treeNodes)); - } - // FIXME : it's append.... -// else { -// log.error("[Node structure changed] Path to root is null !"); -// } - } - } else { - log.error("Node is null !"); - } - } - - public void nodeChanged(NavTreeTableNode<?> node) { - if (node != null) { - NavTreeTableNode<?> parent = node.getParent(); - TreeNode[] treeNodes = getPathToRoot(parent); - if (treeNodes != null) { - getModelSupport().fireChildChanged( - new TreePath(treeNodes), parent.getIndex(node), node); - // FIXME : it's append.... -// else { -// log.error("[Node changed] Path to root is null !"); -// } - } - } else { - log.error("Node is null !"); - } - } - - public MyDefaultTreeTableModel getDelegate() { - return delegate; - } - - public TreeModelSupport getModelSupport() { - return delegate.getModelSupport(); - } - - public String[] getColomnsNames() { - return delegate.getColumnsNames(); - } - - public void setRoot(TreeTableNode root) { - delegate.setRoot(root); - } - - //-------------------------------------------------------------------------- - //-- Overrides delegate methode - //-------------------------------------------------------------------------- - - @Override - public TreeTableNode getRoot() { - return delegate.getRoot(); - } - - @Override - public Object getChild(Object parent, int index) { - return delegate.getChild(parent, index); - } - - @Override - public int getChildCount(Object parent) { - return delegate.getChildCount(parent); - } - - @Override - public boolean isLeaf(Object node) { - return delegate.isLeaf(node); - } - - @Override - public void valueForPathChanged(TreePath path, Object newValue) { - delegate.valueForPathChanged(path, newValue); - } - - @Override - public int getIndexOfChild(Object parent, Object child) { - return delegate.getIndexOfChild(parent, child); - } - - @Override - public void addTreeModelListener(TreeModelListener l) { - delegate.addTreeModelListener(l); - } - - @Override - public void removeTreeModelListener(TreeModelListener l) { - delegate.removeTreeModelListener(l); - } - - @Override - public Class<?> getColumnClass(int i) { - return getDelegate().getColumnClass(i); - } - - @Override - public int getColumnCount() { - return getColomnsNames().length; - } - - @Override - public String getColumnName(int column) { - return getColomnsNames()[column]; - } - - @Override - public int getHierarchicalColumn() { - return getDelegate().getHierarchicalColumn(); - } - - @Override - public Object getValueAt(Object o, int i) { - return getDelegate().getValueAt(o, i); - } - - @Override - public boolean isCellEditable(Object o, int i) { - return getDelegate().isCellEditable(o, i); - } - - @Override - public void setValueAt(Object o, Object o1, int i) { - getDelegate().setValueAt(o, o1, i); - } - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableNode.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableNode.java deleted file mode 100644 index 949f564..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableNode.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav.treetable; - -import jaxx.runtime.swing.nav.NavBridge; -import jaxx.runtime.swing.nav.NavDataProvider; -import jaxx.runtime.swing.nav.NavNode; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.JXTreeTable; -import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode; -import org.jdesktop.swingx.treetable.MutableTreeTableNode; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; - -/** - * Implementation of {@link NavNode} used to create in tree table - * This node extends {@link DefaultMutableTreeTableNode} used by - * {@link JXTreeTable} - * - * @author Sylvain Lletellier - * @since 2.2 - */ -public class NavTreeTableNode<N extends NavTreeTableNode<N>> extends DefaultMutableTreeTableNode implements NavNode<NavTreeTableModel, N> { - - /** Logger */ - static private final Log log = LogFactory.getLog(NavNode.class); - - private static final long serialVersionUID = 1L; - - /** Type of data associated with the node */ - protected final Class<?> internalClass; - - /** - * Optinal context to distinguish different nodes with same - * {@link #internalClass}. - */ - protected final String context; - - /** Id of the data associated with the node. */ - protected final String id; - - /** Flag to know when renderer should (re-)compute render of the node. */ - protected boolean dirty = true; - - /** Flag to know when the none static node was loaded. */ - protected boolean loaded; - - /** Optional child loador to lazy create childs of the node. */ - protected final NavTreeTableNodeChildLoador<?, ?, N> childLoador; - - protected NavTreeTableNode(String id) { - this(String.class, id, null, null); - } - - public NavTreeTableNode(Class<?> internalClass, - String id, - String context, - NavTreeTableNodeChildLoador<?, ?, N> childLoador) { - this.internalClass = internalClass; - this.id = id; - this.context = context; - this.childLoador = childLoador; - if (isStaticNode()) { - - // A static node is always full loaded - loaded = true; - } - if (log.isDebugEnabled()) { - log.debug("new node : " + this); - } - } - - @Override - public String getId() { - return id; - } - - @Override - public String getContext() { - return context; - } - - @Override - public Class<?> getInternalClass() { - return internalClass; - } - - @Override - public boolean isLoaded() { - return loaded; - } - - @Override - public boolean isDirty() { - return dirty; - } - - @Override - public boolean isStringNode() { - return String.class.equals(internalClass); - } - - @Override - public boolean isStaticNode() { - return childLoador == null; - } - - @Override - @SuppressWarnings({"unchecked"}) - public N getContainerNode() { - if (isRoot()) { - // si on arrive sur le root, quelque chose ne va pas, - // on bloque par null, a defaut de declancher une exception - return null; - } - - if (isStringNode()) { - // on est sur un noeud de type String, donc on regarde sur le parent - return getParent().getContainerNode(); - } - - // cas final : sur un noeud de donnee + classe interne de donnee - return (N) this; - } - - public boolean isRoot() { - return getParent() == null; - } - - @Override - @SuppressWarnings({"unchecked"}) - public N findNodeById(String id, - NavBridge<NavTreeTableModel, N> model, - NavDataProvider provider) { - if (id == null) { - - // id null ? donc rien a faire - return null; - } - if (id.equals(getId())) { - - // on a trouve le bon noeud - return (N) this; - } - - if (!isLoaded()) { - - // il faut charger les fils du noeud pour effectuer la recherche - populateChilds(model, provider); - } - - if (isLeaf()) { - - // au final le noeud est une feuille, donc ne convient pas - return null; - } - - // on recherche dans les fils - Enumeration<N> enumeration = children(); - while (enumeration.hasMoreElements()) { - N node = enumeration.nextElement(); - N nodeById = node.findNodeById(id, model, provider); - if (nodeById != null) { - return nodeById; - } - } - - // aucun des noeud fils ne convient - return null; - } - - @Override - public N getChild(String id, - NavBridge<NavTreeTableModel, N> bridge, - NavDataProvider provider) { - - if (id == null) { - - // id null ? donc rien a faire - return null; - } - - if (!isLoaded()) { - - // il faut charger les fils du noeud pour effectuer la recherche - populateChilds(bridge, provider); - } - - if (isLeaf()) { - - // au final le noeud est une feuille, donc ne convient pas - return null; - } - - // on recherche dans les fils - Enumeration<N> enumeration = children(); - while (enumeration.hasMoreElements()) { - N node = enumeration.nextElement(); - if (id.equals(node.getId())) { - return node; - } - } - - // aucun des noeud fils ne convient - return null; - } - - @Override - public void setDirty(boolean dirty) { - this.dirty = dirty; - } - - @Override - public boolean isLeaf() { - // there is two behaviours for the test : - // 1 - when the node is static, then can directly use his number of child - // to determine if node is a leaf (no child) - // 2 - when the node is dynamic, then ALWAYS says the node is NOT a leaf until - // it was loaded, otherwise the WillExpand listener will not load the childs... - // Once the node is loaded, use back the normal behaviour (count number of childs) - return isStaticNode() ? super.isLeaf() : isLoaded() && getChildCount() == 0; - } - - @Override - public Object getUserObject() { - return id; - } - - @Override - public String toString() { - return System.identityHashCode(this) + "-" + id; - } - - //-------------------------------------------------------------------------- - //-- Populate methods - //-------------------------------------------------------------------------- - - @Override - public void populateNode(NavBridge<NavTreeTableModel, N> model, - NavDataProvider provider, - boolean populateChilds) { - - // on indique que le noeud n'est plus propre - setDirty(true); - - if (populateChilds) { - - // chargement des fils - populateChilds(model, provider); - } - } - - @Override - @SuppressWarnings({"unchecked"}) - public void populateChilds(NavBridge<NavTreeTableModel, N> bridge, - NavDataProvider provider) { - if (isStaticNode()) { - - // noeud static, rien a faire - return; - } - - if (!bridge.canLoadChild((N) this)) { - - // can not load childs - if (log.isDebugEnabled()) { - log.debug("Will Skip populateChilds for node : " + this); - } - return; - } - - // chargement des noeuds fils du noeud courant - try { - if (log.isDebugEnabled()) { - log.debug("Will load childs for " + this); - } - childLoador.loadChilds((NavTreeTableBridge<N>) bridge, (N) this, provider); - } catch (Exception e) { - throw new RuntimeException(e.getMessage(), e); - } finally { - - // au final, on passe le noeud a l'état chargé - loaded = true; - } - } - - //-------------------------------------------------------------------------- - //-- Overrides to use generic type as return - //-------------------------------------------------------------------------- - - @SuppressWarnings({"unchecked"}) - @Override - public N getParent() { - return (N) super.getParent(); - } - - @SuppressWarnings({"unchecked"}) - @Override - public N getChildAt(int index) { - return (N) super.getChildAt(index); - } - - // It's a hack to prevent concurent modification exception, caused by - // children() of AbstractMutableTreeTableNode return Collections.enumeration - @SuppressWarnings({"unchecked"}) - @Override - public Enumeration<N> children() { - List<? extends MutableTreeTableNode> newChildrenList = - new ArrayList<MutableTreeTableNode>(children); - - return (Enumeration<N>) Collections.enumeration(newChildrenList); - } - - public void removeAllChildren() { - children.clear(); - } - - @Override - public void add(N node) { - super.add(node); - } - - @SuppressWarnings({"unchecked"}) - public N[] getPathToRoot(NavTreeTableNode aNode, int depth) { - - NavTreeTableNode[] retNodes; - - /* Check for null, in case someone passed in a null node, or - they passed in an element that isn't rooted at root. */ - if (aNode == null) { - if (depth == 0) { - return null; - } else { - retNodes = new NavTreeTableNode[depth]; - } - } else { - depth++; - retNodes = getPathToRoot(aNode.getParent(), depth); - retNodes[retNodes.length - depth] = aNode; - } - return (N[]) retNodes; - } - - @Override - public void remove(N node) { - super.remove(node); - } - - @Override - public void insert(N node, int position) { - super.insert(node, position); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableNodeChildLoador.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableNodeChildLoador.java deleted file mode 100644 index 5ec9afb..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableNodeChildLoador.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.nav.treetable; - -import jaxx.runtime.swing.nav.NavNodeChildLoador; - -/** - * Implementation for tree table of {@link NavNodeChildLoador} - * - * @author Sylvain Lletellier - * @since 2.2 - */ -public abstract class NavTreeTableNodeChildLoador<T, O, N extends NavTreeTableNode<N>> extends NavNodeChildLoador<T, O, NavTreeTableModel, NavTreeTableBridge<N>, N> { - - private static final long serialVersionUID = 1L; - - protected NavTreeTableNodeChildLoador(Class<O> beanType) { - super(beanType); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/BooleanCellRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/BooleanCellRenderer.java deleted file mode 100644 index e62383e..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/BooleanCellRenderer.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.renderer; - -import com.google.common.base.Predicate; - -import javax.swing.Icon; -import javax.swing.JCheckBox; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTable; -import javax.swing.table.TableCellRenderer; -import java.awt.Color; -import java.awt.Component; - -/** - * @author Tony Chemit - chemit@codelutin.com - * @since 1.5 - */ -public class BooleanCellRenderer extends JPanel implements TableCellRenderer { - - private static final long serialVersionUID = 1L; - - protected final TableCellRenderer defaultDelegate; - - protected final JCheckBox checkBox; - - private final Predicate predicate; - - private static final Predicate<Object> DEFAULT_PREDICATE = new Predicate<Object>() { - @Override - public boolean apply(Object input) { - return (input != null && (Boolean) input); - } - }; - - public BooleanCellRenderer(TableCellRenderer delegate, Predicate<?> predicate) { - this(delegate, new JCheckBox(), predicate); - } - - public BooleanCellRenderer(TableCellRenderer delegate) { - //super(new BorderLayout()); - this(delegate, DEFAULT_PREDICATE); - - } - - public BooleanCellRenderer(TableCellRenderer delegate, Icon icon, Predicate<?> predicate) { - this(delegate, new JCheckBox(icon), predicate); - } - - public BooleanCellRenderer(TableCellRenderer delegate, Icon icon) { - //super(new BorderLayout()); - this(delegate, icon, DEFAULT_PREDICATE); - checkBox.setVerticalTextPosition(JLabel.TOP); - - } - - public BooleanCellRenderer(TableCellRenderer delegate, JCheckBox checkBox, Predicate<?> predicate) { - this.defaultDelegate = delegate; - this.predicate = predicate; - this.checkBox = checkBox; - this.checkBox.setBorderPainted(true); - this.checkBox.setHorizontalAlignment(JLabel.CENTER); - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - ((JComponent) defaultDelegate).setBackground(null); - JComponent render = (JComponent) defaultDelegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - if (isSelected) { - setForeground(table.getSelectionForeground()); - setBackground(table.getSelectionBackground()); - } else { - setForeground(render.getForeground()); - setBackground(render.getBackground()); - //fixme make this works... and remove the test - if (row % 2 == 1) { - setBackground(Color.WHITE); - } - } - - boolean selectCheckBox = predicate.apply(value); - checkBox.setSelected(selectCheckBox); - - setBorder(render.getBorder()); - return checkBox; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/ClassTableCellRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/ClassTableCellRenderer.java deleted file mode 100644 index f902461..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/ClassTableCellRenderer.java +++ /dev/null @@ -1,58 +0,0 @@ -package jaxx.runtime.swing.renderer; -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import javax.swing.JTable; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableCellRenderer; -import java.awt.Component; - -/** - * Table cell renderer for a {@link Class} - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.4 - */ -public class ClassTableCellRenderer implements TableCellRenderer { - - protected final TableCellRenderer defaultDelegate; - - public ClassTableCellRenderer() { - this.defaultDelegate = new DefaultTableCellRenderer(); - } - - public ClassTableCellRenderer(TableCellRenderer defaultDelegate) { - this.defaultDelegate = defaultDelegate; - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - - return defaultDelegate.getTableCellRendererComponent( - table, - value == null ? null : ((Class<?>) value).getName(), - isSelected, - hasFocus, - row, - column); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/ColorCellRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/ColorCellRenderer.java deleted file mode 100644 index 0a40211..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/ColorCellRenderer.java +++ /dev/null @@ -1,50 +0,0 @@ -package jaxx.runtime.swing.renderer; -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import javax.swing.JButton; -import javax.swing.JTable; -import javax.swing.table.TableCellRenderer; -import java.awt.Color; -import java.awt.Component; - -/** - * Date: 31/07/12 - * - * @author Matthieu Allon - * @since 2.5.4 - */ -public class ColorCellRenderer implements TableCellRenderer { - - protected JButton button = new JButton(); - - @Override - public Component getTableCellRendererComponent(JTable table, - Object value, - boolean isSelected, - boolean hasFocus, - int row, - int column) { - button.setBackground((Color) value); - return button; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorListCellRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorListCellRenderer.java deleted file mode 100644 index e29b052..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorListCellRenderer.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.renderer; - -import org.nuiton.decorator.Decorator; - -import javax.swing.DefaultListCellRenderer; -import javax.swing.JList; -import javax.swing.ListCellRenderer; -import java.awt.Component; - -/** - * A {@link ListCellRenderer} which compute text with the given {@link #decorator} - * and leave the hand to the {@link #delegate} to perform the visual renderer. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.7.2 - */ -public class DecoratorListCellRenderer implements ListCellRenderer { - - /** Delegate cell renderer */ - protected ListCellRenderer delegate; - - /** Decorator to produce text to render */ - protected Decorator<?> decorator; - - public DecoratorListCellRenderer(Decorator<?> decorator) { - this(new DefaultListCellRenderer(), decorator); - } - - public DecoratorListCellRenderer(ListCellRenderer delegate, - Decorator<?> decorator) { - this.delegate = delegate; - this.decorator = decorator; - } - - @Override - public Component getListCellRendererComponent(JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) { - value = decorateValue(value, index); - return delegate.getListCellRendererComponent(list, - value, - index, - isSelected, - cellHasFocus - ); - } - - protected Object decorateValue(Object value,int index) { - if (value == null) { - value = " "; - } - if (!(value instanceof String) && decorator != null) { - value = decorator.toString(value); - } - return value; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorProviderListCellRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorProviderListCellRenderer.java deleted file mode 100644 index 38e1c93..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorProviderListCellRenderer.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.renderer; - -import org.nuiton.decorator.Decorator; -import org.nuiton.decorator.DecoratorProvider; - -import javax.swing.DefaultListCellRenderer; -import javax.swing.JList; -import javax.swing.ListCellRenderer; -import java.awt.Component; - -/** - * A {@link ListCellRenderer} which use decorators from the {@link #provider} to obtain the text to display. - * - * The interest of this renderer is to define a unique renderer for your application (put it in JAXXContext) - * and then use it simply :) - * - * User: chemit - * Date: 29 oct. 2009 - * Time: 03:00:53 - * - * @see DecoratorProvider - * @since 2.0.0 - */ -public class DecoratorProviderListCellRenderer implements ListCellRenderer { - - /** Delegate cell renderer */ - protected ListCellRenderer delegate; - - /** provider of decorators */ - protected DecoratorProvider provider; - - public DecoratorProviderListCellRenderer(DecoratorProvider provider) { - this(new DefaultListCellRenderer(), provider); - } - - public DecoratorProviderListCellRenderer(ListCellRenderer delegate, DecoratorProvider provider) { - this.delegate = delegate; - this.provider = provider; - } - - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - if (value != null) { - Decorator<?> decorator = provider.getDecorator(value); - - if (decorator != null) { - value = decorator.toString(value); - } - } else { - value = " "; - } - return delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorProviderTableCellRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorProviderTableCellRenderer.java deleted file mode 100644 index 318a920..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorProviderTableCellRenderer.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.renderer; - -import org.nuiton.decorator.Decorator; -import org.nuiton.decorator.DecoratorProvider; - -import javax.swing.JTable; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableCellRenderer; -import java.awt.Component; - -/** - * A {@link TableCellRenderer} which use decorators from the {@link #provider} to obtain the text to display. - * - * The interest of this renderer is to define a unique renderer for your application (put it in JAXXContext) - * and then use it simply :) - * - * User: chemit - * Date: 29 oct. 2009 - * Time: 03:00:53 - * - * @see DecoratorProvider - * @since 2.0.0 - */ -public class DecoratorProviderTableCellRenderer implements TableCellRenderer { - - /** Delegate cell renderer */ - protected TableCellRenderer delegate; - - /** provider of decorators */ - protected DecoratorProvider provider; - - public DecoratorProviderTableCellRenderer(DecoratorProvider provider) { - this(new DefaultTableCellRenderer(), provider); - } - - public DecoratorProviderTableCellRenderer(TableCellRenderer delegate, DecoratorProvider provider) { - this.delegate = delegate; - this.provider = provider; - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasfocus, int row, int column) { - if (value != null) { - Decorator<?> decorator = provider.getDecorator(value); - - if (decorator != null) { - value = decorator.toString(value); - } - } - return delegate.getTableCellRendererComponent(table, value, isSelected, hasfocus, row, column); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorTableCellRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorTableCellRenderer.java deleted file mode 100644 index 9ce0d53..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorTableCellRenderer.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.renderer; - -import org.nuiton.decorator.Decorator; - -import javax.swing.JTable; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableCellRenderer; -import java.awt.Component; -import javax.swing.JComponent; - -/** - * A {@link TableCellRenderer} which compute text with the given {@link #decorator} - * and leave the hand to the {@link #delegate} to perform the visual renderer. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.7.2 (was previously {@code jaxx.runtime.swing.DecoratorTableCellRenderer}). - */ -public class DecoratorTableCellRenderer implements TableCellRenderer { - - /** Delegate cell renderer */ - protected TableCellRenderer delegate; - - /** Decorator to produce text to render */ - protected Decorator<?> decorator; - - protected boolean showToolTipText = false; - - public DecoratorTableCellRenderer(Decorator<?> decorator) { - this(new DefaultTableCellRenderer(), decorator, false); - } - - public DecoratorTableCellRenderer(Decorator<?> decorator, boolean showToolTipText) { - this(new DefaultTableCellRenderer(), decorator, showToolTipText); - } - - public DecoratorTableCellRenderer(TableCellRenderer delegate, Decorator<?> decorator) { - this(new DefaultTableCellRenderer(), decorator, false); - } - - public DecoratorTableCellRenderer(TableCellRenderer delegate, - Decorator<?> decorator, - boolean showToolTipText) { - this.delegate = delegate; - this.decorator = decorator; - this.showToolTipText = showToolTipText; - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasfocus, int row, int column) { - String text = null; - if (value != null) { - text = decorator.toString(value); - } - JComponent result = - (JComponent) delegate.getTableCellRendererComponent(table, - text, - isSelected, - hasfocus, - row, - column); - if (showToolTipText) { - result.setToolTipText(text); - } - return result; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EmptyNumberTableCellRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EmptyNumberTableCellRenderer.java deleted file mode 100644 index e7e58c9..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EmptyNumberTableCellRenderer.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.renderer; - -import javax.swing.JTable; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableCellRenderer; -import java.awt.Component; - -/** - * A {@link TableCellRenderer} which does not display numbers when they are - * equals to 0. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.5 - */ -public class EmptyNumberTableCellRenderer implements TableCellRenderer { - - protected final Integer ZERO = 0; - - protected final Float ZEROF = 0F; - - protected final Double ZEROD = 0D; - - private TableCellRenderer delegate; - - public EmptyNumberTableCellRenderer() { - this(new DefaultTableCellRenderer()); - } - - public EmptyNumberTableCellRenderer(TableCellRenderer delegate) { - this.delegate = delegate; - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - if (value == null || ZERO.equals(value) || ZEROF.equals(value) || ZEROD.equals(value)) { - value = null; - } - return delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EnumEditorRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EnumEditorRenderer.java deleted file mode 100644 index 656447b..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EnumEditorRenderer.java +++ /dev/null @@ -1,53 +0,0 @@ -package jaxx.runtime.swing.renderer; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2016 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.collect.ImmutableMap; - -import javax.swing.DefaultListCellRenderer; -import javax.swing.JList; -import java.awt.Component; - -/** - * Created on 08/03/16. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class EnumEditorRenderer<E extends Enum<E>> extends DefaultListCellRenderer { - private static final long serialVersionUID = 1L; - - private final ImmutableMap<E, String> labels; - - public EnumEditorRenderer(ImmutableMap<E, String> labels) { - this.labels = labels; - } - - @Override - public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - - if (value != null) { - value = labels.get((E) value); - } - return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EnumTableCellRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EnumTableCellRenderer.java deleted file mode 100644 index 9fc1c10..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EnumTableCellRenderer.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.renderer; - -import javax.swing.JTable; -import javax.swing.table.TableCellRenderer; -import java.awt.Component; -import java.util.EnumSet; - -/** - * A {@link TableCellRenderer} which displays enum values from their ordinal value. - * - * @param <E> le type de l'énumération. - * @author Tony Chemit - chemit@codelutin.com - * @since 1.5 - */ -public class EnumTableCellRenderer<E extends Enum<E>> implements TableCellRenderer { - - private TableCellRenderer delegate; - - private EnumSet<E> enumValues; - - public EnumTableCellRenderer(TableCellRenderer delegate, Class<E> enumClass) { - this.delegate = delegate; - this.enumValues = EnumSet.allOf(enumClass); - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - - if (value != null) { - //FIXME : should be also able to read it by name ? - Integer ordinal = Integer.valueOf(value + ""); - if (ordinal == -1) { - value = null; - } else { - for (E enumValue : enumValues) { - if (ordinal == enumValue.ordinal()) { - value = enumValue; - break; - } - } - } - } - return delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/FilteredDecoratorListCellRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/FilteredDecoratorListCellRenderer.java deleted file mode 100644 index 8770d45..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/FilteredDecoratorListCellRenderer.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.renderer; - -import java.awt.Component; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.swing.JList; -import javax.swing.ListCellRenderer; -import org.apache.commons.lang3.StringUtils; -import org.nuiton.decorator.Decorator; - -/** - * A {@link ListCellRenderer} which compute text with the given {@link #decorator}, - * highlights a part of the rendered text, - * and leave the hand to the {@link #delegate} to perform the visual renderer. - * - * @author Kevin Morin - morin@codelutin.com - * @since 2.5.11 - */ -public class FilteredDecoratorListCellRenderer extends DecoratorListCellRenderer { - - /** text to highlight */ - protected String filterText; - - protected Pattern pattern; - - protected boolean highlightFilterText = false; - - public FilteredDecoratorListCellRenderer(Decorator<?> decorator) { - super(decorator); - } - - public FilteredDecoratorListCellRenderer(ListCellRenderer delegate, - Decorator<?> decorator) { - super(delegate, decorator); - } - - public FilteredDecoratorListCellRenderer(ListCellRenderer delegate, - Decorator<?> decorator, - boolean highlightFilterText) { - super(delegate, decorator); - this.highlightFilterText = highlightFilterText; - } - - public String getFilterText() { - return filterText; - } - - public void setFilterText(String filterText) { - this.filterText = filterText; - computePattern(); - } - - public boolean isHighlightFilterText() { - return highlightFilterText; - } - - public void setHighlightFilterText(boolean highlightFilterText) { - this.highlightFilterText = highlightFilterText; - computePattern(); - } - - @Override - public Component getListCellRendererComponent(JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) { - - if (!(value instanceof String) && decorator != null) { - value = decorator.toString(value); - } - - String stringValue = String.valueOf(value); - if (pattern != null) { - Matcher matcher = pattern.matcher(stringValue); - if (matcher.find()) { - // for each group caught, add the text between the previous group - // and the current group and surround the group with the highlighter - StringBuilder sb = new StringBuilder(); - int i = 0; - for (int g = 1 ; g <= matcher.groupCount() ; g++) { - String match = matcher.group(g); - int indexOfMatch = stringValue.indexOf(match, i); - sb.append(stringValue.substring(i, indexOfMatch)) - .append("<span style='background:#FFFF00'>") - .append(match) - .append("</span>"); - i = indexOfMatch + match.length(); - } - sb.append(stringValue.substring(i)); - stringValue = "<html>" + sb.toString() + "</html>"; - } - } - return delegate.getListCellRendererComponent(list, - stringValue, - index, - isSelected, - cellHasFocus - ); - } - - protected void computePattern() { - if (highlightFilterText - && !StringUtils.isEmpty(StringUtils.remove(filterText, '*'))) { - // add the groups in the pattern - String patternText = "(" + filterText.replace("*", ").*(") + ").*"; - patternText = StringUtils.remove(patternText, "()"); - pattern = Pattern.compile(patternText, Pattern.CASE_INSENSITIVE); - - } else { - pattern = null; - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/I18nTableCellRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/I18nTableCellRenderer.java deleted file mode 100644 index 1a187b4..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/I18nTableCellRenderer.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.renderer; - -import javax.swing.JComponent; -import javax.swing.JTable; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; -import java.awt.Component; - -import static org.nuiton.i18n.I18n.t; - -/** - * A simple TableCellRenderer using a delegate TableCellRenderer to render - * everything elese thant the text : the text is I18nalize. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class I18nTableCellRenderer implements TableCellRenderer { - - /** i18n keys of libelles to display */ - protected final String[] keys; - - /** i18n keys of toolTipTexts to display */ - protected final String[] tips; - - /** the delegate cell renderer */ - protected TableCellRenderer delegate; - - public I18nTableCellRenderer(TableCellRenderer delegate, - String... keysAndTips) { - this.delegate = delegate; - if (keysAndTips.length == 0) { - throw new IllegalArgumentException( - "can not have empty keysAndTips parameters (means no " + - "column ?)"); - } - if (keysAndTips.length % 2 == 1) { - throw new IllegalArgumentException( - "must have some couple (text,tooltTipText), but had an" + - " even number of data in keysAndTips parameter"); - } - int size = keysAndTips.length / 2; - keys = new String[size]; - tips = new String[size]; - for (int i = 0; i < size; i++) { - keys[i] = keysAndTips[2 * i]; - tips[i] = keysAndTips[2 * i + 1]; - } - } - - @Override - public Component getTableCellRendererComponent(JTable table, - Object value, - boolean isSelected, - boolean hasfocus, - int row, - int column) { - if (column > keys.length) { - throw new IndexOutOfBoundsException( - "colum can not be greater than " + keys.length); - } - TableColumn col = table.getColumn(table.getColumnName(column)); - int index = col.getModelIndex(); - value = t(keys[index]); - JComponent rendererComponent = (JComponent) - delegate.getTableCellRendererComponent( - table, - value, - isSelected, - hasfocus, - row, - column - ); - rendererComponent.setToolTipText(t(tips[index])); - return rendererComponent; - } - - public String[] getKeys() { - return keys; - } - - public String[] getTips() { - return tips; - } - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/LocaleListCellRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/LocaleListCellRenderer.java deleted file mode 100644 index f0853e0..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/LocaleListCellRenderer.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.renderer; - -import jaxx.runtime.SwingUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.DefaultListCellRenderer; -import javax.swing.Icon; -import javax.swing.JLabel; -import javax.swing.JList; -import java.awt.Component; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -/** @author Tony Chemit - chemit@codelutin.com */ -public class LocaleListCellRenderer extends DefaultListCellRenderer { - - public static final Log log = LogFactory.getLog(LocaleListCellRenderer.class); - - private static final long serialVersionUID = 1L; - - protected final Map<Locale, Icon> cache = new HashMap<Locale, Icon>(); - - protected boolean showIcon; - - protected boolean showText; - - public LocaleListCellRenderer() { - this(true, true); - } - - public LocaleListCellRenderer(boolean showIcon, boolean showText) { - this.showIcon = showIcon; - this.showText = showText; - } - - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - JLabel comp = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - Locale locale = (Locale) value; - if (locale != null) { - Icon icon = getIcon(locale); - comp.setIcon(icon); - } - String text = getText(locale); - String tip = getToolTipText(locale); - comp.setText(text); - comp.setToolTipText(tip); - return comp; - } - - public String getText(Locale locale) { - String text = null; - if (showText) { - text = getSafeText(locale); - } - return text; - } - - public Icon getIcon(Locale locale) { - if (!showIcon) { - return null; - } - synchronized (cache) { - return getSafeIcon(locale); - } - } - - public String getToolTipText(Locale locale) { - return locale.getDisplayName(Locale.getDefault()); - } - - public boolean isShowText() { - return showText; - } - - public boolean isShowIcon() { - return showIcon; - } - - public void setShowIcon(boolean showIcon) { - boolean old = this.showIcon; - this.showIcon = showIcon; - firePropertyChange("showIcon", old, showIcon); - } - - public void setShowText(boolean showText) { - boolean old = this.showText; - this.showText = showText; - firePropertyChange("showText", old, showText); - } - - public String getSafeText(Locale locale) { - return locale.getDisplayName(Locale.getDefault()); - } - - public synchronized Icon getSafeIcon(Locale locale) { - Icon icon = cache.get(locale); - if (icon != null) { - return icon; - } - - icon = SwingUtil.getUIManagerActionIcon("i18n-" + locale.toString()); - - if (icon == null) { - log.warn("could not find icon action.i18n-" + locale.toString()); - if (locale.getCountry() != null) { - icon = SwingUtil.getUIManagerActionIcon("i18n-" + locale.getCountry().toLowerCase()); - if (icon == null) { - log.warn("could not find icon action.i18n-" + locale.getCountry().toLowerCase()); - - icon = SwingUtil.createActionIcon("i18n-" + locale.getCountry().toLowerCase()); - if (icon == null) { - log.warn("could not find icon action.i18n-" + locale.getCountry().toLowerCase()); - } - } - - } - } - - cache.put(locale, icon); - return icon; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/MultiDecoratorListCellRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/MultiDecoratorListCellRenderer.java deleted file mode 100644 index 49a5c0c..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/MultiDecoratorListCellRenderer.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.renderer; - -import org.nuiton.decorator.Decorator; -import org.nuiton.decorator.JXPathDecorator; - -import javax.swing.DefaultListCellRenderer; -import javax.swing.JList; -import javax.swing.ListCellRenderer; -import java.awt.Component; -import java.util.ArrayList; -import java.util.List; - -/** - * A {@link ListCellRenderer} which compute text with the matching decorator - * from {@link #decorators} and leave the hand to the {@link #delegate} to - * perform the visual renderer. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.0 - */ -public class MultiDecoratorListCellRenderer implements ListCellRenderer { - - /** Delegate cell renderer */ - protected ListCellRenderer delegate; - - /** accepted types */ - protected List<Class<?>> types; - - /** decorators for accepted types */ - protected Decorator<?>[] decorators; - - public MultiDecoratorListCellRenderer(ListCellRenderer delegate, JXPathDecorator<?>... decorator) { - this.delegate = delegate; - this.types = new ArrayList<Class<?>>(); - List<Decorator<?>> tmp = new ArrayList<Decorator<?>>(); - for (JXPathDecorator<?> d : decorator) { - if (types.contains(d.getType())) { - throw new IllegalArgumentException("can not have twice a decorator of type " + d.getType()); - } - types.add(d.getType()); - tmp.add(d); - } - decorators = tmp.toArray(new Decorator<?>[tmp.size()]); - } - - public MultiDecoratorListCellRenderer(JXPathDecorator<?>... decorator) { - this(new DefaultListCellRenderer(), decorator); - } - - @Override - public Component getListCellRendererComponent(JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) { - if (value != null) { - int i = types.indexOf(value.getClass()); - if (i != -1) { - Decorator<?> d = decorators[i]; - value = d.toString(value); - } - } - return delegate.getListCellRendererComponent( - list, value, index, isSelected, cellHasFocus); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/MultiDecoratorTableCelleRenderer.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/MultiDecoratorTableCelleRenderer.java deleted file mode 100644 index be63ebc..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/MultiDecoratorTableCelleRenderer.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.renderer; - -import org.nuiton.decorator.Decorator; -import org.nuiton.decorator.JXPathDecorator; - -import javax.swing.JTable; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableCellRenderer; -import java.awt.Component; -import java.util.ArrayList; -import java.util.List; - -/** - * A {@link TableCellRenderer} which compute text with the matching decorator - * from {@link #decorators} based on the type of value and leave the hand to - * the {@link #delegate} to perform the visual renderer. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.0 - */ -public class MultiDecoratorTableCelleRenderer implements TableCellRenderer { - - /** Delegate cell renderer */ - protected TableCellRenderer delegate; - - /** accepted types */ - protected List<Class<?>> types; - - /** decorators for accepted types */ - protected Decorator<?>[] decorators; - - public MultiDecoratorTableCelleRenderer(JXPathDecorator<?>... decorator) { - this(new DefaultTableCellRenderer(), decorator); - } - - public MultiDecoratorTableCelleRenderer(TableCellRenderer delegate, - JXPathDecorator<?>... decorator) { - this.delegate = delegate; - - types = new ArrayList<Class<?>>(); - List<Decorator<?>> tmp = new ArrayList<Decorator<?>>(); - for (JXPathDecorator<?> d : decorator) { - if (types.contains(d.getType())) { - throw new IllegalArgumentException( - "can not have twice a decorator of type " + - d.getType()); - } - types.add(d.getType()); - tmp.add(d); - } - decorators = tmp.toArray(new Decorator<?>[tmp.size()]); - } - - @Override - public Component getTableCellRendererComponent(JTable table, - Object value, - boolean isSelected, - boolean hasfocus, - int row, - int column) { - if (value != null) { - int i = types.indexOf(value.getClass()); - if (i != -1) { - Decorator<?> d = decorators[i]; - value = d.toString(value); - } - } - return delegate.getTableCellRendererComponent(table, - value, - isSelected, - hasfocus, - row, - column - ); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/JSplitPaneState.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/JSplitPaneState.java deleted file mode 100644 index 4bf7495..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/JSplitPaneState.java +++ /dev/null @@ -1,97 +0,0 @@ -package jaxx.runtime.swing.session; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import javax.swing.*; - -/** - * State for JSplit - * FIXME add listener for divider move action - * - * @author poussin - * @author Kevin Morin - morin@codelutin.com - * @since 2.5.16 - */ -public class JSplitPaneState implements State { - - protected int dividerLocation = -1; - - protected int orientation = JSplitPane.HORIZONTAL_SPLIT; - - public JSplitPaneState() { - } - - public int getDividerLocation() { - return dividerLocation; - } - - public void setDividerLocation(int dividerLocation) { - this.dividerLocation = dividerLocation; - } - - public int getOrientation() { - return orientation; - } - - public void setOrientation(int orientation) { - this.orientation = orientation; - } - - protected JSplitPane checkComponent(Object o) { - if (o == null) { - throw new IllegalArgumentException("null component"); - } - if (!(o instanceof JSplitPane)) { - throw new IllegalArgumentException("invalid component"); - } - return (JSplitPane) o; - } - - @Override - public State getState(Object o) { - JSplitPane p = checkComponent(o); - - JSplitPaneState result = new JSplitPaneState(); - result.setDividerLocation(p.getUI().getDividerLocation(p)); - result.setOrientation(p.getOrientation()); - - return result; - } - - @Override - public void setState(Object o, State state) { - if (state == null) { - return; - } - JSplitPane p = checkComponent(o); - if (state instanceof JSplitPaneState) { - JSplitPaneState sps = (JSplitPaneState) state; - if (sps.getDividerLocation() != -1 - && p.getOrientation() == sps.getOrientation()) { - p.setDividerLocation(sps.getDividerLocation()); - } - } else { - throw new IllegalArgumentException("invalid state"); - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/JTabbedPaneState.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/JTabbedPaneState.java deleted file mode 100644 index d9c38a8..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/JTabbedPaneState.java +++ /dev/null @@ -1,97 +0,0 @@ -package jaxx.runtime.swing.session; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import javax.swing.*; - -/** - * State for the JTabbedPane - * - * @author poussin - * @author Kevin Morin - morin@codelutin.com - * @since 2.5.16 - */ -public class JTabbedPaneState implements State { - - protected int selectedIndex = -1; - - protected int tabCount; - - public JTabbedPaneState() { - } - - public int getSelectedIndex() { - return selectedIndex; - } - - public void setSelectedIndex(int selectedIndex) { - this.selectedIndex = selectedIndex; - } - - public int getTabCount() { - return tabCount; - } - - public void setTabCount(int tabCount) { - this.tabCount = tabCount; - } - - - protected JTabbedPane checkComponent(Object o) { - if (o == null) { - throw new IllegalArgumentException("null component"); - } - if (!(o instanceof JTabbedPane)) { - throw new IllegalArgumentException("invalid component"); - } - return (JTabbedPane) o; - } - - @Override - public State getState(Object o) { - JTabbedPaneState result = new JTabbedPaneState(); - - JTabbedPane p = checkComponent(o); - result.setSelectedIndex(p.getSelectedIndex()); - result.setTabCount(p.getTabCount()); - - return result; - } - - @Override - public void setState(Object o, State state) { - if (state == null) { - return; - } - if (state instanceof JTabbedPaneState) { - JTabbedPane p = checkComponent(o); - JTabbedPaneState tps = (JTabbedPaneState) state; - if (tps.getSelectedIndex() != -1 - && p.getTabCount() == tps.getTabCount()) { - p.setSelectedIndex(tps.getSelectedIndex()); - } - } else { - throw new IllegalArgumentException("invalid state"); - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/JTableState.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/JTableState.java deleted file mode 100644 index 709b576..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/JTableState.java +++ /dev/null @@ -1,155 +0,0 @@ -package jaxx.runtime.swing.session; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.*; -import javax.swing.table.TableColumn; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * State for JTable. - * TODO add support for column order change - * - * @author poussin - * @author Kevin Morin - morin@codelutin.com - * @since 2.5.16 - * - */ -public class JTableState implements State { - - private static final Log log = LogFactory.getLog(JTableState.class); - - protected int[] columnWidths = new int[0]; - - protected Map<Integer, String> sortKeys; - - public JTableState() { - } - - public JTableState(int[] columnWidths, Map<Integer, String> sortKeys) { - this.columnWidths = columnWidths; - this.sortKeys = sortKeys; - } - - public int[] getColumnWidths() { - return columnWidths; - } - - public void setColumnWidths(int[] columnWidths) { - this.columnWidths = columnWidths; - } - - public Map<Integer, String> getSortKeys() { - return sortKeys; - } - - public void setSortKeys(Map<Integer, String> sortKeys) { - this.sortKeys = sortKeys; - } - - protected JTable checkComponent(Object o) { - if (o == null) { - throw new IllegalArgumentException("null component"); - } - if (!(o instanceof JTable)) { - throw new IllegalArgumentException("invalid component"); - } - return (JTable) o; - } - - @Override - public State getState(Object o) { - JTable table = checkComponent(o); - - JTableState result = new JTableState(); - - int[] columnWidths = new int[table.getColumnCount()]; - boolean resizableColumnExists = false; - - for (int i = 0; i < columnWidths.length; i++) { - TableColumn tc = table.getColumnModel().getColumn(i); - columnWidths[i] = (tc.getResizable()) ? tc.getWidth() : -1; - if (tc.getResizable()) { - resizableColumnExists = true; - } - } - - if (resizableColumnExists) { - result.setColumnWidths(columnWidths); - } - - if (table.getRowSorter() != null) { - List<? extends RowSorter.SortKey> sortKeys = table.getRowSorter().getSortKeys(); - Map<Integer, String> sortKeysMap = null; - if (sortKeys != null) { - sortKeysMap = new HashMap<Integer, String>(); - for (RowSorter.SortKey sortKey : sortKeys) { - sortKeysMap.put(sortKey.getColumn(), String.valueOf(sortKey.getSortOrder())); - } - } - result.setSortKeys(sortKeysMap); - } - - return result; - } - - @Override - public void setState(Object o, State state) { - if (!(state instanceof JTableState)) { - throw new IllegalArgumentException("invalid state"); - } - - JTable table = checkComponent(o); - JTableState jTableState = (JTableState) state; - - int[] columnWidths = jTableState.getColumnWidths(); - if (columnWidths != null - && table.getColumnCount() == columnWidths.length) { - for (int i = 0; i < columnWidths.length; i++) { - if (columnWidths[i] != -1) { - TableColumn tc = table.getColumnModel().getColumn(i); - if (tc.getResizable()) { - tc.setPreferredWidth(columnWidths[i]); - } - } - } - } - Map<Integer, String> sortKeysMap = jTableState.getSortKeys(); - if (sortKeysMap != null) { - List<RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>(); - for (Integer index : sortKeysMap.keySet()) { - SortOrder sortOrder = SortOrder.valueOf(sortKeysMap.get(index)); - RowSorter.SortKey sortKey = new RowSorter.SortKey(index, sortOrder); - sortKeys.add(sortKey); - } - table.getRowSorter().setSortKeys(sortKeys); - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/JXTableSwingSessionState.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/JXTableSwingSessionState.java deleted file mode 100644 index 7f6d0ff..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/JXTableSwingSessionState.java +++ /dev/null @@ -1,109 +0,0 @@ -package jaxx.runtime.swing.session; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.jdesktop.swingx.JXTable; -import org.jdesktop.swingx.table.DefaultTableColumnModelExt; -import org.jdesktop.swingx.table.TableColumnExt; - -import javax.swing.table.TableColumn; -import java.util.List; -import java.util.Map; - -/** - * @author Kevin Morin - kmorin@codelutin.com - * @since 2.5.16 - */ -public class JXTableSwingSessionState extends JTableState { - - protected boolean[] hiddenColumns; - - public JXTableSwingSessionState() { - super(); - } - - public JXTableSwingSessionState(int[] columnWidths, Map<Integer, String> sortKeys, boolean[] hiddenColumns) { - super(columnWidths, sortKeys); - this.hiddenColumns = hiddenColumns; - } - - public boolean[] getHiddenColumns() { - return hiddenColumns; - } - - public void setHiddenColumns(boolean[] hiddenColumns) { - this.hiddenColumns = hiddenColumns; - } - - protected JXTable checkComponent(Object o) { - if (o == null) { - throw new IllegalArgumentException("null component"); - } - if (!(o instanceof JXTable)) { - throw new IllegalArgumentException("invalid component"); - } - return (JXTable) o; - } - - @Override - public State getState(Object o) { - JXTable table = checkComponent(o); - JXTableSwingSessionState result = new JXTableSwingSessionState(); - JTableState state = (JTableState) super.getState(o); - if (state != null) { - result.setColumnWidths(state.getColumnWidths()); - result.setSortKeys(state.getSortKeys()); - } - DefaultTableColumnModelExt columnModel = - (DefaultTableColumnModelExt) table.getColumnModel(); - List<TableColumn> columns = columnModel.getColumns(true); - boolean[] hiddenColumns = new boolean[columns.size()]; - for (int i = 0; i < hiddenColumns.length; i++) { - TableColumnExt tc = (TableColumnExt) columns.get(i); - hiddenColumns[i] = !tc.isVisible(); - } - result.setHiddenColumns(hiddenColumns); - - return result; - } - - @Override - public void setState(Object o, State state) { - if (!(state instanceof JXTableSwingSessionState)) { - throw new IllegalArgumentException("invalid state"); - } - super.setState(o, state); - JXTable table = checkComponent(o); - boolean[] hiddenColumns = ((JXTableSwingSessionState) state).getHiddenColumns(); - DefaultTableColumnModelExt columnModel = - (DefaultTableColumnModelExt) table.getColumnModel(); - List<TableColumn> columns = columnModel.getColumns(true); - int columnNb = columns.size(); - if (hiddenColumns != null && hiddenColumns.length == columnNb) { - for (int i = 0; i < columnNb; i++) { - TableColumnExt tc = (TableColumnExt) columns.get(i); - tc.setVisible(!hiddenColumns[i]); - } - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/State.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/State.java deleted file mode 100644 index a91ef0f..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/State.java +++ /dev/null @@ -1,38 +0,0 @@ -package jaxx.runtime.swing.session; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -/** - * get(save) and set(restore) state of object passed in argument - * - * @author poussin - * @author Kevin Morin - morin@codelutin.com - * @since 2.5.16 - */ -public interface State { - - State getState(Object o); - - void setState(Object o, State state); - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/SwingSession.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/SwingSession.java deleted file mode 100644 index 86bb4c3..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/SwingSession.java +++ /dev/null @@ -1,478 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.session; - - -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.Predicate; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.JXTable; - -import javax.swing.JFrame; -import javax.swing.JSplitPane; -import javax.swing.JTabbedPane; -import javax.swing.JTable; -import java.awt.Component; -import java.awt.Container; -import java.awt.Rectangle; -import java.awt.Window; -import java.beans.DefaultPersistenceDelegate; -import java.beans.Encoder; -import java.beans.ExceptionListener; -import java.beans.Expression; -import java.beans.XMLDecoder; -import java.beans.XMLEncoder; -import java.io.ByteArrayOutputStream; -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.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Set; - -/** - * Use to store and restore position and size of application. Default supported widgets are: - * <ul> - * <li> java.awt.Window (and subclasses)</li> - * <li> javax.swing.JTabbedPane (and subclasses)</li> - * <li> javax.swing.JSplitPane (and subclasses)</li> - * <li> org.jdesktop.swingx.JXTable (and subclasses)</li> - * <li> javax.swing.JTable (and subclasses)</li> - * </ul> - * - * usage: - * <ul> - * <li> create SwingSession object</li> - * <li> add component that you want save</li> - * <li> explicite call to save</li> - * </ul> - * You can use same SwingSession for multiple window but in this case you must - * have setName for each window with different name, otherwize there are - * collision between window component and result is undetermisitic. - * - * This code is partialy inspired from http://kenai.com/projects/bsaf/pages/Home - * project. This project is under LGPL v2.1 license. We can't reuse directly this - * library because to many fields and methods are private and we can't implements - * it and modify some behavior. - * - * @author poussin - * @author kmorin - * @since 2.5.16 - */ -public class SwingSession { - - private static final Log log = LogFactory.getLog(SwingSession.class); - - protected File file; - - protected boolean autoSave; - - protected Set<Component> registeredComponent = Sets.newIdentityHashSet(); - - /** - * State object registered to get and set State. - * key: class of component managed by the state; value: the state - */ - protected Map<Class, State> stateManager = Maps.newHashMap(); - - /** - * state of all component added with add method. - * key: path of compoenent; value: State - */ - protected Map<String, State> states; - - /** - * Create a new swing session with the given parameters. - * - * If it fails to read the given file, then it will delete it from the fs and starts with a new empty file. - * - * @return the new swing session - * @since 2.8.6 - * @deprecated since 2.10, the default behaviour is now to safely load the incoming file - */ - @Deprecated - public static SwingSession newSession(File file, boolean autoSave) { - return newSession(file, autoSave, Maps.<Class, State>newHashMap()); - } - - /** - * Create a new swing session with the given parameters. - * - * If it fails to read the given file, then it will delete it from the fs and starts with a new empty file. - * - * @return the new swing session - * @since 2.8.6 - * @deprecated since 2.10, the default behaviour is now to safely load the incoming file - */ - @Deprecated - public static SwingSession newSession(File file, boolean autoSave, Map<Class, State> additionalStates) { - return new SwingSession(file, autoSave, additionalStates); - } - - public SwingSession(File file, boolean autoSave) { - this(file, autoSave, Maps.<Class, State>newHashMap()); - } - - public SwingSession(File file, boolean autoSave, Map<Class, State> additionalStates) { - this.file = file; - this.autoSave = autoSave; - stateManager.put(Window.class, new WindowState()); - stateManager.put(JTable.class, new JTableState()); - stateManager.put(JTabbedPane.class, new JTabbedPaneState()); - stateManager.put(JSplitPane.class, new JSplitPaneState()); - stateManager.put(JXTable.class, new JXTableSwingSessionState()); - stateManager.putAll(additionalStates); - - if (file != null && file.exists()) { - - loadSafeStates(); - - } else { - - states =Maps.newHashMap(); - - } - - } - - public File getFile() { - return new File(file.getAbsolutePath()); - } - - public void setFile(File file) { - this.file = file; - } - - /** - * Loads safely the states from the {@link #file}. - * - * If could not read the internal file, then will try to delete it. - * @since 2.10 - */ - public void loadSafeStates() { - - try { - states = loadStates(file); - } catch (IOException e) { - // reset file - if (log.isErrorEnabled()) { - log.error("Could not read swing session file: " + file, e); - } - if (file.exists()) { - - // try to delete it - try { - FileUtils.forceDelete(file); - } catch (IOException e1) { - throw new RuntimeException("Could not delete file: " + file, e1); - } - } - - states = Maps.newHashMap(); - } - - if (states == null) { - states = Maps.newHashMap(); - } - - } - - @Override - protected void finalize() throws Throwable { - save(); - super.finalize(); - } - - - /* If an exception occurs in the XMLEncoder/Decoder, we want - * to throw an IOException. The exceptionThrow listener method - * doesn't throw a checked exception so we just set a flag - * here and check it when the encode/decode operation finishes - */ - static private class AbortExceptionListener implements ExceptionListener { - - public Exception exception = null; - - @Override - public void exceptionThrown(Exception e) { - if (exception == null) { - exception = e; - } - } - } - - /* There are some (old) Java classes that aren't proper beans. Rectangle - * is one of these. When running within the secure sandbox, writing a - * Rectangle with XMLEncoder causes a security exception because - * DefaultPersistenceDelegate calls Field.setAccessible(true) to gain - * access to private fields. This is a workaround for that problem. - * A bug has been filed, see JDK bug ID 4741757 - */ - private static class RectanglePD extends DefaultPersistenceDelegate { - - public RectanglePD() { - super(new String[]{"x", "y", "width", "height"}); - } - - @Override - protected Expression instantiate(Object oldInstance, Encoder out) { - Rectangle oldR = (Rectangle) oldInstance; - Object[] constructorArgs = new Object[]{ - oldR.x, oldR.y, oldR.width, oldR.height - }; - return new Expression(oldInstance, oldInstance.getClass(), "new", constructorArgs); - } - } - - public void save() throws IOException { - updateState(); - AbortExceptionListener el = new AbortExceptionListener(); - ByteArrayOutputStream bst = new ByteArrayOutputStream(); - XMLEncoder e = null; - /* Buffer the XMLEncoder's output so that decoding errors don't - * cause us to trash the current version of the specified file. - */ - try { - e = new XMLEncoder(bst); - e.setPersistenceDelegate(Rectangle.class, new RectanglePD()); - e.setExceptionListener(el); - e.writeObject(states); - } finally { - if (e != null) { - e.close(); - } - } - if (el.exception != null) { - try { - throw el.exception; - } catch (Exception e1) { - if (e1 instanceof IOException) { - throw (IOException) e1; - } else { - throw new IOException(e1); - } - } -// log.warn("save failed \"" + file + "\"", el.exception); - } else { - OutputStream ost = null; - try { - ost = new FileOutputStream(file); - ost.write(bst.toByteArray()); - - ost.close(); - } finally { - IOUtils.closeQuietly(ost); - - } - } - } - - /** - * Loads the states from the file - */ - public Map<String, State> loadStates(File file) throws IOException { - Map<String, State> result = null; - if (file.exists()) { - XMLDecoder d = null; - try { - InputStream ist = new FileInputStream(file); - d = new XMLDecoder(ist); - AbortExceptionListener eee = new AbortExceptionListener(); - d.setExceptionListener(eee); - Object bean = d.readObject(); - if (eee.exception != null) { - log.warn("load failed \"" + file + "\"", eee.exception); - throw eee.exception; - } else { - result = (Map<String, State>) bean; - } - - } catch (Exception e) { - if (e instanceof IOException) { - throw (IOException) e; - } else { - throw new IOException(e); - } - } finally { - if (d != null) { - d.close(); - } - } - } - return result; - } - - public void updateState() { - walkThrowComponent("", registeredComponent, - new SaveStateAction()); - } - - public void add(Component c) { - add(c, false); - } - - public void add(final Component c, boolean replace) { - if (c == null) { - return; - } - final String cName = getComponentName(c); - Object existingComponent = CollectionUtils.find(registeredComponent, - new Predicate<Object>() { - @Override - public boolean evaluate(Object o) { - Component comp = (Component) o; - String compName = getComponentName(comp); - return c.getClass().equals(comp.getClass()) - && cName.equals(compName); - } - }); - - if (existingComponent != null) { - if (replace) { - if (log.isDebugEnabled()) { - log.debug("replacing the component fir path /" + cName); - } - remove((Component) existingComponent); - - } else { - log.warn(String.format( - "Component already added %s(%s)", c.getClass(), c.getName())); - return; - } - } - - registeredComponent.add(c); - walkThrowComponent("", - Collections.singleton(c), - new RestoreStateAction()); - } - - /** - * Remove component from component to save - * - * @param c - */ - public void remove(Component c) { - registeredComponent.remove(c); - } - - protected String getComponentName(Component c) { - String name = c.getName(); - if (name == null) { - int n = c.getParent().getComponentZOrder(c); - if (n >= 0) { - Class clazz = c.getClass(); - name = clazz.getSimpleName(); - if (name.length() == 0) { - name = "Anonymous" + clazz.getSuperclass().getSimpleName(); - } - name = name + n; - } else { - // Implies that the component tree is changing - // while we're computing the path. Punt. - log.warn("Couldn't compute pathname for " + c); - } - } - return name; - } - - public State getStateManager(Class clazz) { - State result = null; - while (result == null && clazz != null) { - result = stateManager.get(clazz); - clazz = clazz.getSuperclass(); - } - return result; - } - - public void addToStateManager(Class component, State state) { - stateManager.put(component, state); - } - - public State getStates(String path) { - return states.get(path); - } - - public void setStates(String path, State state) { - this.states.put(path, state); - } - - protected void walkThrowComponent( - String path, Collection<Component> roots, Action action) { - for (Component root : roots) { - if (root != null) { - String pathname = path + "/" + getComponentName(root); - State state = getStateManager(root.getClass()); - if (state != null) { - action.doAction(this, pathname, root); - } - if (root instanceof Container) { - Component[] children = ((Container) root).getComponents(); - if ((children != null) && (children.length > 0)) { - walkThrowComponent(pathname, Arrays.asList(children), action); - } - } - if (root instanceof JFrame) { - Component[] children = ((JFrame) root).getContentPane().getComponents(); - if ((children != null) && (children.length > 0)) { - walkThrowComponent(pathname, Arrays.asList(children), action); - } - } - } - } - } - - public static interface Action { - public void doAction(SwingSession session, String path, Component c); - } - - public static class SaveStateAction implements Action { - @Override - public void doAction(SwingSession session, String path, Component c) { - State manager = session.getStateManager(c.getClass()); - State state = manager.getState(c); - session.setStates(path, state); - } - } - - public static class RestoreStateAction implements Action { - @Override - public void doAction(SwingSession session, String path, Component c) { - State manager = session.getStateManager(c.getClass()); - State state = session.getStates(path); - if (state != null) { - manager.setState(c, state); - } - } - } - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/WindowState.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/WindowState.java deleted file mode 100644 index 7ddd54f..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/session/WindowState.java +++ /dev/null @@ -1,202 +0,0 @@ -package jaxx.runtime.swing.session; - -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import javax.swing.*; -import java.awt.*; - -/** - * State for Window - * - * @author poussin - * @author Kevin Morin - morin@codelutin.com - * @since 2.5.16 - */ -public class WindowState implements State { - - private static final String WINDOW_STATE_NORMAL_BOUNDS = - "WindowState.normalBounds"; - - protected Rectangle bounds; - protected Rectangle gcBounds; - protected int frameState = Frame.NORMAL; - - public WindowState() { - } - - public WindowState(Rectangle bounds, Rectangle gcBounds, int frameState) { - this.bounds = new Rectangle(bounds); - this.gcBounds = new Rectangle(gcBounds); - this.frameState = frameState; - } - - public Rectangle getBounds() { - return bounds; - } - - public void setBounds(Rectangle bounds) { - this.bounds = bounds; - } - - public Rectangle getGcBounds() { - return gcBounds; - } - - public void setGcBounds(Rectangle gcBounds) { - this.gcBounds = gcBounds; - } - - public int getFrameState() { - return frameState; - } - - public void setFrameState(int frameState) { - this.frameState = frameState; - } - - protected Window checkComponent(Object o) { - if (o == null) { - throw new IllegalArgumentException("null component"); - } - if (!(o instanceof Window)) { - throw new IllegalArgumentException("invalid component"); - } - return (Window) o; - } - - /** - * Checks whether the window supports resizing - * @param window the {@code Window} to be checked - * @return true if the window supports resizing - */ - protected static boolean isResizable(Window window) { - boolean resizable = true; - if (window instanceof Frame) { - resizable = ((Frame) window).isResizable(); - } else if (window instanceof Dialog) { - resizable = ((Dialog) window).isResizable(); - } - return resizable; - } - - /** - * Gets {@code Window} bounds from the client property - * @param window the source {@code Window} - * @return bounds from the client property - */ - protected static Rectangle getWindowNormalBounds(Window window) { - Rectangle result = null; - if (window instanceof JFrame) { - Object res = ((JFrame) window).getRootPane().getClientProperty( - WINDOW_STATE_NORMAL_BOUNDS); - if (res instanceof Rectangle) { - result = (Rectangle) res; - } - } - return result; - } - - /** - * Calculates virtual graphic bounds. - * On multiscreen systems all screens are united into one virtual screen. - * @return the graphic bounds - */ - public static Rectangle computeVirtualGraphicsBounds() { - Rectangle virtualBounds = new Rectangle(); - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice[] gs = ge.getScreenDevices(); - for (GraphicsDevice gd : gs) { - GraphicsConfiguration gc = gd.getDefaultConfiguration(); - virtualBounds = virtualBounds.union(gc.getBounds()); - } - return virtualBounds; - } - - /** - * Puts {@code Window} bounds to client property. - * @param window the target {@code Window} - * @param bounds bounds - */ - public static void putWindowNormalBounds(Window window, Rectangle bounds) { - if (window instanceof JFrame) { - ((JFrame) window).getRootPane().putClientProperty( - WINDOW_STATE_NORMAL_BOUNDS, bounds); - } - } - - @Override - public State getState(Object o) { - Window c = checkComponent(o); - int frameState = Frame.NORMAL; - if (c instanceof Frame) { - frameState = ((Frame) c).getExtendedState(); - } - GraphicsConfiguration gc = c.getGraphicsConfiguration(); - Rectangle gcBounds = (gc == null) ? null : gc.getBounds(); - Rectangle frameBounds = c.getBounds(); - - /* If this is a JFrame created by FrameView and it's been maximized, - * retrieve the frame's normal (not maximized) bounds. More info: - * see FrameStateListener#windowStateChanged in FrameView. - */ - if ((c instanceof JFrame) && (0 != (frameState & Frame.MAXIMIZED_BOTH))) { - frameBounds = getWindowNormalBounds(c); - } - - WindowState result = null; - if (frameBounds != null && !frameBounds.isEmpty()) { - result = new WindowState(); - result.setBounds(frameBounds); - result.setGcBounds(gcBounds); - result.setFrameState(frameState); - } - - return result; - } - - @Override - public void setState(Object o, State state) { - Window w = checkComponent(o); - if ((state != null) && !(state instanceof WindowState)) { - throw new IllegalArgumentException("invalid state"); - } - WindowState windowState = (WindowState) state; - if (windowState.getBounds() != null) { - putWindowNormalBounds(w, windowState.getBounds()); - if (!w.isLocationByPlatform() && (state != null)) { - - Rectangle gcBounds0 = windowState.getGcBounds(); - if (gcBounds0 != null && isResizable(w)) { - if (computeVirtualGraphicsBounds().contains(gcBounds0.getLocation())) { - w.setBounds(windowState.getBounds()); - } else { - w.setSize(windowState.getBounds().getSize()); - } - } - } - if (w instanceof Frame) { - ((Frame) w).setExtendedState(windowState.getFrameState()); - } - } - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/BusyChangeListener.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/BusyChangeListener.java deleted file mode 100644 index 258cf2a..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/BusyChangeListener.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.wizard; - -import jaxx.runtime.swing.BlockingLayerUI; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.awt.Component; -import java.awt.Cursor; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -/** - * To listen the busy state of a {@link WizardModel}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.1 - */ -public class BusyChangeListener implements PropertyChangeListener { - - /** Logger */ - private static final Log log = LogFactory.getLog(BusyChangeListener.class); - - protected Cursor busyCursor; - - protected Cursor defaultCursor; - - protected final Component ui; - - protected BlockingLayerUI blockingUI; - - public BusyChangeListener(Component ui) { - this.ui = ui; - } - - public Component getUi() { - return ui; - } - - public BlockingLayerUI getBlockingUI() { - return blockingUI; - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - Boolean value = (Boolean) evt.getNewValue(); - if (log.isDebugEnabled()) { - log.debug("busy state changed to " + value); - } - if (value != null && value) { - setBusy(ui); - - } else { - setUnBusy(ui); - } - } - - public void setBlockingUI(BlockingLayerUI blockingUI) { - this.blockingUI = blockingUI; - } - - protected void setBusy(Component ui) { - if (ui != null) { - ui.setCursor(getBusyCursor()); - } - if (blockingUI != null) { - blockingUI.setBlock(true); - } - } - - protected void setUnBusy(Component ui) { - if (ui != null) { - ui.setCursor(getDefaultCursor()); - } - if (blockingUI != null) { - blockingUI.setBlock(false); - } - } - - protected Cursor getBusyCursor() { - if (busyCursor == null) { - busyCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); - } - return busyCursor; - } - - protected Cursor getDefaultCursor() { - if (defaultCursor == null) { - defaultCursor = Cursor.getDefaultCursor(); - } - return defaultCursor; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java deleted file mode 100644 index 113bbb7..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java +++ /dev/null @@ -1,306 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.wizard; - -import jaxx.runtime.JAXXUtil; - -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * Un modèle de wizard. - * - * - * <b>Note:</b> le type des étapes doit être uné énumération qui implante {@link - * WizardStep}. - * - * @param <E> le type des étapes. - * @author Tony Chemit - chemit@codelutin.com - * @see WizardStep - * @since 1.3 - */ -public abstract class WizardModel<E extends WizardStep> { - - public static final String STEPS_PROPERTY_NAME = "steps"; - - public static final String STEP_PROPERTY_NAME = "step"; - - public static final String PREVIOUS_STEP_PROPERTY_NAME = "previousStep"; - - public static final String NEXT_STEP_PROPERTY_NAME = "nextStep"; - - public static final String VALID_STEP_PROPERTY_NAME = "validStep"; - - public static final String BUSY_PROPERTY_NAME = "busy"; - - /** le type d'une etape du model (doit etre une enumeration) */ - protected final Class<E> stepClass; - - /** Toutes les étapes à passer */ - protected List<E> steps; - - /** les etapes a exclure */ - protected List<E> excludeSteps; - - /** L'étape courante */ - protected E step; - - /** drapeau pour valider l'état de l'étape courante */ - protected boolean validStep; - - /** un drapeau pour savoir si le modèle est occupé. */ - private boolean busy; - - /** - * drapeau lorsque le modele effectue des operations de transformation de - * modele mais que les écouteurs ne devraient pas tenir compte des - * modifications - */ - protected boolean valueAdjusting; - - /** pour propager les changements dans le modèle vers l'ui */ - protected PropertyChangeSupport pcs; - - public WizardModel(Class<E> stepClass, E... steps) { - if (!Enum.class.isAssignableFrom(stepClass)) { - throw new IllegalArgumentException("stepClass must be an" + - " Enumeration but was " + stepClass.getName()); - } - this.stepClass = stepClass; - pcs = new PropertyChangeSupport(this); - this.steps = new ArrayList<E>(); - if (steps.length > 0) { - setSteps(steps); - } - } - - public void start() { - if (steps.isEmpty()) { - throw new IllegalStateException("can not start, no step found"); - } - step = null; - E startStep = steps.get(0); - setStep(startStep); - } - - public void destroy() { - // suppression de tous les listeners - JAXXUtil.destroy(pcs); - } - - public void gotoNextStep() { - E nextStep = getNextStep(); - if (nextStep == null) { - throw new IllegalStateException("no next step to go"); - } - setStep(nextStep); - } - - public void gotoPreviousStep() { - E previousStep = getPreviousStep(); - if (previousStep == null) { - throw new IllegalStateException("no previous step to go"); - } - setStep(previousStep); - } - - public void gotoStep(E e) { - if (e == null) { - throw new NullPointerException("step can not be null"); - } - if (!steps.contains(e)) { - throw new IllegalStateException("step " + e.toString() + - " is not in universe of steps (" + steps + ')'); - } - setBusy(true); - try { - setStep(e); - } finally { - setBusy(false); - } - } - - public E getStep() { - return step; - } - - public int getStepIndex(E s) { - return steps.indexOf(s); - } - - public boolean isValidStep() { - return validStep; - } - - public E getPreviousStep() { - return getPreviousStep(step); - } - - public E getPreviousStep(E step) { - int index = getStepIndex(step); - if (index < 1) { - // si pas de step ou sur premier step - return null; - } - return steps.get(index - 1); - } - - public E getNextStep(E step) { - int index = getStepIndex(step); - if (index < 1) { - // si pas de step ou sur premier step - return null; - } - return steps.get(index - 1); - } - - public E getNextStep() { - int index = getStepIndex(step); - if (index == -1 || index == steps.size() - 1) { - // si pas de step positionne ou dernier etape - return null; - } - return steps.get(index + 1); - } - - public List<E> getSteps() { - return steps; - } - - public boolean containsStep(E step) { - return getSteps().contains(step); - } - - public boolean isValueAdjusting() { - return valueAdjusting; - } - - public boolean isBusy() { - return busy; - } - - public void setBusy(boolean busy) { - boolean oldValue = this.busy; - this.busy = busy; - firePropertyChange(BUSY_PROPERTY_NAME, oldValue, busy); - } - - /** - * Change l'univers des etapes. - * - * Note: on presume ici que l'étape courante est toujours la meme. - * - * @param steps le nouvel univers des etapes - */ - public void setSteps(E... steps) { - List<E> oldValue = this.steps; - this.steps = Collections.unmodifiableList(Arrays.asList(steps)); - firePropertyChange(STEPS_PROPERTY_NAME, oldValue, this.steps); - // la propriete nextStep peut avoir changee - firePropertyChange(NEXT_STEP_PROPERTY_NAME, null, getNextStep()); - } - - public void setValueAdjusting(boolean valueAdjusting) { - this.valueAdjusting = valueAdjusting; - } - - public void setExcludeSteps(List<E> excludeSteps) { - this.excludeSteps = excludeSteps; - } - - public boolean validate(E s) { - return step != null; - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - pcs.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - pcs.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.removePropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListeners() { - JAXXUtil.destroy(pcs); - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - destroy(); - } - - public void validate() { - if (step == null) { - // pas de validation quand aucune etape n'est sélectionnée - return; - } - validStep = validate(step); - // toujours forcer la propagation - firePropertyChange(VALID_STEP_PROPERTY_NAME, null, validStep); - } - - public abstract void updateUniverse(); - - public Class<E> getStepClass() { - return stepClass; - } - - protected void setStep(E step) { - E oldValue = this.step; - this.step = step; - firePropertyChange(STEP_PROPERTY_NAME, oldValue, step); - // la propriete nextStep peut avoir changee - firePropertyChange(NEXT_STEP_PROPERTY_NAME, null, getNextStep()); - // la propriete previousStep peut avoir changee - firePropertyChange(PREVIOUS_STEP_PROPERTY_NAME, null, getPreviousStep()); - validate(); - } - - protected void firePropertyChange(String propertyName, Object oldValue, - Object newValue) { - pcs.firePropertyChange(propertyName, oldValue, newValue); - } - - protected void firePropertyChange(String propertyName, Object newValue) { - pcs.firePropertyChange(propertyName, null, newValue); - } - - protected void fireIndexedPropertyChange(String propertyName, int index, - Object oldValue, Object newValue) { - pcs.fireIndexedPropertyChange(propertyName, index, oldValue, newValue); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardStep.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardStep.java deleted file mode 100644 index e17c770..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardStep.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.wizard; - -import java.io.Serializable; - -/** - * le contrat d'une étape d'un wizard. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.3 - */ -public interface WizardStep extends Serializable { - - String name(); - - int ordinal(); - - String getLabel(); - - String getDescription(); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardStepUI.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardStepUI.java deleted file mode 100644 index 578007c..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardStepUI.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.wizard; - -/** - * Le contrat d'une ui d'étape. - * - * @param <E> le type d'étape - * @param <M> le type de modèle - * @author Tony Chemit - chemit@codelutin.com - * @since 1.3 - */ -public interface WizardStepUI<E extends WizardStep, M extends WizardModel<E>> { - - E getStep(); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java deleted file mode 100644 index fb50ea6..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.wizard; - -import javax.swing.JTabbedPane; - -/** - * Contrat a respecter pour une ui de wizard. - * - * @param <E> le type d'etape - * @param <M> le type de model - * @author Tony Chemit - chemit@codelutin.com - * @since 1.3 - */ -public interface WizardUI<E extends WizardStep, M extends WizardModel<E>> { - - /** @return le modèle de wizard */ - M getModel(); - - /** @return l'étape courante */ - E getSelectedStep(); - - /** @return l'ui de l'étape courante */ - WizardStepUI<E, M> getSelectedStepUI(); - - /** - * @param step l'étape donnée - * @return l'ui de l'étape donnée - */ - WizardStepUI<E, M> getStepUI(E step); - - /** - * @param stepIndex la position de l'étape - * @return l'ui de l'étape donée - */ - WizardStepUI<E, M> getStepUI(int stepIndex); - - /** démarre le wizard */ - void start(); - - /** - * //TODO il faudrait supprimer cette méthode - * - * @return le conteneur d'ui d'étapes - */ - JTabbedPane getTabs(); - - /** - * Méthode invoquée lorsque l'univers des étapes a été modifié dans le - * modèle. - * - * @param steps les nouvelles étapes - */ - void onStepsChanged(E[] steps); - - /** - * Méthode invoquée lorsque l'étape courante a changé dans le modèle. - * - * @param oldStep l'ancienne étape - * @param newStep la nouvelle étape courante - */ - void onStepChanged(E oldStep, E newStep); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java deleted file mode 100644 index 6e3b96a..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.wizard; - -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.context.JAXXContextEntryDef; -import jaxx.runtime.context.JAXXInitialContext; - -import javax.swing.ImageIcon; -import java.awt.Window; - -/** - * Une classe pour lancer une ui de wizard. - * - * @param <E> le type des etapes - * @param <M> le type de modele - * @param <UI> le type d'ui - * @author Tony Chemit - chemit@codelutin.com - * @since 1.3 - */ -public abstract class WizardUILancher<E extends WizardStep, M extends WizardModel<E>, UI extends WizardUI<E, M>> { - - /** the jaxx context entry to store the apply action */ - public static final JAXXContextEntryDef<Runnable> APPLY_DEF = - JAXXUtil.newContextEntryDef("apply", Runnable.class); - - /** the jaxx context entry to store the cancel action */ - public static final JAXXContextEntryDef<Runnable> CANCEL_DEF = - JAXXUtil.newContextEntryDef("cancel", Runnable.class); - - public static <M extends WizardModel<?>> JAXXContextEntryDef<M> newModelEntry(Class<M> modelType) { - return JAXXUtil.newContextEntryDef("incoming", modelType); - } - - protected UI ui; - - public WizardUILancher(JAXXContext context, - Class<UI> uiClass, - Class<M> modelClass, - String title, - String tip, - ImageIcon icon) { - this(context, uiClass, modelClass, null, title, tip, icon); - } - - public WizardUILancher(JAXXContext context, - Class<UI> uiClass, - Class<M> modelClass, - M model, - String title, - String tip, - ImageIcon icon) { - try { - ui = createUI(context, - uiClass, - modelClass, - model, - title, - tip, - icon - ); - } catch (Exception ex) { - throw new RuntimeException( - "could not instanciate launcher for reason " + - ex.getMessage(), ex); - } - } - - public WizardUILancher(JAXXContext context, - Window mainUI, - Class<UI> uiClass, - Class<M> modelClass, - M model) { - try { - ui = createUI(context, - mainUI, - uiClass, - modelClass, - model - ); - } catch (Exception ex) { - throw new RuntimeException( - "could not instanciate launcher for reason " + - ex.getMessage(), ex); - } - } - - public WizardUILancher(JAXXContext context, - Window mainUI, - Class<UI> uiClass, - Class<M> modelClass) { - this(context, mainUI, uiClass, modelClass, null); - } - - public void start() { - init(ui); - start(ui); - } - - protected void start(UI ui) { - ui.start(); - } - - public <T> T getContextValue(Class<T> clazz, String name) { - if (ui == null) { - throw new NullPointerException("ui can not be null"); - } - if (!(ui instanceof JAXXObject)) { - throw new ClassCastException("ui can not be casted to JAXXObject "); - } - - return ((JAXXObject) ui).getContextValue(clazz, name); - } - - public <T> T getContextValue(Class<T> clazz) { - return getContextValue(clazz, null); - } - - protected void init(UI ui) { - } - - protected void doAction(UI ui) { - } - - protected void doCancel(UI ui) { - } - - protected void doClose(UI ui, boolean wasCanceld) { - } - - protected UI createUI(JAXXContext context, - Window mainUI, - Class<UI> uiClass, - Class<M> modelClass, - M model) throws Exception { - JAXXInitialContext uiContext = new JAXXInitialContext(); - uiContext.add(mainUI == null ? context : mainUI); - // parent context model - uiContext.add(modelClass.newInstance()); - if (model != null) { - uiContext.add(newModelEntry(modelClass), model); - } - // apply action - uiContext.add(APPLY_DEF, new Runnable() { - - @Override - public void run() { - try { - doAction(ui); - } finally { - doClose(ui, false); - } - } - }); - // cancel action - uiContext.add(CANCEL_DEF, new Runnable() { - - @Override - public void run() { - try { - doCancel(ui); - } finally { - doClose(ui, true); - } - } - }); - - // instanciate ui - - return JAXXUtil.invokeConstructor( - uiClass, - new Class[]{Window.class, JAXXContext.class}, - mainUI, uiContext - ); - } - - protected UI createUI(JAXXContext context, - Class<UI> uiClass, - Class<M> modelClass, - M model, - String title, - String tip, - ImageIcon icon) throws Exception { - JAXXInitialContext uiContext = new JAXXInitialContext(); - uiContext.add(context); - // parent context model - uiContext.add(modelClass.newInstance()); - if (model != null) { - uiContext.add(newModelEntry(modelClass), model); - } - // apply action - uiContext.add(APPLY_DEF, new Runnable() { - - @Override - public void run() { - try { - doAction(ui); - } finally { - doClose(ui, false); - } - } - }); - - // cancel action - uiContext.add(CANCEL_DEF, new Runnable() { - - @Override - public void run() { - try { - doCancel(ui); - } finally { - doClose(ui, true); - } - } - }); - - // instanciate ui - return JAXXUtil.invokeConstructor( - uiClass, - new Class[]{ - JAXXContext.class, - String.class, - String.class, - ImageIcon.class - }, - uiContext, title, tip, icon - ); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUtil.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUtil.java deleted file mode 100644 index ddf6910..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUtil.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.wizard; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.JTabbedPane; -import java.awt.Component; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.lang.reflect.Array; -import java.util.List; - -import static org.nuiton.i18n.I18n.t; - -/** - * Classe de méthodes utiles sur les wizard. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.3 - */ -public class WizardUtil { - - /** Logger */ - static private Log log = LogFactory.getLog(WizardUI.class); - - protected WizardUtil() { - } - -// public static boolean acceptStates(WizardState state, WizardState... accepted) { -// for (WizardState s : accepted) { -// if (s == state) { -// return true; -// } -// } -// return false; -// } -// -// public static boolean rejectStates(WizardState state, WizardState... rejected) { -// for (WizardState s : rejected) { -// if (s == state) { -// return false; -// } -// } -// return true; -// } - - public static void addDebugLogListener(final Log log, WizardModel<?> model) { - if (log.isDebugEnabled()) { - model.addPropertyChangeListener(new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - log.debug(evt.getPropertyName() + " <" + evt.getOldValue() + " - " + evt.getNewValue() + ">"); - } - }); - } - } - - public static void addTraceLogListener(final Log log, WizardModel<?> model) { - if (log.isTraceEnabled()) { - model.addPropertyChangeListener(new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - log.trace(evt.getPropertyName() + " <" + evt.getOldValue() + " - " + evt.getNewValue() + ">"); - } - }); - } - } - - public static <E extends WizardStep, M extends WizardModel<E>> void installWizardUIListeners(final WizardUI<E, M> ui) { - ui.getModel().addPropertyChangeListener(new PropertyChangeListener() { - - @Override - @SuppressWarnings("unchecked") - public void propertyChange(PropertyChangeEvent evt) { - String propertyName = evt.getPropertyName(); -// if (WizardExtModel.WAS_STARTED_PROPERTY_NAME.equals(propertyName)) { -// ui.onWasStarted(); -// return; -// } - if (WizardModel.STEPS_PROPERTY_NAME.equals(propertyName)) { - List<E> steps = (List<E>) evt.getNewValue(); - ui.onStepsChanged( - steps.toArray((E[]) Array.newInstance( - ui.getModel().stepClass, steps.size())) - ); - return; - } - if (WizardModel.STEP_PROPERTY_NAME.equals(propertyName)) { - ui.onStepChanged((E) evt.getOldValue(), (E) evt.getNewValue()); -// return; - } - /*if (WizardModel.VALID_STEP_PROPERTY_NAME.equals(propertyName)) { - Boolean value = (Boolean) evt.getNewValue(); - if (value == null || !value) { - ui.onModelStateChanged(WizardState.NEED_FIX); - } else { - ui.onModelStateChanged(WizardState.PENDING); - } - return; - } - if (WizardExtModel.MODEL_STATE_PROPERTY_NAME.equals(propertyName)) { - //TODO should be unicast : only for good stepUI ? - ui.onModelStateChanged((WizardState) evt.getNewValue()); - return; - } - if (WizardExtModel.STEP_STATE_PROPERTY_NAME.equals(propertyName)) { - IndexedPropertyChangeEvent e = (IndexedPropertyChangeEvent) evt; - int stepIndex = e.getIndex(); - E step = ui.getModel().getSteps().get(stepIndex); - ui.onOperationStateChanged(step, (WizardState) evt.getNewValue()); - return; - }*/ - } - }); - } - - /** - * Ajoute un listener sur le modele pour gere la politique d'affichage des - * onglets. - * - * Dans cette implantation, les onglets sont ouverts jusqu'a l'etape - * courante. Lorsque l'on revient en arrière, les onglets d'etapes - * superieurs sont fermes. - * - * @param <E> le type d'un etape de l'assistant - * @param <M> le type du modele de l'assistant - * @param ui l'ui de l'assitant - * @since 1.7.1 - */ - public static <E extends WizardStep, M extends WizardModel<E>> void addTabsDisplayUntilStepListener(final WizardUI<E, M> ui) { - // on écoute les changements d'étapes - ui.getModel().addPropertyChangeListener(WizardModel.STEP_PROPERTY_NAME, new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - M model = (M) evt.getSource(); - E oldStep = (E) evt.getOldValue(); - E newStep = (E) evt.getNewValue(); - log.debug("step has changed <old:" + oldStep + ", new:" + newStep + ">"); - int oldStepIndex = oldStep == null ? -1 : model.getStepIndex(oldStep); - int newStepIndex = model.getStepIndex(newStep); - JTabbedPane tabs = ui.getTabs(); - if (oldStepIndex + 1 == newStepIndex) { - // creation d'un nouvel onglet - WizardStepUI<E, M> c = ui.getStepUI(newStep); - String title = t(newStep.getLabel()); - String tip = t(newStep.getDescription()); - tabs.addTab(title, null, (Component) c, tip); - // selection du nouvel onglet - int index = tabs.indexOfComponent((Component) c); - if (index > -1) { - tabs.setSelectedIndex(index); - } - } else if (oldStepIndex > newStepIndex) { - // il s'agit d'un retour en arrière - // on supprime tous les onglets obsoletes - int index = newStepIndex + 1; - while (tabs.getTabCount() > index) { - log.trace("remove tab : " + index); - tabs.remove(index); - } - } else { - throw new IllegalStateException("can not go from " + oldStep + " to " + newStep); - } - } - }); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtModel.java deleted file mode 100644 index e82dead..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtModel.java +++ /dev/null @@ -1,435 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.wizard.ext; - -import jaxx.runtime.swing.wizard.WizardModel; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.EnumMap; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Un modèle de wizard avec des opérations. - * - * @param <E> le type des étapes. - * @author Tony Chemit - chemit@codelutin.com - * @since 1.3 - */ -public abstract class WizardExtModel<E extends WizardExtStep> extends WizardModel<E> { - - /** Logger */ - private static final Log log = LogFactory.getLog(WizardExtModel.class); - - public static final String OPERATIONS_PROPERTY_NAME = "operations"; - - public static final String STEP_STATE_PROPERTY_NAME = "stepState"; - - public static final String MODEL_STATE_PROPERTY_NAME = "modelState"; - - public static final String WAS_STARTED_PROPERTY_NAME = "wasStarted"; - - /** La liste des opérations à effectuer */ - protected Set<E> operations; - - /** le dictionnaire des modèles d'opération */ - protected final Map<E, WizardExtStepModel<E>> models; - - /** Pour conserver les états des opérations */ - protected Map<E, WizardState> stepStates; - - /** L'état générale du modèle */ - protected WizardState modelState; - - /** un drapeau pour savoir siune opération a été lancée */ - protected boolean wasStarted; - - @SuppressWarnings("unchecked") - public <T extends Enum<T>> WizardExtModel(Class<E> stepClass, E... steps) { - super(stepClass, steps); - Class<T> k = (Class<T>) stepClass; - stepStates = new EnumMap(k); - operations = (Set<E>) EnumSet.noneOf(k); - models = (Map<E, WizardExtStepModel<E>>) new EnumMap(k); - } - - public Set<E> getOperations() { - return operations; - } - - public WizardState getModelState() { - return modelState; - } - - public boolean isWasStarted() { - return wasStarted; - } - - public boolean containsOperation(E step) { - return getOperations().contains(step); - } - - @SuppressWarnings("unchecked") - public E getOperation() { - return getStep() != null && getStep().isOperation() ? getStep() : null; - } - - public WizardState getStepState() { - E operation = getOperation(); - return getStepState(operation); - } - - public WizardState getStepState(E step) { - return stepStates.get(step); - } - - public void setStepState(WizardState newState) { - E operation = getOperation(); - setStepState(operation, newState); - } - - public void setStepState(E step, WizardState newState) { - WizardState oldValue = getStepState(step); - stepStates.put(step, newState); - if (valueAdjusting) { - return; - } - fireIndexedPropertyChange(STEP_STATE_PROPERTY_NAME, getSteps().indexOf(step), oldValue, newState); - updateModelState(step, newState); - validate(); - } - - public boolean[] getAccessibleSteps() { - if (log.isDebugEnabled()) { - log.debug("compute with steps " + getSteps()); - } - boolean[] result = new boolean[getSteps().size()]; - int index = getSteps().indexOf(getStep()); - if (index != -1) { - - for (int i = 0, j = steps.size(); i < j; i++) { - if (i <= index) { - // tous les onglets inferieur ou egal au courant sont accessibles - result[i] = true; - continue; - } - // les onglets au dela de l'onglet sélectionné sont accessibles - // uniquement si l'onglet precedent est accessible, valide et son etat est a SUCCESSED - E previousStep = steps.get(i - 1); - result[i] = modelState == WizardState.SUCCESSED || - result[i - 1] && - validate(previousStep) && - (!previousStep.isOperation() || getStepState(previousStep) == WizardState.SUCCESSED); - } - } - if (log.isDebugEnabled()) { - log.debug("accessibles steps -------- " + Arrays.toString(result)); - } - return result; - } - - @Override - public void start() { -// super.start(); - - if (steps.isEmpty()) { - throw new IllegalStateException("can not start, no step found"); - } - - // update universe of steps and actions - updateUniverse(); - - // set first step - step = null; - E startStep = steps.get(0); - setStep(startStep); - - // model is ready - setModelState(WizardState.PENDING); - - validate(); - } - - public void cancel() { - - for (E op : operations) { - if (getStepState(op) == WizardState.PENDING) { - // on annule l'opération à venir - setStepState(op, WizardState.CANCELED); - } - } - setModelState(WizardState.CANCELED); - } - - public WizardExtModel<E> addOperation(E operation) { - if (operations.contains(operation)) { - - // skip add - return this; - } - - log.info("Add operation " + operation); - operations.add(operation); - // mis a jour de l'univers des etapes et operations - updateUniverse(); - // validation - validate(); - return this; - } - - public void removeOperation(E operation) { - if (!operations.contains(operation)) { - - // skip remove - return; - } - operations.remove(operation); - - // mis a jour de l'univers des etapes et operations - updateUniverse(); - // validation - validate(); - } - - @Override - public void setSteps(E... steps) { - super.setSteps(steps); - if (valueAdjusting) { - return; - } - // on force la propagation de la nouvelle liste - firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations); - } - - public WizardExtStepModel<E> getStepModel(E operation) { - if (operation == null) { - return null; - } - if (!operation.isOperation()) { - throw new IllegalStateException("step [" + operation + "] is not an operation."); - } - return models.get(operation); - } - - public void updateStepStates(List<E> steps) { - int index = 0; - for (E e : steps) { - fireIndexedPropertyChange(STEP_STATE_PROPERTY_NAME, index++, null, getStepState(e)); - } - firePropertyChange(MODEL_STATE_PROPERTY_NAME, null, modelState); - } - - protected void setModelState(WizardState modelState) { - WizardState oldValue = this.modelState; - this.modelState = modelState; - firePropertyChange(MODEL_STATE_PROPERTY_NAME, oldValue, modelState); - if (!wasStarted) { - if ((oldValue == null || oldValue == WizardState.PENDING) && modelState == WizardState.RUNNING) { - wasStarted = true; - firePropertyChange(WAS_STARTED_PROPERTY_NAME, false, true); - } - } - } - - protected void updateModelState(E step, WizardState newState) { - - switch (newState) { - case RUNNING: - //le modele est occupé - setModelState(WizardState.RUNNING); - break; - case FAILED: - //le modele est en erreur - setModelState(WizardState.FAILED); - break; - case CANCELED: - //le modele devient annulé - setModelState(WizardState.CANCELED); - return; - case PENDING: - //le modele est en attente - setModelState(WizardState.PENDING); - break; - case NEED_FIX: - //le modele est en attente - setModelState(WizardState.PENDING); - break; - case SUCCESSED: - // on regarde si on peut passer le model a l'état success - boolean valid = true; - for (E o : operations) { - if (getStepState(o) != WizardState.SUCCESSED) { - valid = false; - break; - } - } - if (valid) { - setModelState(WizardState.SUCCESSED); - } else { - setModelState(WizardState.PENDING); - } - break; - } - updateStepStates(steps); - } - - @Override - public void updateUniverse() { -// setValueAdjusting(true); - - List<E> oldSteps = new ArrayList<E>(getSteps()); - log.info("Start updateUniverse (oldSteps = " + oldSteps + ")"); - E[] newSteps = updateStepUniverse(); - log.info("newSteps = " + Arrays.toString(newSteps)); - - // do nothing if steps has not changed - boolean skip = true; - for (E newStep : newSteps) { - if (!oldSteps.contains(newStep)) { - skip = false; - } - } - - if (skip && oldSteps.size() == newSteps.length) { - - // same steps, so nothing to do - log.info("Steps are same, do not modify anything"); - return; - } - - for (WizardExtStepModel<E> model : models.values()) { - log.info("Destroy previous model : " + model); - model.destroy(); - } - models.clear(); - - List<E> toAdd = new ArrayList<E>(Arrays.asList(newSteps)); - - log.info("Will add models for " + toAdd); - - Iterator<E> itr = toAdd.iterator(); - while (itr.hasNext()) { - - E step = itr.next(); - - if (step.getModelClass() == null) { - - // no model attach to the step - itr.remove(); - continue; - } - - if (step.isOperation()) { - - // step is operation, model must be instanciate - WizardExtStepModel<E> model = (WizardExtStepModel<E>) step.newModel(); - if (log.isInfoEnabled()) { - log.info("[" + step + "] Add primary model " + model); - } - models.put(step, model); - - itr.remove(); - } - - // step has a model - } - - if (!toAdd.isEmpty()) { - - // there is some steps with model to attach - itr = toAdd.iterator(); - while (itr.hasNext()) { - - E step = itr.next(); - Class<? extends WizardExtStepModel<?>> modelClass = step.getModelClass(); - WizardExtStepModel<E> selectedModel = null; - // find out in models a - for (WizardExtStepModel<E> model : models.values()) { - if (modelClass.isAssignableFrom(model.getClass())) { - // find one - selectedModel = model; - break; - } - } - - if (selectedModel == null) { - throw new IllegalStateException("Could not find a primary model " + modelClass + " for step [" + step + "]"); - } - - log.info("[" + step + "] Attach model " + selectedModel); - models.put(step, selectedModel); - itr.remove(); - } - - if (!toAdd.isEmpty()) { - throw new IllegalStateException("There is some step no model : " + toAdd); - } - } - - setSteps(newSteps); - - // on met a jour les états des étapes - stepStates.clear(); - for (E step : newSteps) { - if (!stepStates.containsKey(step)) { - setStepState(step, WizardState.PENDING); - } - } - - // finally set the steps (this will refire a lot) - - log.info("Ending updateUniverse"); - -// setValueAdjusting(false); - } - - protected abstract E[] updateStepUniverse(); - - @Override - public void destroy() { - super.destroy(); - - for (WizardExtStepModel<E> model : models.values()) { - if (log.isDebugEnabled()) { - log.debug("destroy model " + model); - } - model.destroy(); - } - } - - protected int getOperationIndex(E operation) { - int index = 0; - for (E o : operations) { - if (o.equals(operation)) { - return index; - } - index++; - } - return -1; - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtStep.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtStep.java deleted file mode 100644 index f2981a1..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtStep.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.wizard.ext; - -import jaxx.runtime.swing.wizard.WizardStep; -import jaxx.runtime.swing.wizard.WizardStepUI; - - -/** - * Extension de {@link WizardStep} avec des états supplémentaires. - * - * Chaque étape possède un modèle de type {@link #getModelClass()}. - * Ce modèle peut être partagé par plusieurs étapes. - * - * De plus, on a deux drapeaux {@link #isConfig()} pour savoir si l'étape est une phase de configuration. - * - * Le drapeau {@link #isOperation()} quand à lui permet de savoir si l'étape est une opération. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.1 - */ -public interface WizardExtStep extends WizardStep { - - /** @return le label de l'opération */ - String getOperationLabel(); - - /** @return la description de l'opération */ - String getOperationDescription(); - - /** @return le type du modèle de l'action */ - Class<? extends WizardExtStepModel<?>> getModelClass(); - - /** @return le type de l'ui de l'opération */ - Class<? extends WizardStepUI<?, ?>> getUiClass(); - - /** @return {@code true} si l'étape a une opération associée, {@code false} sinon. */ - boolean isOperation(); - - /** @return {@code true} si l'étape est une phase de configuration, {@code false} sinon. */ - boolean isConfig(); - - /** - * Instancie le modèle associée à l'étape. - * - * @return le nouveau modèle associé à l'étape - */ - WizardExtStepModel<?> newModel(); - - /** - * Construit l'ui associée à l'étape. - * - * @param ui l'ui principale du wiard - * @return la noveau ui associé à l'étape - */ - WizardStepUI<?, ?> newUI(WizardExtUI<?, ?> ui); -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtStepModel.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtStepModel.java deleted file mode 100644 index 1ca65c7..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtStepModel.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.wizard.ext; - -import jaxx.runtime.JAXXUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; - -/** - * Abstract model of {@link WizardExtStep}. - * - * @author Tony Chemit - chemit@codelutin.com - * @see WizardExtStep - * @since 2.1 - */ -public abstract class WizardExtStepModel<E extends WizardExtStep> { - - /** Logger */ - private static final Log log = LogFactory.getLog(WizardExtStepModel.class); - - /** for properties change support */ - private final PropertyChangeSupport pcs; - - /** step of the model */ - protected final E step; - - /** to store if an error occurs while running */ - protected Exception error; - - protected WizardExtStepModel(E step) { - this.step = step; - pcs = new PropertyChangeSupport(this); - } - - public final E getStep() { - return step; - } - - public final Exception getError() { - return error; - } - - public void setError(Exception error) { - this.error = error; - } - - public final void addPropertyChangeListener(PropertyChangeListener listener) { - pcs.addPropertyChangeListener(listener); - } - - public final void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { - pcs.addPropertyChangeListener(propertyName, listener); - } - - - public final void removePropertyChangeListener(PropertyChangeListener listener) { - pcs.removePropertyChangeListener(listener); - } - - public final void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { - pcs.removePropertyChangeListener(propertyName, listener); - } - - public void destroy() { - if (log.isDebugEnabled()) { - log.debug("will destroy " + this); - } - - // remove all listeners - JAXXUtil.destroy(pcs); - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - destroy(); - } - - protected final void firePropertyChange(String propertyName, Object oldValue, Object newValue) { - pcs.firePropertyChange(propertyName, oldValue, newValue); - } - - protected final void firePropertyChange(String propertyName, Object newValue) { - pcs.firePropertyChange(propertyName, null, newValue); - } -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtUI.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtUI.java deleted file mode 100644 index cbc53fa..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtUI.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.wizard.ext; - -import jaxx.runtime.swing.wizard.WizardUI; - -/** - * Contrat a respecter pour une ui de wizard. - * - * @param <E> le type d'etape - * @param <M> le type de model - * @author Tony Chemit - chemit@codelutin.com - * @since 1.3 - */ -public interface WizardExtUI<E extends WizardExtStep, M extends WizardExtModel<E>> extends WizardUI<E, M> { - - /** Méthode invoqué lorsque le modèle a été initialisé. */ - void onWasInit(); - - /** Méthode invoqué lorsque la première opération du modèlé a été démarrée. */ - void onWasStarted(); - - /** - * Méthode invoquée lorsque l'état interne du modèle a changé. - * - * @param newState le nouvelle état du modèle de wizard - */ - void onModelStateChanged(WizardState newState); - - /** - * Méthode invoqué lorsque l'état d'une opération a changé. - * - * @param step l'étape dont l'état a changé - * @param newState le nouvel état pour l'étape donné - */ - void onOperationStateChanged(E step, WizardState newState); - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtUtil.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtUtil.java deleted file mode 100644 index cd5d185..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtUtil.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.wizard.ext; - -import jaxx.runtime.swing.wizard.WizardModel; -import jaxx.runtime.swing.wizard.WizardUI; -import jaxx.runtime.swing.wizard.WizardUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.beans.IndexedPropertyChangeEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.lang.reflect.Array; -import java.util.List; - -/** - * Classe de méthodes utiles sur les wizard. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.3 - */ -public class WizardExtUtil extends WizardUtil { - - /** Logger */ - static private Log log = LogFactory.getLog(WizardUI.class); - - protected WizardExtUtil() { - } - - public static boolean acceptStates(WizardState state, WizardState... accepted) { - for (WizardState s : accepted) { - if (s == state) { - return true; - } - } - return false; - } - - public static boolean rejectStates(WizardState state, WizardState... rejected) { - for (WizardState s : rejected) { - if (s == state) { - return false; - } - } - return true; - } - - public static <E extends WizardExtStep, M extends WizardExtModel<E>> void installWizardUIListeners(final WizardExtUI<E, M> ui) { - - - PropertyChangeListener dispatcher = new PropertyChangeListener() { - - @Override - @SuppressWarnings("unchecked") - public void propertyChange(PropertyChangeEvent evt) { - String propertyName = evt.getPropertyName(); - if (WizardExtModel.WAS_STARTED_PROPERTY_NAME.equals(propertyName)) { - ui.onWasStarted(); - return; - } - WizardExtModel<E> model = (WizardExtModel<E>) evt.getSource(); - if (WizardModel.STEPS_PROPERTY_NAME.equals(propertyName)) { - List<E> steps = (List<E>) evt.getNewValue(); - ui.onStepsChanged( - steps.toArray((E[]) Array.newInstance( - model.getStepClass(), steps.size())) - ); - return; - } - if (WizardModel.STEP_PROPERTY_NAME.equals(propertyName)) { - ui.onStepChanged((E) evt.getOldValue(), (E) evt.getNewValue()); - return; - } - if (WizardModel.VALID_STEP_PROPERTY_NAME.equals(propertyName)) { - Boolean value = (Boolean) evt.getNewValue(); - if (value == null || !value) { - ui.onModelStateChanged(WizardState.NEED_FIX); - } else { - ui.onModelStateChanged(WizardState.PENDING); - } - return; - } - if (WizardExtModel.MODEL_STATE_PROPERTY_NAME.equals(propertyName)) { - //TODO should be unicast : only for good stepUI ? - ui.onModelStateChanged((WizardState) evt.getNewValue()); - return; - } - if (WizardExtModel.STEP_STATE_PROPERTY_NAME.equals(propertyName)) { - IndexedPropertyChangeEvent e = (IndexedPropertyChangeEvent) evt; - int stepIndex = e.getIndex(); - E step = model.getSteps().get(stepIndex); - ui.onOperationStateChanged(step, (WizardState) evt.getNewValue()); - } - } - }; - M model = ui.getModel(); - log.info("Adding dispatcher " + dispatcher + " to model " + model); - model.addPropertyChangeListener(dispatcher); - } - -} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardState.java b/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardState.java deleted file mode 100644 index 12e9fb4..0000000 --- a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardState.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.wizard.ext; - -/** - * Pour caractériser l'état d'une opération. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public enum WizardState { - - /** quand l'opération n'a pas encore été réalisée */ - PENDING, - - /** quand l'opération est en cours */ - RUNNING, - - /** quand l'opération est annulé en cours d'exécution */ - CANCELED, - - /** quand une erreur s'est produite pendant l'exécution */ - FAILED, - - /** quand l'exécution s'est terminée mais requière des corrections */ - NEED_FIX, - - /** quand l'exécution s'est terminée et ne requière pas de correction */ - SUCCESSED -} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/Base64Coder.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/Base64Coder.java new file mode 100644 index 0000000..412f92e --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/Base64Coder.java @@ -0,0 +1,264 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +/** + * A Base64 Encoder/Decoder. + * + * + * This class is used to encode and decode data in Base64 format as described in RFC 1521. + * + * + * This is "Open Source" software and released under the <a href="http://www.gnu.org/licenses/lgpl.html">GNU/LGPL</a> license.<br> + * It is provided "as is" without warranty of any kind.<br> + * Copyright 2003: Christian d'Heureuse, Inventec Informatik AG, Switzerland.<br> + * Home page: <a href="http://www.source-code.biz">www.source-code.biz</a><br> + * + * + * Version history:<br> + * 2003-07-22 Christian d'Heureuse (chdh): Module created.<br> + * 2005-08-11 chdh: Lincense changed from GPL to LGPL.<br> + * 2006-11-21 chdh:<br> + * Method encode(String) renamed to encodeString(String).<br> + * Method decode(String) renamed to decodeString(String).<br> + * New method encode(byte[],int) added.<br> + * New method decode(String) added.<br> + */ + +public class Base64Coder { + + // Mapping table from 6-bit nibbles to Base64 characters. + + private static char[] map1 = new char[64]; + + static { + int i = 0; + for (char c = 'A'; c <= 'Z'; c++) { + map1[i++] = c; + } + for (char c = 'a'; c <= 'z'; c++) { + map1[i++] = c; + } + for (char c = '0'; c <= '9'; c++) { + map1[i++] = c; + } + map1[i++] = '+'; + map1[i] = '/'; + } + + // Mapping table from Base64 characters to 6-bit nibbles. + + private static byte[] map2 = new byte[128]; + + static { + for (int i = 0; i < map2.length; i++) { + map2[i] = -1; + } + for (int i = 0; i < 64; i++) { + map2[map1[i]] = (byte) i; + } + } + + /** + * Read the object from Base64 string. + * + * @param s the string representation of serialized object. + * @param gzip if gzip stream + * @return the deserialize object + * @throws java.io.IOException if any io pb + * @throws ClassNotFoundException if class not found ? + */ + public static Object deserialize(String s, boolean gzip) throws IOException, + ClassNotFoundException { + byte[] data = Base64Coder.decode(s); + InputStream stream = new ByteArrayInputStream(data); + if (gzip) { + stream = new GZIPInputStream(stream); + } + ObjectInputStream ois = new ObjectInputStream(stream); + Object o = ois.readObject(); + ois.close(); + return o; + } + + /** + * Write the object to a Base64 string. + * + * @param o the object to serialize + * @param gzip if gzip stream + * @return the string representation + * @throws java.io.IOException if any io pb + */ + public static String serialize(Object o, boolean gzip) throws IOException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + ObjectOutputStream oos; + if (gzip) { + oos = new ObjectOutputStream(new GZIPOutputStream(stream)); + } else { + oos = new ObjectOutputStream(stream); + } + oos.writeObject(o); + oos.close(); + return new String(Base64Coder.encode(stream.toByteArray())); + } + + /** + * Encodes a string into Base64 format. + * No blanks or line breaks are inserted. + * + * @param s a String to be encoded. + * @return A String with the Base64 encoded data. + */ + public static String encodeString(String s) { + return new String(encode(s.getBytes())); + } + + /** + * Encodes a byte array into Base64 format. + * No blanks or line breaks are inserted. + * + * @param in an array containing the data bytes to be encoded. + * @return A character array with the Base64 encoded data. + */ + public static char[] encode(byte[] in) { + return encode(in, in.length); + } + + /** + * Encodes a byte array into Base64 format. + * No blanks or line breaks are inserted. + * + * @param in an array containing the data bytes to be encoded. + * @param iLen number of bytes to process in <code>in</code>. + * @return A character array with the Base64 encoded data. + */ + public static char[] encode(byte[] in, int iLen) { + int oDataLen = (iLen * 4 + 2) / 3; // output length without padding + int oLen = ((iLen + 2) / 3) * 4; // output length including padding + char[] out = new char[oLen]; + int ip = 0; + int op = 0; + while (ip < iLen) { + int i0 = in[ip++] & 0xff; + int i1 = ip < iLen ? in[ip++] & 0xff : 0; + int i2 = ip < iLen ? in[ip++] & 0xff : 0; + int o0 = i0 >>> 2; + int o1 = ((i0 & 3) << 4) | (i1 >>> 4); + int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); + int o3 = i2 & 0x3F; + out[op++] = map1[o0]; + out[op++] = map1[o1]; + out[op] = op < oDataLen ? map1[o2] : '='; + op++; + out[op] = op < oDataLen ? map1[o3] : '='; + op++; + } + return out; + } + + /** + * Decodes a string from Base64 format. + * + * @param s a Base64 String to be decoded. + * @return A String containing the decoded data. + * @throws IllegalArgumentException if the input is not valid Base64 encoded data. + */ + public static String decodeString(String s) { + return new String(decode(s)); + } + + /** + * Decodes a byte array from Base64 format. + * + * @param s a Base64 String to be decoded. + * @return An array containing the decoded data bytes. + * @throws IllegalArgumentException if the input is not valid Base64 encoded data. + */ + public static byte[] decode(String s) { + return decode(s.toCharArray()); + } + + /** + * Decodes a byte array from Base64 format. + * No blanks or line breaks are allowed within the Base64 encoded data. + * + * @param in a character array containing the Base64 encoded data. + * @return An array containing the decoded data bytes. + * @throws IllegalArgumentException if the input is not valid Base64 encoded data. + */ + public static byte[] decode(char[] in) { + int iLen = in.length; + if (iLen % 4 != 0) { + throw new IllegalArgumentException("Length of Base64 encoded input string is not a multiple of 4."); + } + while (iLen > 0 && in[iLen - 1] == '=') { + iLen--; + } + int oLen = (iLen * 3) / 4; + byte[] out = new byte[oLen]; + int ip = 0; + int op = 0; + while (ip < iLen) { + int i0 = in[ip++]; + int i1 = in[ip++]; + int i2 = ip < iLen ? in[ip++] : 'A'; + int i3 = ip < iLen ? in[ip++] : 'A'; + if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) { + throw new IllegalArgumentException("Illegal character in Base64 encoded data."); + } + int b0 = map2[i0]; + int b1 = map2[i1]; + int b2 = map2[i2]; + int b3 = map2[i3]; + if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) { + throw new IllegalArgumentException("Illegal character in Base64 encoded data."); + } + int o0 = (b0 << 2) | (b1 >>> 4); + int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2); + int o2 = ((b2 & 3) << 6) | b3; + out[op++] = (byte) o0; + if (op < oLen) { + out[op++] = (byte) o1; + } + if (op < oLen) { + out[op++] = (byte) o2; + } + } + return out; + } + + // Dummy constructor. + + private Base64Coder() { + } + +} // end class Base64Coder + diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/ComponentDescriptor.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/ComponentDescriptor.java new file mode 100644 index 0000000..cf68946 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/ComponentDescriptor.java @@ -0,0 +1,70 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime; + +import java.io.Serializable; + +public class ComponentDescriptor implements Serializable { + String id; + + String javaClassName; + + String styleClass; + + ComponentDescriptor parent; + + private static final long serialVersionUID = 1L; + + + public ComponentDescriptor(String id, String javaClassName, String styleClass, ComponentDescriptor parent) { + this.id = id; + this.javaClassName = javaClassName; + this.styleClass = styleClass; + this.parent = parent; + } + + + public String getId() { + return id; + } + + + public String getJavaClassName() { + return javaClassName; + } + + + public String getStyleClass() { + return styleClass; + } + + + public ComponentDescriptor getParent() { + return parent; + } + + + @Override + public String toString() { + return "ComponentDescriptor[" + id + ", " + javaClassName + ", " + styleClass + "]"; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/DataBindingListener.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/DataBindingListener.java new file mode 100644 index 0000000..a558d41 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/DataBindingListener.java @@ -0,0 +1,65 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + + +/** + * A <code>PropertyChangeListener</code> which processes a data binding when it receives a + * <code>PropertyChangeEvent</code>. + */ +public class DataBindingListener implements PropertyChangeListener { + private JAXXObject object; + + private String dest; + + /** + * Creates a new <code>DataBindingListener</code> which will run the given data binding + * when it receives a <code>PropertyChangeEvent</code>. + * + * @param object the object in which the data binding exists + * @param dest the name of the data binding to run + */ + public DataBindingListener(JAXXObject object, String dest) { + this.object = object; + this.dest = dest; + } + + + /** + * Processes the data binding in response to a <code>PropertyChangeEvent</code>. + * + * @param e the event which triggered the binding + */ + @Override + public void propertyChange(PropertyChangeEvent e) { + object.processDataBinding(dest); + + // for now, handle dependency changes by always removing & reapplying + // the binding. We should be more efficient and only do this when it's + // actually necessary + object.removeDataBinding(dest); + object.applyDataBinding(dest); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/DataBindingUpdateListener.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/DataBindingUpdateListener.java new file mode 100644 index 0000000..2523d87 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/DataBindingUpdateListener.java @@ -0,0 +1,65 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + + +/** + * A <code>PropertyChangeListener</code> which removes and re-applies a data binding + * when it receives a <code>PropertyChangeEvent</code>. + */ +public class DataBindingUpdateListener implements PropertyChangeListener { + private JAXXObject object; + + private String dest; + + /** + * Creates a new <code>DataBindingUpdateListener</code> which will remove and re-apply a + * data binding when it receives a <code>PropertyChangeEvent</code>. + * + * @param object the object in which the data binding exists + * @param dest the name of the data binding to reapply + */ + public DataBindingUpdateListener(JAXXObject object, String dest) { + this.object = object; + this.dest = dest; + } + + + public String getBindingName() { + return dest; + } + + + /** + * Updates the data binding in response to a <code>PropertyChangeEvent</code>. + * + * @param e the event which triggered the binding + */ + @Override + public void propertyChange(PropertyChangeEvent e) { + object.removeDataBinding(dest); + object.applyDataBinding(dest); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/FileChooserUtil.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/FileChooserUtil.java new file mode 100644 index 0000000..b51124b --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/FileChooserUtil.java @@ -0,0 +1,358 @@ +package org.nuiton.jaxx.runtime; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.FileUtil; + +import javax.swing.JFileChooser; +import java.awt.Component; +import java.io.File; + +/** + * To help choosing a file / directory. + * + * Was previously in {@code org.nuiton.util.FileUtil} from + * {@code nuiton-utils} project. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.16 + * @deprecated since 2.15, prefer use {@link JaxxFileChooser}. + */ +public class FileChooserUtil { + + /** Logger. */ + private static final Log log = LogFactory.getLog(FileChooserUtil.class); + + public static final File DEFAULT_CURRENT_DIRECTORY_FILE = new File("."); + + protected static File currentDirectory = DEFAULT_CURRENT_DIRECTORY_FILE; + + public static void setCurrentDirectory(File dir) { + JaxxFileChooser.setCurrentDirectory(currentDirectory ); + } + + public static File getCurrentDirectory() { + return JaxxFileChooser.getCurrentDirectory(); + } + + public static boolean isCurrentDirectoryDefault() { + return JaxxFileChooser.isCurrentDirectoryDefault(); + } + + protected FileChooserUtil() { + // no instance please + } + + + public static class PatternChooserFilter extends javax.swing.filechooser.FileFilter { + protected String pattern; + + protected String description; + + public PatternChooserFilter(String pattern, String description) { + this.pattern = pattern; + this.description = description; + } + + @Override + public boolean accept(File f) { + return f.isDirectory() || f.getAbsolutePath().matches(pattern); + } + + @Override + public String getDescription() { + return description; + } + + } + + + /** + * Retourne le nom du fichier entre dans la boite de dialogue. + * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. + * + * @param patternOrDescriptionFilters les filtres a utiliser, les chaines doivent etre données + * par deux, le pattern du filtre + la description du filtre + * @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé + * @see #getFile(javax.swing.filechooser.FileFilter...) + */ + public static File getFile(String... patternOrDescriptionFilters) { + File result; + result = getFile(null, patternOrDescriptionFilters); + return result; + } + + /** + * Retourne le nom du fichier entre dans la boite de dialogue. + * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. + * + * @param filters les filtres a ajouter + * @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé + */ + public static File getFile(javax.swing.filechooser.FileFilter... filters) { + return getFile(null, filters); + } + + /** + * Retourne le nom du fichier entre dans la boite de dialogue. + * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. + * + * @param parent le component parent du dialog + * @param patternOrDescriptionFilters les filtres a utiliser, les chaines doivent etre données + * par deux, le pattern du filtre + la description du filtre + * @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé + * @see #getFile(javax.swing.filechooser.FileFilter...) + */ + public static File getFile(Component parent, + String... patternOrDescriptionFilters) { + File result; + result = getFile("Ok", "Ok", parent, patternOrDescriptionFilters); + return result; + } + + /** + * Retourne le nom du fichier entre dans la boite de dialogue. + * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. + * + * @param title le titre de la boite de dialogue + * @param approvalText le label du boutton d'acceptation + * @param parent le component parent du dialog + * @param patternOrDescriptionFilters les filtres a utiliser, les chaines doivent etre données + * par deux, le pattern du filtre + la description du filtre + * @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé + * @see #getFile(javax.swing.filechooser.FileFilter...) + */ + public static File getFile(String title, + String approvalText, + Component parent, + String... patternOrDescriptionFilters) { + + if (patternOrDescriptionFilters.length % 2 != 0) { + throw new IllegalArgumentException( + "Arguments must be (pattern, description) couple"); + } + javax.swing.filechooser.FileFilter[] filters = + new javax.swing.filechooser.FileFilter[ + patternOrDescriptionFilters.length / 2]; + for (int i = 0; i < filters.length; i++) { + String pattern = patternOrDescriptionFilters[i * 2]; + String description = patternOrDescriptionFilters[i * 2 + 1]; + filters[i] = new PatternChooserFilter(pattern, description); + } + File result; + result = getFile(title, approvalText, parent, filters); + return result; + } + + + /** + * Retourne le nom du fichier entre dans la boite de dialogue. + * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. + * + * @param parent le component parent du dialog + * @param filters les filtres a ajouter + * @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé + */ + public static File getFile(Component parent, + javax.swing.filechooser.FileFilter... filters) { + return getFile("Ok", "Ok", parent, filters); + } + + /** + * Retourne le nom du fichier entre dans la boite de dialogue. + * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. + * + * @param title le titre de la boite de dialogue + * @param approvalText le label du boutton d'acceptation + * @param parent le component parent du dialog + * @param filters les filtres a ajouter + * @return le fichier accepté, ou null si rien n'est choisi ou l'utilisateur a annulé + */ + public static File getFile(String title, + String approvalText, + Component parent, + javax.swing.filechooser.FileFilter... filters) { + try { + JFileChooser chooser = new JFileChooser(currentDirectory); + + chooser.setDialogType(JFileChooser.CUSTOM_DIALOG); + if (filters.length > 0) { + if (filters.length == 1) { + chooser.setFileFilter(filters[0]); + } else { + for (javax.swing.filechooser.FileFilter filter : filters) { + chooser.addChoosableFileFilter(filter); + } + } + } + chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + chooser.setDialogTitle(title); + int returnVal = chooser.showDialog(parent, approvalText); + if (returnVal == JFileChooser.APPROVE_OPTION) { + File theFile = chooser.getSelectedFile(); + if (theFile != null) { + currentDirectory = theFile; + return theFile.getAbsoluteFile(); + } + } + } catch (Exception eee) { + log.warn("Erreur:", eee); + } + return null; + } + + /** + * Retourne le nom du fichier entre dans la boite de dialogue. + * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. + * + * @param title le titre de la boite de dialogue + * @param approvalText le label du boutton d'acceptation + * @param parent le component parent du dialog + * @param patternOrDescriptionFilters les filtres a utiliser, les chaines doivent etre données + * par deux, le pattern du filtre + la description du filtre + * @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé + */ + public static File saveFile(String filename, + String title, + String approvalText, + Component parent, + String... patternOrDescriptionFilters) { + + if (patternOrDescriptionFilters.length % 2 != 0) { + throw new IllegalArgumentException( + "Arguments must be (pattern, description) couple"); + } + javax.swing.filechooser.FileFilter[] filters = + new javax.swing.filechooser.FileFilter[ + patternOrDescriptionFilters.length / 2]; + for (int i = 0; i < filters.length; i++) { + String pattern = patternOrDescriptionFilters[i * 2]; + String description = patternOrDescriptionFilters[i * 2 + 1]; + filters[i] = new FileUtil.PatternChooserFilter(pattern, description); + } + File result; + result = saveFile(filename, title, approvalText, parent, filters); + return result; + } + + /** + * Retourne le nom du fichier entre dans la boite de dialogue. + * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null. + * + * @param title le titre de la boite de dialogue + * @param approvalText le label du boutton d'acceptation + * @param parent le component parent du dialog + * @param filters les filtres a ajouter + * @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé + */ + public static File saveFile(String filename, + String title, + String approvalText, + Component parent, + javax.swing.filechooser.FileFilter... filters) { + File selectedFile = new File(getCurrentDirectory(), filename); + JFileChooser chooser = new JFileChooser(selectedFile); + + chooser.setDialogType(JFileChooser.SAVE_DIALOG); + chooser.setSelectedFile(selectedFile); + if (filters.length > 0) { + if (filters.length == 1) { + chooser.setFileFilter(filters[0]); + } else { + for (javax.swing.filechooser.FileFilter filter : filters) { + chooser.addChoosableFileFilter(filter); + } + } + } + chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + chooser.setDialogTitle(title); + + File result = null; + + int returnVal = chooser.showDialog(parent, approvalText); + if (returnVal == JFileChooser.APPROVE_OPTION) { + result = chooser.getSelectedFile(); + if (result != null) { + setCurrentDirectory(result); + result = result.getAbsoluteFile(); + } + } + return result; + } + + /** + * @return le nom du repertoire entre dans la boite de dialogue. + * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne + * null. + */ + public static String getDirectory() { + return getDirectory(null, "Ok", "Ok"); + } + + /** + * @param title le nom de la boite de dialogue + * @param approvalText le texte de l'action d'acceptation du répertoire dans le file chooser + * @return le nom du repertoire entre dans la boite de dialogue. + * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne + * null. + */ + public static String getDirectory(String title, String approvalText) { + return getDirectory(null, title, approvalText); + } + + /** + * @param parent le component parent du dialog + * @param title le nom de la boite de dialogue + * @param approvalText le texte de l'action d'acceptation du répertoire dans le file chooser + * @return le nom du repertoire entre dans la boite de dialogue. + * Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne + * null. + */ + public static String getDirectory(Component parent, + String title, + String approvalText) { + try { + JFileChooser chooser = new JFileChooser(currentDirectory); + chooser.setDialogType(JFileChooser.CUSTOM_DIALOG); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + chooser.setDialogTitle(title); + int returnVal = chooser.showDialog(parent, approvalText); + if (returnVal == JFileChooser.APPROVE_OPTION) { + File theFile = chooser.getSelectedFile(); + if (theFile != null) { + currentDirectory = theFile; + if (theFile.isDirectory()) { + return theFile.getAbsolutePath(); + } + } + } else { + return null; + } + } catch (Exception eee) { + log.warn("Erreur:", eee); + } + return null; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXAction.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXAction.java new file mode 100644 index 0000000..cfcd6d8 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXAction.java @@ -0,0 +1,42 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime; + +import org.nuiton.jaxx.runtime.context.JAXXInitialContext; + +/** + * This is the contract to be realized by any class to be used as Action class for an ui. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public interface JAXXAction { + + /** + * Prepare the initial context of the ui. + * + * @param parentContent the context of the parent of the ui (can be null if no parent is required) + * @param datas other datas to inject in initial context + * @return the {@link JAXXInitialContext} to be injected in the ui via the constructor of the {@link JAXXObject} + */ + JAXXInitialContext init(JAXXContext parentContent, Object... datas); + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXBinding.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXBinding.java new file mode 100644 index 0000000..33d2cf7 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXBinding.java @@ -0,0 +1,57 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime; + +import java.beans.PropertyChangeListener; + +/** + * Created: 5 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + * + * Mise a jour: $Date$ par : + * $Author$ + */ +public interface JAXXBinding extends PropertyChangeListener { + /** @return the unique id of a binding */ + String getId(); + + /** @return the {@link JAXXObject} which owns the binding */ + JAXXObject getSource(); + + /** + * This state is not used actually, but will be usefull later... + * + * @return {@code true} if binding was registred as a default binding, {@code false} otherwise + */ + boolean isDefaultBinding(); + + /** Apply the binding without processing it (say just install listeners). */ + void applyDataBinding(); + + /** Processes the binding. */ + void processDataBinding(); + + /** Remove the binding. */ + void removeDataBinding(); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXContext.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXContext.java new file mode 100644 index 0000000..f015fba --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXContext.java @@ -0,0 +1,129 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime; + +/** + * The {@link JAXXContext} contract defines a generic context. + * + * A context contains two king of entries : + * + * <h2>Unamed entry</h2> + * a such entry maps filter only on the clas of the object of the entry. + * + * To add a <b>unamed</b> entry, use {@link #setContextValue(Object)} and {@link #getContextValue(Class)} to reteave a + * such entry. + * + * <h2>named entry</h2> + * a such entry filter on class of the object and on the name of the entry. + * + * To add a <b>named</b> entry, use {@link #setContextValue(Object, String)} and {@link #getContextValue(Class, String)} + * to reteave a such entry. + * + * @author letellier + * @author Tony Chemit - chemit@codelutin.com + */ +public interface JAXXContext { + + /** + * Push in the context a new unamed entry. + * + * If a previous entry exists in context (unamed and same class), it will be removed. + * + * @param <T> type of data to set in context + * @param o the value to push in context + */ + <T> void setContextValue(T o); + + /** + * * Push in the context a new amed entry. + * + * If a previous entry exists in context (same name and class), it will be removed. + * + * @param <T> type of data to set in context + * @param o the value to push in context + * @param name the name of the new entry + */ + <T> void setContextValue(T o, String name); + + /** + * Remove from context the value with the given klazz as an unamed entry + * + * @param <T> type of data to remove from context + * @param klazz the klazz entry + */ + <T> void removeContextValue(Class<T> klazz); + + /** + * Remove from context the value with the given klazz as an unamed (if name is null) or named entry + * + * @param <T> type of data to remove from context + * @param klazz the klazz entry + * @param name extra name of the entry + */ + <T> void removeContextValue(Class<T> klazz, String name); + + /** + * Seek for a unamed entry in the context + * + * This is an exemple to call a method in JAXX : + * + * <code><JButton onActionPerformed='{getContextValue(Action.class).method(args[])}'/></code> + * + * @param <T> type of data to obtain from context + * @param clazz the class of unamed entry to seek in context + * @return the value of the unamed entry for the given class, or <code>null</code> if no such entry. + */ + <T> T getContextValue(Class<T> clazz); + + /** + * Seek for a named entry in the context + * + * @param <T> type of data to obtain from context + * @param clazz the class of named entry to seek in context + * @param name the name of the entry to seek in context + * @return the value of the named entry for the given class, or <code>null</code> if no such entry. + */ + <T> T getContextValue(Class<T> clazz, String name); + +// /** +// * Return parent's container corresponding to the Class clazz +// * +// * @param <O> type of container to obtain from context +// * @param clazz clazz desired +// * @return parent's container +// * @deprecated since 2.0.0 : breaks neutral since Swing +// */ +// @Deprecated +// public <O extends Container> O getParentContainer(Class<O> clazz); +// +// /** +// * Return parent's container corresponding to the Class clazz +// * +// * @param <O> type of container to obtain from context +// * @param top the top container +// * @param clazz desired +// * @return parent's container +// * @deprecated since 2.0.0 : breaks neutral since Swing +// */ +// @Deprecated +// public <O extends Container> O getParentContainer(Object top, Class<O> clazz); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXObject.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXObject.java new file mode 100644 index 0000000..5a961a1 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXObject.java @@ -0,0 +1,167 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime; + +import java.awt.Container; +import java.beans.PropertyChangeListener; +import java.io.Serializable; +import java.util.Map; + +/** + * The <code>JAXXObject</code> interface is implemented by all classes + * produced by the JAXX compiler. + */ +public interface JAXXObject extends JAXXContext, Serializable { + + /** + * Retrieves an object defined in an XML tag by its ID. + * + * @param id the id of the component to retrieve + * @return the object + */ + Object getObjectById(String id); + + /** + * Pretrieves the dictonary of knwon objects indexed by their ids. + * + * @return the dictonary of objects. + */ + Map<String, Object> get$objectMap(); + + /** @return the {@link JAXXContext} attached to the object */ + JAXXContext getDelegateContext(); + + /** @return all the databinding registred on the jaxx object */ + JAXXBinding[] getDataBindings(); + + /** + * Register a new binding in the jaxx object. + * + * @param binding the binding to add + */ + void registerDataBinding(JAXXBinding binding); + + /** + * Apply the data bind by name and then process it. + * + * @param id the id of the databinding + */ + void applyDataBinding(String id); + + /** + * Processes a data binding by name. Data binding names are comprised of an object ID and a property name: + * for example, the data binding in the tag <code><JLabel id='label' text='{foo.getText()}'/></code> is + * named <code>"label.text"</code>. Processing a data binding causes it to reevaluate its expression, in this + * case <code>foo.getText()</code>. + * + * @param dest the name of the data binding to run + */ + void processDataBinding(String dest); + + /** + * Processes a data binding by name. Data binding names are comprised of an object ID and a property name: + * for example, the data binding in the tag <code><JLabel id='label' text='{foo.getText()}'/></code> is + * named <code>"label.text"</code>. Processing a data binding causes it to reevaluate its expression, in this + * case <code>foo.getText()</code>. + * + * @param dest the name of the data binding to run + * @param force flag to force binding, even if already on run + */ + void processDataBinding(String dest, boolean force); + + /** + * Remove a databinding by name. + * + * @param id the name of databinding to remove + */ + void removeDataBinding(String id); + + /** + * Obtain a binding given his id. + * + * @param bindingId the id of the binding + * @return the binding, or {@code null} if not found. + * @see JAXXBinding + * @since 2.4.2 + */ + JAXXBinding getDataBinding(String bindingId); + + /** + * All <code>JAXXObject</code> implements are capable of broadcasting <code>PropertyChangeEvent</code>, and + * furthermore (for technical reasons) must allow code in outside packages, specifically the JAXX runtime, + * to trigger these events. + * + * @param name the name of the property which changed + * @param oldValue the old value of the property + * @param newValue the new value of the property + */ + void firePropertyChange(String name, Object oldValue, Object newValue); + + /** + * Register a general {@link PropertyChangeListener}. + * + * @param listener the listener to register + */ + void addPropertyChangeListener(PropertyChangeListener listener); + + /** + * Register a {@link PropertyChangeListener}. for the given {@code propertyName}. + * + * @param property the property name to listen + * @param listener the listener to register + */ + void addPropertyChangeListener(String property, PropertyChangeListener listener); + + /** + * Unregister a general {@link PropertyChangeListener}. + * + * @param listener the listener to unregister + */ + void removePropertyChangeListener(PropertyChangeListener listener); + + /** + * Unregister a {@link PropertyChangeListener}. for the given {@code propertyName}. + * + * @param property the property name to listen + * @param listener the listener to unregister + */ + void removePropertyChangeListener(String property, PropertyChangeListener listener); + + /** + * Return parent's container corresponding to the Class clazz + * + * @param <O> type of container to obtain from context + * @param clazz clazz desired + * @return parent's container + */ + <O extends Container> O getParentContainer(Class<O> clazz); + + /** + * Return parent's container corresponding to the Class clazz + * + * @param <O> type of container to obtain from context + * @param top the top container + * @param clazz desired + * @return parent's container + */ + <O extends Container> O getParentContainer(Object top, Class<O> clazz); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXObjectDescriptor.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXObjectDescriptor.java new file mode 100644 index 0000000..f442d6a --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXObjectDescriptor.java @@ -0,0 +1,61 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime; + +import org.nuiton.jaxx.runtime.css.Stylesheet; + +import java.io.Serializable; + +public class JAXXObjectDescriptor implements Serializable { + private ComponentDescriptor[] descriptors; + + private Stylesheet stylesheet; + + private static final long serialVersionUID = 1L; + + + public JAXXObjectDescriptor(ComponentDescriptor[] descriptors, + Stylesheet stylesheet) { + this.descriptors = descriptors; + this.stylesheet = stylesheet; + } + + + public ComponentDescriptor[] getComponentDescriptors() { + return descriptors; + } + + + public Stylesheet getStylesheet() { + return stylesheet; + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + for (ComponentDescriptor descriptor : descriptors) { + buffer.append("\n").append(descriptor); + } + buffer.append("\n").append(stylesheet); + return buffer.toString(); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXUtil.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXUtil.java new file mode 100644 index 0000000..4feb5b4 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/JAXXUtil.java @@ -0,0 +1,664 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime; + +import org.nuiton.jaxx.runtime.context.JAXXContextEntryDef; +import org.nuiton.jaxx.runtime.context.JAXXInitialContext; +import org.apache.commons.beanutils.ConstructorUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Component; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeListenerProxy; +import java.beans.PropertyChangeSupport; +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EventListener; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + +public class JAXXUtil { + + /** Logger */ + static private final Log log = LogFactory.getLog(JAXXUtil.class); + + public static final String PARENT = "parent"; + + // Maps root objects to lists of event listeners + + private static Map<Object, WeakReference<List<EventListenerDescriptor>>> + eventListeners = new WeakHashMap<Object, WeakReference<List<EventListenerDescriptor>>>(); + + private static Map<JAXXObject, WeakReference<List<DataBindingUpdateListener>>> + dataBindingUpdateListeners = new WeakHashMap<JAXXObject, WeakReference<List<DataBindingUpdateListener>>>(); + + private static final PropertyChangeListener[] EMPTY_ARRAY_PROPERTY_CHANGE_LISTENERS = new PropertyChangeListener[0]; + + private static class EventListenerDescriptor { + + Class<?> listenerClass; + + String listenerMethodName; + + String methodName; + + Object eventListener; + } + + /** + * Decodes the serialized representation of a JAXXObjectDescriptor. The + * string must be a byte-to-character mapping of the binary serialization + * data for a JAXXObjectDescriptor. See the comments in + * JAXXCompiler.createJAXXObjectDescriptorField for the rationale behind + * this (admittedly ugly) approach. + * + * @param descriptor descriptor to decode + * @return the dedoced descriptor + */ + public static JAXXObjectDescriptor decodeJAXXObjectDescriptor( + String descriptor) { + try { + return (JAXXObjectDescriptor) Base64Coder.deserialize(descriptor, + false); + } catch (IOException e) { + throw new RuntimeException("Internal error: can't-happen error", e); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Internal error: can't-happen error", e); + } + } + + public static JAXXObjectDescriptor decodeCompressedJAXXObjectDescriptor( + String descriptor) { + try { + return (JAXXObjectDescriptor) Base64Coder.deserialize(descriptor, + true); + } catch (IOException e) { + throw new RuntimeException("Internal error: can't-happen error", e); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Internal error: can't-happen error", e); + } + } + + public static <O> JAXXContextEntryDef<O> newContextEntryDef( + Class<O> klass) { + return newContextEntryDef(null, klass); + } + + public static <O> JAXXContextEntryDef<O> newContextEntryDef( + String name, Class<?> klass) { + return new JAXXContextEntryDef<O>(name, (Class<O>) klass); + } + + public static <O> JAXXContextEntryDef<List<O>> newListContextEntryDef() { + return newListContextEntryDef(null); + } + + public static <O> JAXXContextEntryDef<List<O>> newListContextEntryDef( + String name) { + Class<List<O>> castList = castList(); + return new JAXXContextEntryDef<List<O>>(name, castList); + } + + public static <K, V> JAXXContextEntryDef<Map<K, V>> newMapContextEntryDef( + String name) { + return new JAXXContextEntryDef<Map<K, V>>(Map.class, name); + } + + @SuppressWarnings({"unchecked"}) + protected static <K, V> Class<Map<K, V>> castMap() { + return (Class<Map<K, V>>) Collections.emptyMap().getClass(); + } + + @SuppressWarnings({"unchecked"}) + protected static <O> Class<List<O>> castList() { + return (Class<List<O>>) Collections.emptyList().getClass(); + } + + /** + * Method to initialize the context of a ui. + * + * @param ui the ui + * @param parentContext the context to set in ui + */ + public static void initContext(JAXXObject ui, JAXXContext parentContext) { + + if (parentContext instanceof JAXXInitialContext) { + ((JAXXInitialContext) parentContext).to(ui); + } else { + ui.setContextValue(parentContext); + } + // if parentContext is a JAXXObject then + // add an special parent entry to can go up + if (parentContext instanceof JAXXObject) { + ui.setContextValue(parentContext, PARENT); + } + } + + public static <E extends EventListener> E getEventListener( + Class<E> listenerClass, + final String listenerMethodName, + final Object methodContainer, + String methodName) { + + WeakReference<List<EventListenerDescriptor>> ref = + eventListeners.get(methodContainer); + List<EventListenerDescriptor> descriptors = ref != null ? + ref.get() : null; + if (descriptors == null) { + descriptors = new ArrayList<EventListenerDescriptor>(); + eventListeners.put( + methodContainer, + new WeakReference<List<EventListenerDescriptor>>( + descriptors)); + } else { + for (EventListenerDescriptor descriptor : descriptors) { + if (descriptor.listenerClass.equals(listenerClass) && + (listenerMethodName == null ? + descriptor.listenerMethodName == null : + listenerMethodName.equals( + descriptor.listenerMethodName)) && + methodName.equals(descriptor.methodName)) { + return (E) descriptor.eventListener; + } + } + } + + // else we need to create a new listener + final EventListenerDescriptor descriptor = new EventListenerDescriptor(); + descriptor.listenerClass = listenerClass; + descriptor.listenerMethodName = listenerMethodName; + descriptor.methodName = methodName; + try { + final List<Method> listenerMethods = + Arrays.asList(listenerClass.getMethods()); + Method listenerMethod = null; + if (listenerMethodName != null) { + for (Method listenerMethod1 : listenerMethods) { + if (listenerMethod1.getName().equals(listenerMethodName)) { + listenerMethod = listenerMethod1; + break; + } + } + } + if (listenerMethodName != null && listenerMethod == null) { + throw new IllegalArgumentException( + "no method named " + listenerMethodName + + " found in class " + listenerClass.getName()); + } + // tchemit 2010-12-01 : we must the exact method found, some none javaBeans + // api does use different signature for some of them listener + // an exemple is the TableColumnModelListener : http://download.oracle.com/javase/6/docs/api/javax/swing/event/TableColumnMo... + // This fix the bug https://forge.nuiton.org/issues/show/1124 + Class<?>[] parameterTypes; + if (listenerMethodName != null) { + + // search an exact method, so must use the exact found listener method + parameterTypes = listenerMethod.getParameterTypes(); + } else { + + // keep this horrible code which is not safe at all : + // see previous comment + parameterTypes = listenerMethods.get(0).getParameterTypes(); + } + Class<?> methodContainerClass = methodContainer.getClass(); + final Method targetMethod = + methodContainerClass.getMethod(methodName, parameterTypes); + descriptor.eventListener = + Proxy.newProxyInstance(listenerClass.getClassLoader(), + new Class<?>[]{listenerClass}, + new InvocationHandler() { + + @Override + public Object invoke(Object proxy, + Method method, + Object[] args) { + String methodName = method.getName(); + if (listenerMethodName == null && + listenerMethods.contains(method) || + methodName.equals(listenerMethodName)) { + try { + targetMethod.setAccessible(true); + return targetMethod.invoke( + methodContainer, args); + } catch (IllegalAccessException e) { + throw new RuntimeException( + "could not invoke on container " + + methodContainer, e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + if (methodName.equals("toString")) { + return toString(); + } + if (methodName.equals("equals")) { + return descriptor.eventListener == args[0]; + } + if (methodName.equals("hashCode")) { + return hashCode(); + } + return null; + } + }); + descriptors.add(descriptor); + return (E) descriptor.eventListener; + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public static <E extends EventListener> E getEventListener( + Class<E> listenerClass, + Object methodContainer, + String methodName) { + return getEventListener(listenerClass, null, methodContainer, + methodName); + } + + public static DataBindingUpdateListener getDataBindingUpdateListener( + JAXXObject object, String bindingName) { + WeakReference<List<DataBindingUpdateListener>> ref = + dataBindingUpdateListeners.get(object); + List<DataBindingUpdateListener> listeners = ref == null ? null : + ref.get(); + if (listeners == null) { + listeners = new ArrayList<DataBindingUpdateListener>(); + dataBindingUpdateListeners.put( + object, + new WeakReference<List<DataBindingUpdateListener>>( + listeners)); + } else { + for (DataBindingUpdateListener listener : listeners) { + if (bindingName.equals(listener.getBindingName())) { + return listener; + } + } + } + DataBindingUpdateListener listener = + new DataBindingUpdateListener(object, bindingName); + listeners.add(listener); + return listener; + } + + /** + * Remove all listeners registred in given {@code pcs}. + * + * @param pcs the pcs to clean + */ + public static void destroy(PropertyChangeSupport pcs) { + PropertyChangeListener[] listeners = pcs.getPropertyChangeListeners(); + for (PropertyChangeListener l : listeners) { + if (log.isInfoEnabled()) { + if (l instanceof PropertyChangeListenerProxy) { + PropertyChangeListenerProxy ll = (PropertyChangeListenerProxy) l; + log.info("remove property change listener " + ll.getPropertyName() + " : " + l); + } else { + log.info("remove property change listener " + l); + } + } + pcs.removePropertyChangeListener(l); + } + } + + /** + * Remove all listeners registred in given {@code component}. + * + * @param component the pcs to clean + */ + public static void destroy(Component component) { + PropertyChangeListener[] listeners = component.getPropertyChangeListeners(); + for (PropertyChangeListener l : listeners) { + if (log.isInfoEnabled()) { + if (l instanceof PropertyChangeListenerProxy) { + PropertyChangeListenerProxy ll = (PropertyChangeListenerProxy) l; + log.info("remove property change listener " + ll.getPropertyName() + " : " + l); + } else { + log.info("remove property change listener " + l); + } + } + component.removePropertyChangeListener(l); + } + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static boolean assignment(boolean value, + String name, + JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + + public static byte assignment(byte value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static short assignment(short value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static int assignment(int value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static long assignment(long value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static float assignment(float value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static double assignment(double value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static char assignment(char value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static Object assignment(Object value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** + * Compute the string representation of an object. + * + * Return empty string if given object is null + * + * @param value the value to write + * @return the string representation of the given object or an empty string + * if object is null. + */ + public static String getStringValue(Object value) { + String result; + result = value == null ? "" : value.toString(); + return result; + } + + /** + * Test if some entries exists in a given context and throw an + * IllegalArgumentException if not. + * + * + * @param context the context to test + * @param defs the definitions of entries to seek in context + * @throws IllegalArgumentException if the entry is not found in context. + */ + public static void checkJAXXContextEntries(JAXXContext context, + JAXXContextEntryDef<?>... defs) + throws IllegalArgumentException { + + for (JAXXContextEntryDef<?> def : defs) { + Object value = def.getContextValue(context); + + if (value == null) { + throw new IllegalArgumentException( + "the context entry [" + def + "] ] was not found in " + + "context " + context); + } + } + } + + /** + * Test if a type of entry exists in a given context and throw an + * IllegalArgumentException if not found. + * + * If entry is found, return his value in context. + * + * @param <T> the type of required data + * @param context the context to test + * @param def the definition of the entry to seek in context + * @return the value from the context + * @throws IllegalArgumentException if the entry is not found in context. + */ + public static <T> T checkJAXXContextEntry(JAXXContext context, + JAXXContextEntryDef<T> def) + throws IllegalArgumentException { + + T value = def.getContextValue(context); + + if (value == null) { + throw new IllegalArgumentException( + "the context entry [" + def + "] ] was not found in " + + "context " + context); + } + + return value; + } + + /** + * To reload a binding, the method will invoke + * <ul> + * <li>{@link JAXXBinding#removeDataBinding()}</li> + * <li>{@link JAXXBinding#applyDataBinding()}</li> + * </ul> + * + * @param binding the binding to reload. + * @since 2.4.2 + */ + public static void reloadBinding(JAXXBinding binding) { + binding.removeDataBinding(); + binding.applyDataBinding(); + } + + /** + * Convinient method to reload a given binding by his id on a JAXX ui. + * + * @param src the ui to treate + * @param bindingId the id of binding to reload. + * @since 2.4.2 + */ + public static void reloadBinding(JAXXObject src, String bindingId) { + JAXXBinding dataBinding = src.getDataBinding(bindingId); + if (dataBinding != null) { + reloadBinding(dataBinding); + } else { + if (log.isWarnEnabled()) { + log.warn("Could not found binding[" + bindingId + "] on ui " + src); + } + } + } + + /** + * Convinient method to apply more than one binding on a JAXX ui. + * + * @param src the ui to treate + * @param bindings the list of binding to process. + */ + public static void applyDataBinding(JAXXObject src, String... bindings) { + for (String binding : bindings) { + src.applyDataBinding(binding); + } + } + + /** + * Convinient method to apply more than one binding on a JAXX ui. + * + * @param src the ui to treate + * @param bindings the list of binding to process. + */ + public static void applyDataBinding(JAXXObject src, + Collection<String> bindings) { + for (String binding : bindings) { + src.applyDataBinding(binding); + } + } + + /** + * Convinient method to process more than one binding on a JAXX ui. + * + * @param src the ui to treate + * @param bindings the list of binding to process. + */ + public static void processDataBinding(JAXXObject src, String... bindings) { + for (String binding : bindings) { + src.processDataBinding(binding); + } + } + + /** + * Convinient method to remove more than one binding on a JAXX ui. + * + * @param src the ui to treate + * @param bindings the list of binding to process. + */ + public static void removeDataBinding(JAXXObject src, String... bindings) { + for (String binding : bindings) { + src.removeDataBinding(binding); + } + } + + /** + * Convinient method to remove all than one binding on a JAXX ui. + * + * @param src the ui to treate + * @since 2.10 + */ + public static void removeAllDataBindings(JAXXObject src) { + + JAXXBinding[] bindings = src.getDataBindings(); + for (JAXXBinding binding : bindings) { + removeDataBinding(src, binding.getId()); + } + + } + + /** + * detects all PropertychangedListener added by Jaxx uis (should be a {@link + * DataBindingListener} + * + * @param propertyNames the array of property names to find + * @param listeners the array of listeners to filter + * @return the filtered listeners + */ + public static PropertyChangeListener[] findJaxxPropertyChangeListener( + String[] propertyNames, PropertyChangeListener... listeners) { + if (listeners == null || listeners.length == 0) { + return EMPTY_ARRAY_PROPERTY_CHANGE_LISTENERS; + } + List<String> pNames = Arrays.asList(propertyNames); + + List<PropertyChangeListener> toRemove = + new ArrayList<PropertyChangeListener>(); + + for (PropertyChangeListener listener : listeners) { + String pName = null; + PropertyChangeListenerProxy plistener = null; + if (listener instanceof PropertyChangeListenerProxy) { + plistener = (PropertyChangeListenerProxy) listener; + if (!pNames.contains(plistener.getPropertyName())) { + // not on the good property + continue; + } + listener = (PropertyChangeListener) plistener.getListener(); + pName = plistener.getPropertyName(); + } + if (plistener != null && + pName != null && + listener instanceof DataBindingListener) { + if (log.isDebugEnabled()) { + log.debug("find config listener to remove [" + pName + + "] : " + listener); + } + toRemove.add(plistener); + //toRemove.add(listener); + } + } + return toRemove.toArray(new PropertyChangeListener[toRemove.size()]); + } + + /** + * Overrides the commons method to have generict cast fiex. + * + * @param type the type of objet to instanciate + * @param prototype prototype of the constructor + * @param parms params to pass to constructor + * @param <O> type of object to create + * @return the new object + * @throws Exception if something wrong + * @since 2.1 + */ + @SuppressWarnings({"unchecked"}) + public static <O> O invokeConstructor(Class<O> type, + Class<?>[] prototype, + Object... parms) throws Exception { + return (O) ConstructorUtils.invokeConstructor(type, + parms, + prototype + ); + } + + /** + * Copy to clipBoard the content of the given text. + * + * @param text text to copy to clipboard + * @since 2.17 + */ + public static void copyToClipBoard(String text) { + + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + if (log.isInfoEnabled()) { + log.info("Put in clipboard :\n" + text); + } + StringSelection selection = new StringSelection(text); + clipboard.setContents(selection, selection); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/SwingUtil.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/SwingUtil.java new file mode 100644 index 0000000..3554caa --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/SwingUtil.java @@ -0,0 +1,1531 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime; + +import com.google.common.base.Predicate; +import org.nuiton.jaxx.runtime.swing.Item; +import org.nuiton.jaxx.runtime.swing.JAXXComboBox; +import org.nuiton.jaxx.runtime.swing.editor.BooleanCellEditor; +import org.nuiton.jaxx.runtime.swing.model.JaxxDefaultComboBoxModel; +import org.nuiton.jaxx.runtime.swing.model.JaxxDefaultListModel; +import org.nuiton.jaxx.runtime.swing.renderer.BooleanCellRenderer; +import org.nuiton.jaxx.runtime.swing.renderer.EmptyNumberTableCellRenderer; +import org.nuiton.jaxx.runtime.swing.renderer.EnumTableCellRenderer; +import org.nuiton.jaxx.runtime.swing.renderer.I18nTableCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.jxlayer.JXLayer; +import org.jdesktop.jxlayer.plaf.LayerUI; +import org.jdesktop.swingx.JXTreeTable; + +import javax.swing.ComboBoxModel; +import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JLayeredPane; +import javax.swing.JList; +import javax.swing.JRootPane; +import javax.swing.JTabbedPane; +import javax.swing.JTable; +import javax.swing.JTree; +import javax.swing.ListModel; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; +import javax.swing.text.AbstractDocument; +import javax.swing.text.JTextComponent; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Desktop; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Rectangle; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.EventObject; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.Properties; + +import static org.nuiton.i18n.I18n.t; + +/** + * The runtime swing util class with some nice stuff. + * + * Note : Replace previous class jaxx.runtime.swing.Utils in previous versions. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.2 + */ +public class SwingUtil extends JAXXUtil { + + /** Logger */ + static private final Log log = LogFactory.getLog(SwingUtil.class); + + public static final String DEFAULT_ICON_PATH = "/icons/"; + + public static final String DEFAULT_ICON_PATH_PROPERTY = "default.icon.path"; + + private static Field numReaders; + + private static Field notifyingListeners; + + public static final String ICON_PREFIX = "icon."; + + public static final String COLOR_PREFIX = "color."; + + public static Dimension newMinDimension() { + return new Dimension(0, 0); + } + + public static Dimension newMaxXDimension() { + return new Dimension(Short.MAX_VALUE, 0); + } + + public static Dimension newMaxYDimension() { + return new Dimension(0, Short.MAX_VALUE); + } + + public static Dimension newMaxXYDimension() { + return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); + } + + public static void setText(final JTextComponent c, final String text) { + try { + // AbstractDocument deadlocks if we try to acquire a write lock while a read lock is held by the current thread + // If there are any readers, dispatch an invokeLater. This should only happen in the event of circular bindings. + // Similarly, circular bindings can result in an "Attempt to mutate in notification" error, which we deal with + // by checking for the 'notifyingListeners' property. + AbstractDocument document = (AbstractDocument) c.getDocument(); + if (numReaders == null) { + numReaders = AbstractDocument.class.getDeclaredField("numReaders"); + numReaders.setAccessible(true); + } + if (notifyingListeners == null) { + notifyingListeners = AbstractDocument.class.getDeclaredField("notifyingListeners"); + notifyingListeners.setAccessible(true); + } + + if (notifyingListeners.get(document).equals(Boolean.TRUE)) { + return; + } + + if ((Integer) numReaders.get(document) > 0) { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + if (!c.getText().equals(text)) { + c.setText(text); + } + } + }); + return; + } + + String oldText = c.getText(); + if (oldText == null || !oldText.equals(text)) { + c.setText(text); + } + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (SecurityException e) { + c.setText(text); + } + } + + /** + * Fill a combo box model with some datas, and select after all the given object + * + * @param combo the combo to fill + * @param data data ot inject in combo + * @param select the object to select in combo after reflling his model + */ + public static void fillComboBox(JComboBox combo, Collection<?> data, + Object select) { + + ComboBoxModel comboBoxModel = combo.getModel(); + + if (comboBoxModel instanceof JaxxDefaultComboBoxModel) { + JaxxDefaultComboBoxModel model = + (JaxxDefaultComboBoxModel) comboBoxModel; + + // evince the model + model.removeListDataListener(combo); + + // set data + model.setAllElements((Collection) data); + + // attach the model + model.addListDataListener(combo); + model.setSelectedItem(select); + } else if (comboBoxModel instanceof DefaultComboBoxModel) { + DefaultComboBoxModel model = (DefaultComboBoxModel) combo.getModel(); + // evince the model + model.removeListDataListener(combo); + model.removeAllElements(); + if (data != null) { + for (Object o : data) { + model.addElement(o); + } + } + // attach the model + model.addListDataListener(combo); + model.setSelectedItem(select); + } else { + throw new IllegalArgumentException( + "this method need a DefaultComboBoxModel for " + + "this model but was " + combo.getModel().getClass()); + } + + } + + /** + * Fill a list model with some datas, and select after all the given object + * + * @param list the list to fill + * @param data data ot inject in combo + * @param select the object to select in combo after reflling his model + */ + public static void fillList(JList list, Collection<?> data, Object select) { + ListModel listModel = list.getModel(); + if (listModel instanceof JaxxDefaultListModel) { + JaxxDefaultListModel model = (JaxxDefaultListModel) listModel; + + // evince the model +// model.removeListDataListener(combo); + model.setAllElements(data); + + // attach the model +// model.addListDataListener(combo); + list.setSelectedValue(select, true); + } else if (listModel instanceof DefaultListModel) { + DefaultListModel model = (DefaultListModel) listModel; + // evince the model +// model.removeListDataListener(combo); + model.removeAllElements(); + if (data != null) { + for (Object o : data) { + model.addElement(o); + } + } + // attach the model +// model.addListDataListener(combo); + list.setSelectedValue(select, true); + } else { + throw new IllegalArgumentException( + "this method need a DefaultListModel for this model " + + "but was " + listModel.getClass()); + } + } + + /** + * TODO move this to JAXXComboBox. + * + * Fill a combo box model with some datas, and select after all the given object + * + * @param combo the combo to fill + * @param data data ot inject in combo + * @param select the object to select in combo after reflling his model + * @param firstNull add a first null element + * @deprecated since 1.7.XXX this code is moved to JAXXComboBox + */ + @Deprecated + public static void fillComboBox(JAXXComboBox combo, + Collection<?> data, + Object select, boolean firstNull) { + List<Item> items = new ArrayList<Item>(); + if (firstNull) { + items.add(new Item("null", " ", null, false)); + } + if (data != null) { + for (Object d : data) { + Item item = new Item(d.toString(), d.toString(), d, + d.equals(select)); + items.add(item); + } + } + combo.setItems(items); + } + + /** + * Return parent's container corresponding to the Class clazz + * + * @param <O> type of container to obtain from context + * @param top the top container + * @param clazz desired + * @return parent's container + */ + @SuppressWarnings({"unchecked"}) + public static <O extends Container> O getParentContainer(Object top, + Class<O> clazz) { + + return getParent(top, clazz); + } + + + /** + * Find a parent of the given {@code top} object using the container api to get up. + * + * Stop on parent when it is of the given{@code clazz} type. + * + * @param <O> type of container to obtain from context + * @param top the top container + * @param clazz desired + * @return parent's container + * @since 2.5.14 + */ + public static <O> O getParent(Object top, Class<O> clazz) { + if (top == null) { + throw new IllegalArgumentException("top parameter can not be null"); + } + if (!Container.class.isAssignableFrom(top.getClass())) { + throw new IllegalArgumentException("top parameter " + top + + " is not a " + Container.class); + } + Container parent = ((Container) top).getParent(); + if (parent != null && !clazz.isAssignableFrom(parent.getClass())) { + parent = (Container) getParent(parent, clazz); + } + return (O) parent; + } + + public static int computeTableColumnWidth(JTable table, + Font font, + int columnIndex, String suffix) { + int width = 0; + if (font == null) { + font = table.getFont(); + } +// if (font == null) { +// TableColumn column = table.getColumnModel().getColumn(columnIndex); +// font = ((JComponent) column.getCellRenderer()).getFont(); +// } + FontMetrics fontMetrics = table.getFontMetrics(font); + for (int i = 0, rowCount = table.getRowCount(); i < rowCount; i++) { + String key = (String) table.getModel().getValueAt(i, 0); + int w = fontMetrics.stringWidth(key + suffix); + if (w > width) { + width = w; + } + } + return width; + } + + public static void fixTableColumnWidth(JTable table, + int columnIndex, + int width) { + TableColumn column = table.getColumnModel().getColumn(columnIndex); + column.setMaxWidth(width); + column.setMinWidth(width); + column.setWidth(width); + column.setPreferredWidth(width); + } + + public static void setTableColumnEditor(JTable table, + int columnIndex, + TableCellEditor editor) { + TableColumn column = table.getColumnModel().getColumn(columnIndex); + column.setCellEditor(editor); + } + + public static void setTableColumnRenderer(JTable table, + int columnIndex, + TableCellRenderer editor) { + TableColumn column = table.getColumnModel().getColumn(columnIndex); + column.setCellRenderer(editor); + } + + public static void setI18nTableHeaderRenderer(JTable table, + String... libelles) { + I18nTableCellRenderer defaultRenderer = + new I18nTableCellRenderer( + table.getTableHeader().getDefaultRenderer(), libelles); + table.getTableHeader().setDefaultRenderer(defaultRenderer); + } + + public static TableCellRenderer newStringTableCellRenderer( + final DefaultTableCellRenderer renderer, + final int length, + final boolean tooltip) { + + return new DefaultTableCellRenderer() { + + private static final long serialVersionUID = 1l; + + @Override + public Component getTableCellRendererComponent( + JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, + int column) { + + renderer.getTableCellRendererComponent( + table, + value, + isSelected, + hasFocus, + row, + column + ); + String val = renderer.getText(); + String val2 = val; + if (val.length() > length) { + val2 = val.substring(0, length - 3) + "..."; + } + + JComponent comp = (JComponent) + super.getTableCellRendererComponent( + table, + val2, + isSelected, + hasFocus, + row, + column + ); + if (tooltip) { + comp.setToolTipText(val); + } + return comp; + } + }; + } + + /** + * Box a component in a {@link JXLayer}. + * + * @param component the component to box + * @return the {@link JXLayer} boxing the component + */ + public static <V extends JComponent> JXLayer<V> boxComponentWithJxLayer(V component) { + JXLayer<V> layer = getLayer(component); + if (layer != null) { + return layer; + } + layer = new JXLayer<V>(); + layer.setView(component); + return layer; + } + + public static List<JComponent> getLayeredComponents(JAXXObject object) { + List<JComponent> result = new ArrayList<JComponent>(); + for (Entry<String, Object> child : object.get$objectMap().entrySet()) { + if (child.getValue() == null) { + log.warn("find a null object in $objectMap " + child.getKey()); + continue; + } + if (JComponent.class.isAssignableFrom(child.getValue().getClass())) { + JComponent comp = (JComponent) child.getValue(); + if (isLayered(comp)) { + result.add(comp); + } + } + } + return result; + } + + public static <V extends JComponent> JXLayer<V> getLayer(V comp) { + if (!isLayered(comp)) { + return null; + } + return (JXLayer<V>) comp.getParent(); + } + + public static void setLayerUI(JComponent comp, LayerUI<JComponent> ui) { + JXLayer<JComponent> layer = getLayer(comp); + layer.setUI(ui); + } + + public static boolean isLayered(JComponent comp) { + Container parent = comp.getParent(); + return parent != null && parent instanceof JXLayer<?>; + } + + /** + * recherche les composants portant le meme nom que les champs de la classe + * clazz. Cette methode est statique pour pouvoir eventuellement l'utiliser + * dans un autre context (je pense par exemple a la generation jaxx). + * + * Si la recherche echoue pour quelque raison que se soit, aucune exception + * n'est leve, et la map retournee est tout simplement vide ou incomplete + * + * @param clazz la classe ou recherche les champs + * @param container le container ou rechercher les composants d'edition + * @return le dictionnaire des composants recherches. + */ + public static Map<String, JComponent> lookingForEditor( + Class<?> clazz, + Container container) { + Map<String, JComponent> result = new HashMap<String, JComponent>(); + try { + // looking for all component with name set + Map<String, JComponent> allNamedComponent = + new HashMap<String, JComponent>(); + List<Container> todo = new LinkedList<Container>(); + todo.add(container); + while (todo.size() > 0) { + for (ListIterator<Container> i = todo.listIterator(); + i.hasNext(); ) { + Container parent = i.next(); + i.remove(); + for (Component c : parent.getComponents()) { + if (c instanceof Container) { + i.add((Container) c); + String name = c.getName(); + if (c instanceof JComponent && + name != null && !"".equals(name)) { + allNamedComponent.put(name, (JComponent) c); + } + } + } + } + } + + // looking for all properties on class + BeanInfo info = Introspector.getBeanInfo(clazz); + PropertyDescriptor[] props = info.getPropertyDescriptors(); + + // find if one properties have same name that component + for (PropertyDescriptor prop : props) { + String name = prop.getName(); + if (allNamedComponent.containsKey(name)) { + result.put(name, allNamedComponent.get(name)); + } + } + + } catch (IntrospectionException eee) { + log.warn("Can't introspect bean", eee); + } + + if (log.isDebugEnabled()) { + log.debug("Result: " + result); + } + + return result; + } + + /** + * Centrer un component graphique au center d'un autre component. + * + * <b>Note:</b> si le parent est null, alors on ne fait rien. + * + * @param parent le component parent + * @param component le component à centrer + */ + public static void center(Component parent, Component component) { + if (parent == null) { + return; + } + Rectangle r = parent.getBounds(); + int x = r.x + (r.width - component.getSize().width) / 2; + int y = r.y + (r.height - component.getSize().height) / 2; + component.setLocation(x, y); + } + + /** + * Try to load the Nimbus look and feel. + * + * @throws UnsupportedLookAndFeelException if nimbus is not applicable + * @throws ClassNotFoundException + * @throws InstantiationException + * @throws IllegalAccessException + */ + public static void initNimbusLoookAndFeel() throws UnsupportedLookAndFeelException, ClassNotFoundException, InstantiationException, IllegalAccessException { + + for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { + if ("Nimbus".equals(laf.getName())) { + UIManager.setLookAndFeel(laf.getClassName()); + } + } + } + + /** + * Load the ui.properties file and set in {@link UIManager} colors and + * icons found. + * + * @param defaultUIConfig le path vers le fichier de la config d'ui par + * défaut (doit etre dansle class-path) + * @param extraUIConfig le path vers une surcharge de la config d'ui + * (doit etre dans le class-path) + * @throws IOException if could not load the ui.properties file + */ + public static void loadUIConfig(String defaultUIConfig, + String extraUIConfig) throws IOException { + + Properties p = new Properties(); + log.info("loading default UI config " + defaultUIConfig); + p.load(SwingUtil.class.getResourceAsStream(defaultUIConfig)); + if (log.isDebugEnabled()) { + log.debug(p.toString()); + } + if (extraUIConfig != null) { + InputStream extraStream = + SwingUtil.class.getResourceAsStream(extraUIConfig); + if (extraStream == null) { + log.warn("could not find extraUIConfig : " + extraUIConfig); + } else { + log.info("loading extra UI config " + extraUIConfig); + Properties p2 = new Properties(p); + p2.load(extraStream); + if (log.isDebugEnabled()) { + log.debug(p2.toString()); + } + p.putAll(p2); + } + } + for (Entry<Object, Object> entry : p.entrySet()) { + String key = (String) entry.getKey(); + if (key.startsWith(ICON_PREFIX)) { + ImageIcon icon; + try { + icon = createImageIcon((String) entry.getValue()); + UIManager.put(key.substring(ICON_PREFIX.length()), icon); + } catch (Exception e) { + log.warn("could not load icon " + entry.getValue()); + } + continue; + } + if (key.startsWith(COLOR_PREFIX)) { + String value = (String) entry.getValue(); + String[] rgb = value.split(","); + UIManager.put( + key.substring(COLOR_PREFIX.length()), + new Color( + Integer.valueOf(rgb[0]), + Integer.valueOf(rgb[1]), + Integer.valueOf(rgb[2]) + ) + ); + } + } + } + + /** + * Load the ui.properties file and set in {@link UIManager} colors and + * icons found. + * + * @param incoming the ui resources to load. + * @since 2.1 + */ + public static void loadUIConfig(Properties incoming) { + + for (Entry<Object, Object> entry : incoming.entrySet()) { + String key = (String) entry.getKey(); + if (key.startsWith(ICON_PREFIX)) { + ImageIcon icon; + try { + icon = createImageIcon((String) entry.getValue()); + UIManager.put(key.substring(ICON_PREFIX.length()), icon); + } catch (Exception e) { + log.warn("could not load icon " + entry.getValue()); + } + continue; + } + if (key.startsWith(COLOR_PREFIX)) { + String value = (String) entry.getValue(); + String[] rgb = value.split(","); + UIManager.put( + key.substring(COLOR_PREFIX.length()), + new Color( + Integer.valueOf(rgb[0]), + Integer.valueOf(rgb[1]), + Integer.valueOf(rgb[2]) + ) + ); + } + } + } + + /** + * Iterate the components of a {@link JTabbedPane} in natural order. + * + * Says using method {@link JTabbedPane#getComponent(int)} + * + * @param tabs the + * @return the iterator + * @since 1.4 + */ + public static TabbedPaneIterator<Component> newTabbedPaneIterator( + JTabbedPane tabs) { + return new TabbedPaneIterator<Component>(false, tabs) { + + @Override + protected Component get(int index, Component comp) { + return comp; + } + }; + } + + /** + * Return the selected rows of the table in the model coordinate or empty + * array if selection is empty. + * + * @param table the table to seek + * @return the selected rows of the table in the model coordinate or empty + * array if selection is empty. + * @since 2.5.29 + */ + public static int[] getSelectedModelRows(JTable table) { + int[] selectedRows = table.getSelectedRows(); + int length = selectedRows.length; + int[] result = new int[length]; + for (int i = 0; i < length; i++) { + int selectedRow = selectedRows[i]; + result[i] = table.convertRowIndexToModel(selectedRow); + } + return result; + } + + /** + * Return the selected row of the table in the model coordinate or + * {@code -1} if selection is empty. + * + * @param table the table to seek + * @return the selected row of the table in the model coordinate or + * {@code -1} if selection is empty. + * @since 2.5.29 + */ + public static int getSelectedModelRow(JTable table) { + int result = table.getSelectedRow(); + if (result != -1) { + // can convert to model coordinate + result = table.convertRowIndexToModel(result); + } + return result; + } + + /** + * Return the selected column of the table in the model coordinate or + * {@code -1} if selection is empty. + * + * @param table the table to seek + * @return the selected column of the table in the model coordinate or + * {@code -1} if selection is empty. + * @since 2.5.29 + */ + public static int getSelectedModelColumn(JTable table) { + int result = table.getSelectedColumn(); + if (result != -1) { + // can convert to model coordinate + result = table.convertColumnIndexToModel(result); + } + return result; + } + + /** + * Select the given row index {@code rowIndex} (from the model coordinate) + * in the selection of the given table. + * + * @param table the table where to set the selection + * @param rowIndex the row index in the model coordinate to set as selection + * @since 2.5.29 + */ + public static void setSelectionInterval(JTable table, int rowIndex) { + + int rowViewIndex = table.convertRowIndexToView(rowIndex); + table.getSelectionModel().setSelectionInterval(rowViewIndex, rowViewIndex); + } + + /** + * Add the given row index {@code rowIndex} (from the model coordinate) + * in the selection of the given table. + * + * @param table the table where to set the selection + * @param rowIndex the row index in the model coordinate to add to selection + * @since 2.5.29 + */ + public static void addRowSelectionInterval(JTable table, int rowIndex) { + + int rowViewIndex = table.convertRowIndexToView(rowIndex); + table.getSelectionModel().addSelectionInterval(rowViewIndex, rowViewIndex); + } + + /** + * A simple iterator on a {@link JTabbedPane}. + * + * Implements the method {@link #get(int, Component)} to obtain + * the data required given the component (or index). + * + * You can also inverse the order by usin the method {@link #reverse()}. + * + * Note: After the use of the method {@link #reverse()} the iterator returns + * to the first element. + * + * @param <O> the type of return elements. + * @since 1.4 + */ + public static abstract class TabbedPaneIterator<O> implements Iterator<O> { + + final JTabbedPane tabs; + + boolean reverse; + + int index; + + int increment; + + protected abstract O get(int index, Component comp); + + public TabbedPaneIterator(boolean reverse, JTabbedPane tabs) { + this.tabs = tabs; + setReverse(reverse); + } + + public void reset() { + setReverse(reverse); + } + + public int size() { + return tabs.getTabCount(); + } + + public TabbedPaneIterator<O> reverse() { + setReverse(!reverse); + return this; + } + + @Override + public boolean hasNext() { + return reverse ? index > 0 : index < tabs.getTabCount(); + } + + public int getIndex() { + return index; + } + + @Override + public O next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + Component next = tabs.getComponentAt(index); + O result = get(index, next); + index += increment; + return result; + } + + @Override + public void remove() { + throw new IllegalStateException("not implemented for " + this); + } + + @Override + public String toString() { + return super.toString() + "< reverse:" + reverse + ", index:" + + index + ", size:" + tabs.getTabCount() + " >"; + } + + protected void setReverse(boolean reverse) { + if (reverse) { + index = tabs.getTabCount() - 1; + increment = -1; + } else { + index = 0; + increment = 1; + } + this.reverse = reverse; + } + } + + public static JLabel newLabel(String text, Object iconKey, int aligment) { + Icon icon = null; + if (iconKey instanceof Icon) { + icon = (Icon) iconKey; + } else if (iconKey instanceof String) { + icon = getUIManagerActionIcon((String) iconKey); + } + JLabel result; + if (icon == null) { + result = new JLabel(text, aligment); + } else { + result = new JLabel(text, icon, aligment); + } + return result; + } + + /** + * Gets the higest visible component in a ancestor hierarchy at + * specific x,y coordinates + * + * @param parent + * @param x + * @param y + * @return the deppest component + */ + public static Component getDeepestObjectAt(Component parent, int x, int y) { + + if (parent instanceof Container) { + Container cont = (Container) parent; + // use a copy of 1.3 Container.findComponentAt + Component child = findComponentAt(cont, + cont.getWidth(), + cont.getHeight(), x, y); + if (child != null && child != cont) { + //log.info("child find : " + child.getName()); + if (child instanceof JRootPane) { + JLayeredPane lp = ((JRootPane) child).getLayeredPane(); + Rectangle b = lp.getBounds(); + child = getDeepestObjectAt(lp, x - b.x, y - b.y); + } + if (child != null) { + return child; + } + } + } + // if the parent is not a Container then it might be a MenuItem. + // But even if it isn't a MenuItem just return the parent because + // that's a close as we can come. + return parent; + } + + public static Component findComponentAt(Container cont, + int width, + int height, + int x, + int y) { + //log.info("container : " + cont.getName()); + synchronized (cont.getTreeLock()) { + + if (!(x >= 0 && x < width && y >= 0 && y < height && + cont.isVisible() && cont.isEnabled())) { + return null; + } + + Component[] component = cont.getComponents(); + int ncomponents = cont.getComponentCount(); + + // Two passes: see comment in sun.awt.SunGraphicsCallback + for (int i = 0; i < ncomponents; i++) { + Component comp = component[i]; + Rectangle rect = null; + + if (comp != null && !comp.isLightweight()) { + if (rect == null || rect.width == 0 || rect.height == 0) { + rect = comp.getBounds(); + } + if (comp instanceof JXLayer<?>) { + JXLayer<?> layer = (JXLayer<?>) comp; + comp = layer.getView(); + } + if (comp instanceof Container) { + comp = findComponentAt( + (Container) comp, + rect.width, + rect.height, + x - rect.x, + y - rect.y + ); + } else { + comp = comp.getComponentAt(x - rect.x, y - rect.y); + } + if (comp != null && comp.isVisible() && comp.isEnabled()) { + return comp; + } + } + } + + for (int i = 0; i < ncomponents; i++) { + Component comp = component[i]; + Rectangle rect = null; + + if (comp != null && comp.isLightweight()) { + if (rect == null || rect.width == 0 || rect.height == 0) { + rect = comp.getBounds(); + } + if (comp instanceof JXLayer<?>) { + JXLayer<?> layer = (JXLayer<?>) comp; + comp = layer.getView(); + } + if (comp instanceof Container) { + comp = findComponentAt( + (Container) comp, + rect.width, + rect.height, + x - rect.x, + y - rect.y + ); + } else { + comp = comp.getComponentAt(x - rect.x, y - rect.y); + } + if (comp != null && comp.isVisible() && comp.isEnabled()) { + return comp; + } + } + } + return cont; + } + } + + public static TableCellRenderer newDeleteCellRenderer( + DefaultTableCellRenderer renderer) { + Icon icon = UIManager.getIcon("Table.removeIcon"); + if (icon == null) { + // try with default icon + icon = createActionIcon("delete"); + } + return new BooleanCellEditor(renderer, icon); + } + + public static TableCellRenderer newBooleanTableCellRenderer( + TableCellRenderer renderer) { + return new BooleanCellRenderer(renderer); + } + + public static TableCellRenderer newBooleanTableCellRenderer( + TableCellRenderer renderer, Predicate<?> predicate) { + return new BooleanCellRenderer(renderer, predicate); + } + + public static TableCellRenderer newBooleanTableCellEditorAndRenderer( + TableCellRenderer renderer) { + return new BooleanCellEditor(renderer); + } + + public static BooleanCellEditor newBooleanTableCellEditor( + TableCellRenderer renderer) { + return new BooleanCellEditor(renderer); + } + + public static EmptyNumberTableCellRenderer newEmptyNumberTableCellRenderer( + TableCellRenderer renderer) { + return new EmptyNumberTableCellRenderer(renderer); + } + + public static <E extends Enum<E>> EnumTableCellRenderer<E> + newEnumTableCellRenderer(TableCellRenderer renderer, Class<E> enumClass) { + return new EnumTableCellRenderer<E>(renderer, enumClass); + } + + /** + * Open a link coming from a {@link HyperlinkEvent}. + * + * And try to open the link if an url in a browser. + * + * @param he the event to treate + * @since 1.6.0 + */ + public static void openLink(HyperlinkEvent he) { + if (he.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + + if (Desktop.isDesktopSupported()) { + try { + URL u = he.getURL(); + if (u.getProtocol().equalsIgnoreCase("mailto") || + u.getProtocol().equalsIgnoreCase("http") || + u.getProtocol().equalsIgnoreCase("ftp")) { + Desktop.getDesktop().browse(u.toURI()); + } + } catch (IOException e) { + if (log.isErrorEnabled()) { + log.error("Error while opening link", e); + } + } catch (URISyntaxException e) { + if (log.isErrorEnabled()) { + log.error("Error while opening link", e); + } + } + } + } + } + + public static void openLink(String url) { + + try { + if (!Desktop.isDesktopSupported()) { + throw new IllegalStateException( + t("swing.error.desktop.not.supported")); + } + + + Desktop desktop = Desktop.getDesktop(); + + if (!desktop.isSupported(Desktop.Action.BROWSE)) { + + throw new IllegalStateException( + t("swing.error.desktop.browse.not.supported")); + } + + URI uri = new URI(url); + desktop.browse(uri); + } catch (Exception e) { + + if (log.isErrorEnabled()) { + log.error("Error while opening link", e); + } + } + } + + /** + * Expand all childs of a tree. + * + * @param tree the tree to expand + */ + public static void expandTree(final JTree tree) { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + int i = 0; + while (i < tree.getRowCount()) { + tree.expandRow(i++); + } + } + }); + } + + /** + * Expand all childs of a tree table. + * + * FIXME : Voir pour enlever le copier coller + * + * @param treeTable the tree to expand + */ + public static void expandTreeTable(final JXTreeTable treeTable) { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + int i = 0; + while (i < treeTable.getRowCount()) { + treeTable.expandRow(i++); + } + } + }); + } + + /** + * Add a listener of tree selection model to expand a new selected node + * when it is selected. + * + * @param tree the tree to treate + */ + public static void addExpandOnClickListener(final JTree tree) { + + tree.getSelectionModel().addTreeSelectionListener( + new TreeSelectionListener() { + + @Override + public void valueChanged(final TreeSelectionEvent e) { + TreeNode node = (TreeNode) + e.getPath().getLastPathComponent(); + if (node != null && !node.isLeaf()) { + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + for (TreePath path : e.getPaths()) { + if (e.isAddedPath(path) && + !tree.isExpanded(path)) { + log.info("expand node [" + path + + "]"); + // will expand the node + tree.expandPath(path); + } + } + } + }); + } + } + }); + } + + /** + * Add a listener of tree table selection model to expand a new selected + * node when it is selected. + * + * FIXME : Voir pour enlever le copier coller + * + * @param treeTable the tree to treate + */ + public static void addExpandOnClickListener(final JXTreeTable treeTable) { + + treeTable.addTreeSelectionListener(new TreeSelectionListener() { + + @Override + public void valueChanged(final TreeSelectionEvent e) { + TreeNode node = (TreeNode) e.getPath().getLastPathComponent(); + if (node != null && !node.isLeaf()) { + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + for (TreePath path : e.getPaths()) { + if (e.isAddedPath(path) && + !treeTable.isExpanded(path)) { + log.info("expand node [" + path + "]"); + // will expand the node + treeTable.expandPath(path); + } + } + } + }); + } + } + }); + } + + /** + * Set the width of the given component + * + * @param component the component to resize + * @param width the new width to apply + */ + public static void setComponentWidth(Component component, int width) { + component.setSize(width, component.getHeight()); + if (component instanceof JComponent) { + JComponent jcomponent = (JComponent) component; + jcomponent.setPreferredSize( + new Dimension(width, + jcomponent.getPreferredSize().height) + ); + jcomponent.setMinimumSize( + new Dimension(width, + jcomponent.getPreferredSize().height) + ); + if (jcomponent.isDisplayable()) { + jcomponent.revalidate(); + } + } + } + + /** + * Set the height of a given component. + * + * @param component the component to resize + * @param height the new height to apply + */ + public static void setComponentHeight(Component component, int height) { + component.setSize(component.getWidth(), height); + if (component instanceof JComponent) { + JComponent jcomponent = (JComponent) component; + jcomponent.setPreferredSize( + new Dimension(jcomponent.getPreferredSize().width, height)); + jcomponent.setMinimumSize( + new Dimension(jcomponent.getPreferredSize().width, height)); + if (jcomponent.isDisplayable()) { + jcomponent.revalidate(); + } + } + } + + public static ImageIcon createIcon(String path) { + URL imgURL = JAXXUtil.class.getResource(path); + if (imgURL != null) { + return new ImageIcon(imgURL); + } else { + throw new IllegalArgumentException("could not find icon " + path); + } + } + + /** + * @param path the location of icons in root directory icons + * @return the icon at {@link #getIconPath()}+path + */ + public static ImageIcon createImageIcon(String path) { + String iconPath = getIconPath(); + return createIcon(iconPath + path); + } + + /** + * @param key the key of the icon to retreave from {@link UIManager} + * @return the icon, or {@code null} if no icon found in {@link UIManager} + */ + public static Icon getUIManagerIcon(String key) { + return UIManager.getIcon(key); + } + + /** + * retreave for the {@link UIManager} the icon prefixed by {@code action}. + * + * @param key the key of the action icon to retreave from {@link UIManager} + * @return the icon, or {@code null} if no icon found in {@link UIManager} + */ + public static Icon getUIManagerActionIcon(String key) { + return getUIManagerIcon("action." + key); + } + + public static ImageIcon createActionIcon(String name) { + String iconPath = getIconPath(); + return createIcon("action", name); + } + + public static ImageIcon createIcon(String classifier, String name) { + String iconPath = getIconPath(); + return createIcon(iconPath + classifier + "-" + name + ".png"); + } + + public static ImageIcon createI18nIcon(String name) { + String iconPath = getIconPath(); + return createIcon(iconPath + "i18n/" + name + ".png"); + } + + private static String getIconPath() { + String iconPath = UIManager.getString(DEFAULT_ICON_PATH_PROPERTY); + if (iconPath == null) { + iconPath = DEFAULT_ICON_PATH; + } else { + if (!iconPath.endsWith("/")) { + iconPath += "/"; + } + } + return iconPath; + } + + /** + * Add {@link java.awt.event.KeyListener} to focus next editable cell on TAB key + * + * @param table to add TAB {@link java.awt.event.KeyListener} + */ + public static void makeTableTabFocusable(final JTable table) { + table.setCellSelectionEnabled(true); + table.setSurrendersFocusOnKeystroke(true); + table.addKeyListener(new KeyAdapter() { + + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_TAB) { + + // get table informations + int selectedColumn = table.getSelectedColumn(); + int selectedRow = table.getSelectedRow(); + + if (log.isDebugEnabled()) { + log.debug("Selected was row[" + selectedRow + "] column[" + selectedColumn + "]"); + } + + int columnCount = table.getColumnCount(); + int rowCount = table.getRowCount(); + + // search on current line + for (int toSelectColumn = selectedColumn; toSelectColumn < columnCount; toSelectColumn++) { + + if (editCell(table, selectedRow, toSelectColumn)) { + return; + } + } + + // search on other lines + for (int toSelectRow = selectedRow; toSelectRow < rowCount; toSelectRow++) { + for (int toSelectColumn = 0; toSelectColumn < columnCount; toSelectColumn++) { + + if (editCell(table, toSelectRow, toSelectColumn)) { + return; + } + } + } + } + } + }); + } + + /** + * Used to edit a cell of a given table. + * + * @param table the table to edit + * @param row row index of cell to editing + * @param colummn column index of cell to editing + * @return {@code false} if for any reason the cell cannot be edited, + * or if the indices are invalid + */ + public static boolean editCell(JTable table, int row, int colummn) { + + boolean result = false; + if (table.isCellEditable(row, colummn)) { + + if (table.isEditing()) { + + int editingRow = table.getEditingRow(); + int editingColumn = table.getEditingColumn(); + + // stop edition + TableCellEditor cellEditor = table.getCellEditor(editingRow, + editingColumn); + cellEditor.stopCellEditing(); + } + + // select row + table.setColumnSelectionInterval(colummn, colummn); + table.setRowSelectionInterval(row, row); + + // edit cell + result = table.editCellAt(row, colummn, new EventObject(table)); + Component component = table.getEditorComponent(); + component.requestFocus(); + + if (log.isDebugEnabled()) { + log.debug("Select row[" + row + "] column[" + colummn + + "] return : " + result); + } + } + return result; + } + + public static void ensureRowIndex(TableModel model, int rowIndex) + throws ArrayIndexOutOfBoundsException { + if (rowIndex < -1 || rowIndex >= model.getRowCount()) { + throw new ArrayIndexOutOfBoundsException( + "the rowIndex was " + rowIndex + ", but should be int [0," + + (model.getRowCount() - 1) + "]"); + } + } + + public static void ensureColumnIndex(TableModel model, int index) + throws ArrayIndexOutOfBoundsException { + if (index < -1 || index >= model.getColumnCount()) { + throw new ArrayIndexOutOfBoundsException( + "the columnIndex was " + index + ", but should be int [0," + + (model.getColumnCount() - 1) + "]"); + } + } + + /** + * Add to a given table a selec tion model listener to always scroll to + * current cell selection. + * + * @param table the table + * @since 2.5.3 + */ + public static void scrollToTableSelection(final JTable table) { + + table.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + ListSelectionModel listSelectionModel = + (ListSelectionModel) e.getSource(); + int firstIndex = e.getFirstIndex(); + int lastIndex = e.getLastIndex(); + Integer newSelectedRow = null; + + if (listSelectionModel.isSelectionEmpty()) { + + // no selection + } else if (listSelectionModel.isSelectedIndex(firstIndex)) { + + // use first index + newSelectedRow = firstIndex; + } else if (listSelectionModel.isSelectedIndex(lastIndex)) { + + // use last index + newSelectedRow = lastIndex; + } + if (newSelectedRow != null) { + Rectangle rect = table.getCellRect(newSelectedRow, 0, true); + table.scrollRectToVisible(rect); + } + } + }); + } + + /** + * Get the first char of a String, or return default value. + * + * Used for example by generated code (i18nMnemonic). + * + * @param text the text to cut + * @param defaultValue default char value if text is null, or empty + * @return the first char of the given text or the default value if text is null or empty. + * @since 2.6.14 + */ + public static char getFirstCharAt(String text, char defaultValue) { + return text == null || text.trim().length() == 0 ? + defaultValue : text.charAt(0); + } + + public static void openLink(URI uri) { + + Desktop desktop = getDesktopForBrowse(); + + try { + + desktop.browse(uri); + } catch (Exception e) { + + throw new RuntimeException( + t("application.error.cannot.open.link", uri), e); + } + } + + public static Desktop getDesktopForBrowse() { + + if (!Desktop.isDesktopSupported()) { + throw new RuntimeException( + t("application.error.desktop.not.supported")); + } + + Desktop desktop = Desktop.getDesktop(); + + if (!desktop.isSupported(Desktop.Action.BROWSE)) { + + throw new RuntimeException( + t("application.error.desktop.browse.not.supported")); + } + + return desktop; + } + + public static DefaultComboBoxModel newComboModel(Object... items) { + return new DefaultComboBoxModel(items); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/BuildTreeVisitor.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/BuildTreeVisitor.java new file mode 100644 index 0000000..6fa8c4c --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/BuildTreeVisitor.java @@ -0,0 +1,69 @@ +package org.nuiton.jaxx.runtime.awt.visitor; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.jdesktop.jxlayer.JXLayer; + +import javax.swing.JRootPane; +import java.awt.Component; +import java.awt.Container; + +/** + * A visitor to build the tree from a given component. + * + * To obtain a tree from a compoent use the method {@link #buildTree(Component)}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.14 + */ +public class BuildTreeVisitor implements ComponentTreeNodeVisitor { + + public static ComponentTreeNode buildTree(Component component) { + BuildTreeVisitor v = new BuildTreeVisitor(); + ComponentTreeNode rootNode = new ComponentTreeNode(component); + rootNode.visit(v); + return rootNode; + } + + @Override + public void startNode(ComponentTreeNode node) { + Component component = node.getUserObject(); + if (component instanceof Container) { + Container container = (Container) component; + //TODO-TC-2013-03-17 Should use some rules to add this. + for (Component child : container.getComponents()) { + if (child instanceof JXLayer<?>) { + child = ((JXLayer<?>) child).getView(); + } else if (child instanceof JRootPane) { + child = ((JRootPane) child).getLayeredPane(); + } + ComponentTreeNode childNode = new ComponentTreeNode(child); + node.add(childNode); + } + } + } + + @Override + public void endNode(ComponentTreeNode componentTree) { + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/ComponentTreeNode.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/ComponentTreeNode.java new file mode 100644 index 0000000..11c8e56 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/ComponentTreeNode.java @@ -0,0 +1,111 @@ +package org.nuiton.jaxx.runtime.awt.visitor; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.collections4.iterators.EnumerationIterator; + +import javax.swing.tree.DefaultMutableTreeNode; +import java.awt.Component; +import java.awt.Container; +import java.util.Iterator; + +/** + * A node where userObject is a {@link Component}. + * + * If the component is a {@link Container}, then his children are the components + * of the container. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.14 + */ +public class ComponentTreeNode extends DefaultMutableTreeNode implements Iterable<ComponentTreeNode> { + + private static final long serialVersionUID = 1L; + + public ComponentTreeNode(Component userObject) { + super(userObject, true); + } + + /** + * To visit a node. + * + * @param visitor the visitor + */ + public void visit(ComponentTreeNodeVisitor visitor) { + visitor.startNode(this); + for (ComponentTreeNode child : this) { + child.visit(visitor); + } + visitor.endNode(this); + } + + @Override + public Component getUserObject() { + return (Component) super.getUserObject(); + } + + @Override + public ComponentTreeNode getParent() { + return (ComponentTreeNode) super.getParent(); + } + + @Override + public ComponentTreeNode getNextLeaf() { + return (ComponentTreeNode) super.getNextLeaf(); + } + + @Override + public ComponentTreeNode getNextNode() { + return (ComponentTreeNode) super.getNextNode(); + } + + @Override + public ComponentTreeNode getNextSibling() { + return (ComponentTreeNode) super.getNextSibling(); + } + + @Override + public ComponentTreeNode getPreviousLeaf() { + return (ComponentTreeNode) super.getPreviousLeaf(); + } + + @Override + public ComponentTreeNode getPreviousNode() { + return (ComponentTreeNode) super.getPreviousNode(); + } + + @Override + public ComponentTreeNode getPreviousSibling() { + return (ComponentTreeNode) super.getPreviousSibling(); + } + + @Override + public ComponentTreeNode getRoot() { + return (ComponentTreeNode) super.getRoot(); + } + + @Override + public Iterator<ComponentTreeNode> iterator() { + return new EnumerationIterator(children()); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/ComponentTreeNodeVisitor.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/ComponentTreeNodeVisitor.java new file mode 100644 index 0000000..ccb69c5 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/ComponentTreeNodeVisitor.java @@ -0,0 +1,36 @@ +package org.nuiton.jaxx.runtime.awt.visitor; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/** + * To visit a {@link ComponentTreeNode}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.14 + */ +public interface ComponentTreeNodeVisitor { + + void startNode(ComponentTreeNode componentTree); + + void endNode(ComponentTreeNode componentTree); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/DebugComponentTreeNodeVisitor.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/DebugComponentTreeNodeVisitor.java new file mode 100644 index 0000000..1297c12 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/DebugComponentTreeNodeVisitor.java @@ -0,0 +1,87 @@ +package org.nuiton.jaxx.runtime.awt.visitor; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Component; + +/** + * To print a tree node. + * + * Created on 1/10/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.7 + */ +public class DebugComponentTreeNodeVisitor implements ComponentTreeNodeVisitor { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(DebugComponentTreeNodeVisitor.class); + + /** + * Flag to log in debug level (otherwise will be in info level). + */ + protected boolean debug; + + protected int level = 0; + + public void parse(ComponentTreeNode componentTree) { + + sb = new StringBuilder(); + componentTree.visit(this); + + String message = sb.toString(); + if (debug) { + log.debug(message); + } else { + log.info(message); + } + } + + protected StringBuilder sb = new StringBuilder(); + + @Override + public void startNode(ComponentTreeNode componentTree) { + String message = StringUtils.leftPad(" ", 2 * level); + sb.append("\n").append(message).append(getMessage(componentTree)); + level++; + } + + @Override + public void endNode(ComponentTreeNode componentTree) { + level--; + } + + public void setDebug(boolean debug) { + this.debug = debug; + } + + public String getMessage(ComponentTreeNode componentTree) { + Component userObject = componentTree.getUserObject(); + return userObject.getClass().getSimpleName() + "::" + userObject.getName(); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/GetCompopentAtPointVisitor.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/GetCompopentAtPointVisitor.java new file mode 100644 index 0000000..7aabd9a --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/GetCompopentAtPointVisitor.java @@ -0,0 +1,114 @@ +package org.nuiton.jaxx.runtime.awt.visitor; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.Lists; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Component; +import java.awt.Point; +import java.awt.Rectangle; +import java.util.List; + +/** + * A visitor to get the deepest component given a point in a tree. + * + * To obtain the component use the method {@link #get(ComponentTreeNode, Point)}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.14 + */ +public class GetCompopentAtPointVisitor implements ComponentTreeNodeVisitor { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(GetCompopentAtPointVisitor.class); + + int currentX; + + int currentY; + + final List<ComponentTreeNode> components = Lists.newArrayList(); + + public static Component get(ComponentTreeNode node, Point p) { + + GetCompopentAtPointVisitor v = new GetCompopentAtPointVisitor(p); + node.visit(v); + Component result = v.getLastComponent(); + v.components.clear(); + return result; + } + + public GetCompopentAtPointVisitor(Point p) { + currentX = (int) p.getX(); + currentY = (int) p.getY(); + } + + public Component getLastComponent() { + Component result = null; + if (!components.isEmpty()) { + ComponentTreeNode node = components.get(components.size() - 1); + result = node.getUserObject(); + } + return result; + } + + @Override + public void startNode(ComponentTreeNode node) { + Component component = node.getUserObject(); + + if (!(component.isVisible() && component.isShowing())) { + if (log.isDebugEnabled()) { + log.debug("Skip invisible component: " + + component.getClass().getSimpleName() + "::" + + component.getName()); + } + return; + } + + // check parent is ok + if (node.isRoot() || components.contains(node.getParent())) { + + Point locationOnScreen = component.getLocationOnScreen(); + Rectangle bounds = component.getBounds(); + bounds.setLocation(locationOnScreen); + + boolean containsPoint = bounds.contains(currentX, currentY); + + if (containsPoint) { + + if (log.isDebugEnabled()) { + log.debug("Accept component: " + component); + } + + // keep this node + components.add(node); + } + } + } + + @Override + public void endNode(ComponentTreeNode componentTree) { + } +} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/package.html b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/package.html similarity index 100% rename from jaxx-runtime/src/main/java/jaxx/runtime/awt/visitor/package.html rename to jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/awt/visitor/package.html diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/bean/BeanTypeAware.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/bean/BeanTypeAware.java new file mode 100644 index 0000000..56621d3 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/bean/BeanTypeAware.java @@ -0,0 +1,41 @@ +package org.nuiton.jaxx.runtime.bean; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/** + * Contract for ui which contains a {@code beanType} property. + * + * In a jaxx file, if an object has a genericType and implementsthis contract + * then the {@code beanType} will be automaticly setted. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.9 + */ +public interface BeanTypeAware<O> { + + String PROPERTY_BEAN_TYPE= "beanType"; + + Class<O> getBeanType(); + + void setBeanType(Class<O> beanType); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/binding/DefaultJAXXBinding.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/binding/DefaultJAXXBinding.java new file mode 100644 index 0000000..98295f5 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/binding/DefaultJAXXBinding.java @@ -0,0 +1,162 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.binding; + +import org.nuiton.jaxx.runtime.JAXXBinding; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.PropertyChangeEvent; + + +/** + * A <code>PropertyChangeListener</code> which processes a data binding when it receives a + * <code>PropertyChangeEvent</code>. + */ +public abstract class DefaultJAXXBinding implements JAXXBinding { + + /** Logger */ + private static final Log log = LogFactory.getLog(DefaultJAXXBinding.class); + + /** Counter of all bindings hits */ + private static long NB; + + /** Counter of current binding hits */ + private long nb; + + /** Id of the binding */ + private final String id; + + /** The source of the binding. */ + protected final JAXXObject source; + + /** + * flag to know {@code true} : if the binding was init from a generated + * jaxx object, {@code false} otherwise. + */ + protected final boolean defaultBinding; + + /** + * Internal state to reapply the binding after each fires :this is sometimes + * necessary when binding is complex. For example with this binding + * <pre> + * ui.getModel().getProperty() + * </pre> + * We need to listen two things : first listen on {@code ui} the + * modification of {@code model}, then on {@code model} the {@code property}. + * + * @since 2.4.2 + */ + protected final boolean reloadAfterFire; + + /** + * Creates a new Data binding which will run the given data binding + * when it receives a <code>PropertyChangeEvent</code>. + * + * @param source the {@link JAXXObject} source of the binding + * @param id the name of the data binding to run + * @param defaultBinding flag to knwon if binding is coming from a generated jaxx object ({@code true}). + */ + public DefaultJAXXBinding(JAXXObject source, String id, + boolean defaultBinding) { + this(source, id, defaultBinding, false); + } + + /** + * Creates a new Data binding which will run the given data binding + * when it receives a <code>PropertyChangeEvent</code>. + * + * @param source the {@link JAXXObject} source of the binding + * @param id the name of the data binding to run + * @param defaultBinding flag to know if binding is coming from a generated jaxx object ({@code true}). + * @param reloadAfterFire flag to know if the binding need to be reload after each fires + */ + public DefaultJAXXBinding(JAXXObject source, String id, + boolean defaultBinding, + boolean reloadAfterFire) { + this.source = source; + this.id = id; + this.defaultBinding = defaultBinding; + this.reloadAfterFire = reloadAfterFire; + } + + @Override + public String getId() { + return id; + } + + @Override + public JAXXObject getSource() { + return source; + } + + @Override + public boolean isDefaultBinding() { + return defaultBinding; + } + + @Override + public String toString() { + return super.toString() + ":" + id; + } + + private static final String LOG_START_PATTERN = ">> (hits:%1$5d, total:%2$5d) on %3$s"; + + private static final String LOG_END_PATTERN = "<< %4$3d (hits:%1$5d, total:%2$5d) on %3$s"; + + /** + * Processes the data binding in response to a <code>PropertyChangeEvent</code>. + * + * When the binding is wake up, delegate the process to the source object which + * can manage re-entrant code (can not process a re-entrant event). + * + * @param e the event which triggered the binding + */ + @Override + public void propertyChange(PropertyChangeEvent e) { + long count = NB; + if (log.isDebugEnabled()) { + log.debug(String.format(LOG_START_PATTERN, ++nb, ++NB, this)); + } + //TODO-TC-20091202 perharps could we have a nicer way to process it, + // let the source deal with it to avoid re-entrant code + source.processDataBinding(id); + + //TODO-20091201 Must test on a lot of cases before next release 2.0.0-beta-2 + //TC-20091201 : I really don't see the point + // I comment the code, and still working fine ? Any trick + // for now, handle dependency changes by always removing & reapplying + // the binding. We should be more efficient and only do this when it's + // actually necessary + if (reloadAfterFire) { + JAXXUtil.reloadBinding(this); + } +// source.removeDataBinding(id); +// source.applyDataBinding(id); + if (log.isDebugEnabled()) { + log.debug(String.format(LOG_END_PATTERN, ++nb, ++NB, this, NB - count)); + } + } + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/binding/SimpleJAXXObjectBinding.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/binding/SimpleJAXXObjectBinding.java new file mode 100644 index 0000000..403ae42 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/binding/SimpleJAXXObjectBinding.java @@ -0,0 +1,81 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.binding; + +import org.nuiton.jaxx.runtime.JAXXObject; + +/** + * Created: 5 déc. 2009 + * + * @author Tony Chemit - chemit@codelutin.com + * @version $Revision$ + * + * Mise a jour: $Date$ par : + * $Author$ + */ +public abstract class SimpleJAXXObjectBinding extends DefaultJAXXBinding { + + protected final String[] propertyNames; + + /** + * Creates a new Data binding which will run the given data binding + * when it receives a <code>PropertyChangeEvent</code>. + * + * @param source the {@link JAXXObject} source of the binding + * @param id the name of the data binding to run + * @param defaultBinding flag to knwon if binding is coming from a generated jaxx object ({@code true}). + * @param propertyNames the name of properties to listen on source + */ + public SimpleJAXXObjectBinding(JAXXObject source, String id, boolean defaultBinding, String... propertyNames) { + super(source, id, defaultBinding); + if (propertyNames == null || propertyNames.length == 0) { + throw new IllegalArgumentException("must at least have one propertyName "); + } + this.propertyNames = propertyNames; + } + + public boolean canApply() { + return true; + } + + public String[] getPropertyNames() { + return propertyNames; + } + + @Override + public void applyDataBinding() { + if (canApply()) { + for (String s : propertyNames) { + source.addPropertyChangeListener(s, this); + } + } + } + + @Override + public void removeDataBinding() { + if (canApply()) { + for (String s : propertyNames) { + source.removePropertyChangeListener(s, this); + } + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/DataContext.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/DataContext.java new file mode 100644 index 0000000..afe0a33 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/DataContext.java @@ -0,0 +1,448 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.context; + +import org.nuiton.jaxx.runtime.JAXXContext; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.regex.Pattern; + +/** + * Un contexte de données qui permet l'utilisation des bindings sur les + * entrées du contexte. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.3 + */ +public abstract class DataContext { + + /** Logger */ + static private Log log = LogFactory.getLog(DataContext.class); + + public static final DataContextEntry<?>[] EMPTY_DATA_CONTEXT_ENTRY_ARRAY = + new DataContextEntry<?>[0]; + + /** le context qui contient les données */ + protected final DefaultJAXXContext delegate; + + /** la definition de l'entree actuallement selectionnee */ + protected DataContextEntry<?> currentEntry; + + /** to manage properties modifications */ + protected final PropertyChangeSupport pcs; + + protected DataContextEntry<?>[] entries; + + protected final String[] DEFAULT_JAXX_PCS; + + public abstract String getContextPath(Object... e); + + public DataContext(String[] DEFAULT_JAXX_PCS, + DataContextEntry<?>[] entries) { + this.DEFAULT_JAXX_PCS = DEFAULT_JAXX_PCS; + this.entries = entries; + delegate = new DefaultJAXXContext() { + + @Override + protected void setParentContext(JAXXContext parentContext) { + throw new IllegalStateException( + "can not use this method for this type of context"); + } + + @Override + protected JAXXContext getParentContext() { + return null; + } + + @Override + public <T> void removeContextValue(Class<T> klazz, String name) { + if (log.isTraceEnabled()) { + log.trace(klazz + " - " + name); + } + super.removeContextValue(klazz, name); + } + + @Override + public <T> void setContextValue(T o, String name) { + if (log.isTraceEnabled()) { + log.trace(name + " - " + o.getClass()); + } + super.setContextValue(o, name); + } + }; + pcs = new PropertyChangeSupport(this); + } + + public DefaultJAXXContext getDelegate() { + return delegate; + } + + public Iterable<? extends DataContextEntry<?>> iterateOnAll() { + return new Iterable<DataContextEntry<?>>() { + + @Override + public Iterator<DataContextEntry<?>> iterator() { + return new DataContextEntryIterator(entries); + } + }; + } + + public Iterable<? extends DataContextEntry<?>> iterateToLevel( + final int level) { + return new Iterable<DataContextEntry<?>>() { + + @Override + public Iterator<DataContextEntry<?>> iterator() { + return new DataContextEntryIterator(entries, level); + } + }; + } + + public Iterable<? extends DataContextEntry<?>> reverseIterateOnAll() { + + return new Iterable<DataContextEntry<?>>() { + + @Override + public Iterator<DataContextEntry<?>> iterator() { + return new DataContextEntryIterator(entries, true); + } + }; + } + + public DataContextEntry<?> getCurrentEntry() { + return currentEntry; + } + + public DataContextEntry<?> getEntry(String path) { + for (DataContextEntry<?> scope : reverseIterateOnAll()) { + if (scope.acceptPath(path)) { + return scope; + } + } + return null; + } + + public DataContextEntry<?> getEntry(Class<?> type) { + for (DataContextEntry<?> scope : iterateOnAll()) { + if (scope.acceptType(type)) { + return scope; + } + } + return null; + } + + public <T> T getContextValue(DataContextEntry<T> entry, String key) { + String contextKey = getKey(entry, key); + return delegate.getContextValue(entry.getKlass(), contextKey); + } + + public void setContextValue(DataContextEntry<?> entry, + Object value, + String key) { + String contextKey = getKey(entry, key); + delegate.setContextValue(value, contextKey); + } + + /** + * @param entry + * @param klass + * @param key + */ + public void removeContextValue(DataContextEntry<?> entry, + Class<?> klass, + String key) { + String contextKey = getKey(entry, key); + delegate.removeContextValue(klass, key); + } + + public void removeContextValue(DataContextEntry<?> entry, + String key) { + String contextKey = getKey(entry, key); + delegate.removeContextValue(entry.getKlass(), contextKey); + } + + @SuppressWarnings("unchecked") + public void updateSelectedData(String path, + Object data, + UpdateDataContext updator) { + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------------" + + "-----------"); + } + if (currentEntry != null) { + + if (log.isDebugEnabled()) { + log.debug("remove from old entry " + currentEntry); + } + for (DataContextEntry<?> s : currentEntry) { + if (log.isDebugEnabled()) { + log.debug("remove entry " + s); + } + updator.onRemovingData(this, s); + } + } + + currentEntry = getEntry(path); + + if (log.isDebugEnabled()) { + log.debug("new entry " + currentEntry + " for path " + path); + } + + if (currentEntry != null) { + + for (DataContextEntry<?> s : + iterateToLevel(currentEntry.getLevel())) { + + if (log.isDebugEnabled()) { + log.debug("add entry " + s); + } + updator.onAddingData(this, s, path); + } + } + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + public synchronized boolean hasListeners(String propertyName) { + return pcs.hasListeners(propertyName); + } + + public synchronized PropertyChangeListener[] getPropertyChangeListeners( + String propertyName) { + return pcs.getPropertyChangeListeners(propertyName); + } + + public synchronized PropertyChangeListener[] getPropertyChangeListeners() { + return pcs.getPropertyChangeListeners(); + } + + public void removeJaxxPropertyChangeListener() { + PropertyChangeListener[] toRemove = + JAXXUtil.findJaxxPropertyChangeListener( + DEFAULT_JAXX_PCS, getPropertyChangeListeners()); + if (toRemove == null || toRemove.length == 0) { + return; + } + if (log.isDebugEnabled()) { + log.debug("before remove : " + getPropertyChangeListeners().length); + log.debug("toRemove : " + toRemove.length); + } + for (PropertyChangeListener listener : toRemove) { + removePropertyChangeListener(listener); + } + if (log.isDebugEnabled()) { + log.debug("after remove : " + getPropertyChangeListeners().length); + } + } + + protected void firePropertyChange(String name, + Object oldValue, + Object newValue) { + pcs.firePropertyChange(name, oldValue, newValue); + } + + protected String getKey(DataContextEntry<?> entry, String key) { + String result = null; + if (key != null) { + result = entry.hashCode() + "#" + key; + } + return result; + } + + public void close() throws Exception { + clear(); + + // suppression des ecouteurs + + for (PropertyChangeListener l : getPropertyChangeListeners()) { + removePropertyChangeListener(l); + } + } + + public void clear() { + delegate.clear(); + } + + public static abstract class DataContextEntry<E> implements Iterable<DataContextEntry<?>> { + + private final int level; + + private final DataContextEntry<?> previous; + + private final DataContextEntry<?>[] parents; + + private Class<E> klass; + + public DataContextEntry(Class<E> klass, DataContextEntry<?> previous) { + this.previous = previous; + level = previous.level + 1; + this.klass = klass; + parents = new DataContextEntry<?>[level]; + int i = level; + while (i > 0) { + parents[--i] = previous; + previous = previous.previous; + } + } + + public DataContextEntry(Class<E> klass) { + level = 0; + this.klass = klass; + previous = null; + parents = EMPTY_DATA_CONTEXT_ENTRY_ARRAY; + } + + public Class<E> getKlass() { + return klass; + } + + public int getLevel() { + return level; + } + + public DataContextEntry<?>[] getParents() { + return parents; + } + + public abstract Pattern getPattern(); + + public abstract String getContextPath(Object... args); + + public boolean acceptPath(String path) { + return getPattern().matcher(path).matches(); + } + + public boolean acceptType(Class<?> type) { + return klass.isAssignableFrom(type); + } + + @Override + public Iterator<DataContextEntry<?>> iterator() { + int length = parents.length; + DataContextEntry<?>[] t = new DataContextEntry<?>[length + 1]; + System.arraycopy(parents, 0, t, 0, length); + t[length] = this; + return new DataContextEntryIterator(t, true); + } + + @Override + public String toString() { + return super.toString() + "<type: " + klass.getSimpleName() + ">"; + } + } + + public interface UpdateDataContext<D extends DataContext> { + + void onRemovingData(D context, DataContextEntry<D> entry); + + void onAddingData(D context, DataContextEntry<D> entry, String path); + } + + public static class DataContextEntryIterator implements Iterator<DataContextEntry<?>> { + + protected final DataContextEntry<?>[] datas; + + protected final boolean reverse; + + protected final int level; + + protected int index; + + public DataContextEntryIterator(DataContextEntry<?>[] datas) { + this(datas, false, -1); + } + + public DataContextEntryIterator(DataContextEntry<?>[] datas, + int level) { + this(datas, false, level); + } + + public DataContextEntryIterator(DataContextEntry<?>[] datas, + boolean reverse) { + this(datas, reverse, -1); + } + + DataContextEntryIterator(DataContextEntry<?>[] datas, + boolean reverse, + int level) { + this.datas = datas; + this.reverse = reverse; + if (reverse) { + index = datas.length; + } else { + index = -1; + } + this.level = level; + } + + @Override + public boolean hasNext() { + if (reverse) { + return index > 0; + } else { + return index + 1 < datas.length && + (level == -1 || datas[index + 1].getLevel() <= level); + } + } + + @Override + public DataContextEntry<?> next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + if (reverse) { + index--; + } else { + index++; + } + return datas[index]; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("Not supported yet."); + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/DefaultApplicationContext.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/DefaultApplicationContext.java new file mode 100644 index 0000000..da14046 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/DefaultApplicationContext.java @@ -0,0 +1,473 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.context; + +import org.nuiton.jaxx.runtime.JAXXContext; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +/** + * The default context to be used for an application. + * + * This extends the {@link DefaultJAXXContext} and add a possibility to + * auto-instanciate some classes asked via {@link #getContextValue(Class)} and + * {@link #getContextValue(Class, String)} methods. + * + * To registred a such class, just annotate your class with {@link AutoLoad}. + * + * @author Tony Chemit - chemit@codelutin.com + * @see DefaultJAXXContext + * @since 1.2 + */ +public class DefaultApplicationContext extends DefaultJAXXContext { + + /** + * A class annotated @AutoLoad is used by context to auto instanciate + * the class when required. + * + * Note : A such class always have a public default constructor. + * + * @author Tony Chemit - chemit@codelutin.com + * @version 1.0, 21/02/09 + * @since 1.2 + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface AutoLoad { + //TODO use this to add a method to init + + String initMethod() default ""; + } + + /** + * A class annotated @MethodAccess is used by context to obtain the + * value of an entry via a declared method. + * + * Note : A such class must have a method called {@link #methodName()} with + * a single String parameter. + * + * @author Tony Chemit - chemit@codelutin.com + * @version 1.0, 21/02/09 + * @since 1.2 + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface MethodAccess { + + /** + * Define a forward to a target class. When the target class will be + * asked with method {@link JAXXContext#getContextValue(Class, String)} + * it will be delegating to this class. + * + * @return the forwarded class + */ + Class<?> target() default Object.class; + + /** @return the name of the method to access data */ + String methodName(); + } + + /** Map of forwarded classes (key) to classes (values). */ + protected Map<Class<?>, Class<?>> forwards; + + /** + * Map of entries to watch associated with the property to fires if a + * modification was found. + */ + protected Map<JAXXContextEntryDef<?>, String> entryListened; + + public DefaultApplicationContext() { + forwards = new HashMap<Class<?>, Class<?>>(); + pcs = new PropertyChangeSupport(this); + } + + /** Logger */ + static private final Log log = + LogFactory.getLog(DefaultApplicationContext.class); + + /** to manage properties modifications */ + protected PropertyChangeSupport pcs; + + @SuppressWarnings({"unchecked"}) + @Override + public <T> T getContextValue(Class<T> clazz, String name) { + Object value; + MethodAccess access; + + Class<?> realClass; + + if (forwards.containsKey(clazz)) { + // this is a forward class + realClass = forwards.get(clazz); + // always call the forwarder with no name + value = getContextValue(realClass, null); + if (log.isDebugEnabled()) { + log.debug("detect forward from " + clazz + " to " + realClass + + " (" + value + ")"); + } + + } else { + realClass = clazz; + value = super.getContextValue(realClass, name); + } + + //TC-20091007 TODO Make possible use of named autoload entries + //(add a parameter on AutoLoad annotation) + if (value == null) { + AutoLoad anno = clazz.getAnnotation(AutoLoad.class); + + if (anno == null) { + // no annotation, so do nothing + return null; + } + + if (name != null) { + throw new IllegalArgumentException( + "an " + AutoLoad.class.getName() + " can not have " + + "a named context but was call with this one : " + name); + } + value = newInstance(clazz); + if (!anno.initMethod().trim().isEmpty()) { + // apply method on class + newAccess(clazz, value, anno.initMethod().trim()); + } + if (log.isDebugEnabled()) { + log.debug("new instance " + clazz + " : " + value); + } + // save new instance + setContextValue(value, null); + } + + access = realClass.getAnnotation(MethodAccess.class); + + if (access != null) { + if (name == null) { + if (!Object.class.equals(access.target())) { + // register forward + Class<?> targetClass = access.target(); + if (!forwards.containsKey(targetClass)) { + // register forward + forwards.put(targetClass, clazz); + if (log.isDebugEnabled()) { + log.debug("register forward from " + targetClass + + " to " + clazz); + } + } + } + } else { + // specialized access + value = newAccess(realClass, value, access.methodName(), name); + } + } + return (T) value; + } + + @Override + public <T> void removeContextValue(Class<T> klass, String name) { + Entry<Class<?>, Class<?>> entry; + if (name == null && forwards.containsValue(klass)) { + // remove forward + Iterator<Entry<Class<?>, Class<?>>> itr = + forwards.entrySet().iterator(); + while (itr.hasNext()) { + entry = itr.next(); + if (entry.getValue().equals(klass)) { + itr.remove(); + if (log.isDebugEnabled()) { + log.debug("removed forward from " + entry.getKey() + + " to " + klass); + } + break; + } + } + } + //FIXME should update forwards state + JAXXContextEntryDef<?> entryToDel = getEntry(klass, name); + Object t = remove0(klass, name); + if (log.isDebugEnabled()) { + log.debug("removed object = " + t); + } + if (t != null && entryToDel != null) { + // a value was removed + // notify listeners + fireEntryChanged(entryToDel, t, null); + } +// super.removeContextValue(klass, name); + } + + @Override + public <T> void setContextValue(T o, String name) { +// super.setContextValue(o, name); + if (name == null && PARENT_CONTEXT_ENTRY.accept2(o.getClass(), null)) { + setParentContext((JAXXContext) o); + return; + } + JAXXContextEntryDef<?> entry = getKey(name, o.getClass()); + // first remove entry + Object oldValue = remove0(o.getClass(), name); + if (oldValue != null) { + if (log.isDebugEnabled()) { + log.debug("remove value " + oldValue.getClass() + " for " + + entry); + } + } + // then can put safely + data.put(entry, o); + if (log.isDebugEnabled()) { + log.debug("[" + name + "] set value for entry " + entry); + } + // firezs + fireEntryChanged(entry.getKlass(), name, oldValue, o); + } + + /** + * To add a listen modification of the given entry in the context. + * + * @param entry the entry to listen + * @param name the property name to fire if necessary + * @param listener the listener to notify if entry has changed + * @since 2.0.1 + */ + public void addPropertyChangeListener(JAXXContextEntryDef<?> entry, + String name, + PropertyChangeListener listener) { + if (entryListened == null) { + entryListened = new HashMap<JAXXContextEntryDef<?>, String>(); + } + entryListened.put(entry, name); + if (log.isDebugEnabled()) { + log.debug("[" + name + "] for " + entry); + } + pcs.addPropertyChangeListener(name, listener); + } + + /** + * To remove a listen modification of the given entry in the context. + * + * @param entry the entry to listen + * @param name the property name to fire if necessary + * @param listener the listener to notify if entry has changed + * @since 2.0.1 + */ + public void removePropertyChangeListener(JAXXContextEntryDef<?> entry, + String name, + PropertyChangeListener listener) { + if (entryListened == null) { + entryListened = new HashMap<JAXXContextEntryDef<?>, String>(); + } + entryListened.remove(entry); + pcs.removePropertyChangeListener(name, listener); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + public synchronized boolean hasListeners(String propertyName) { + return pcs.hasListeners(propertyName); + } + + public synchronized PropertyChangeListener[] getPropertyChangeListeners( + String propertyName) { + return pcs.getPropertyChangeListeners(propertyName); + } + + public synchronized PropertyChangeListener[] getPropertyChangeListeners() { + return pcs.getPropertyChangeListeners(); + } + + protected void fireEntryChanged(Class<?> klass, + String name, + Object oldValue, + Object newValue) { + // a value was removed + if (entryListened != null) { + // look if the entry was listened + + if (log.isTraceEnabled()) { + log.trace("data size : " + data.size()); + for (Entry<JAXXContextEntryDef<?>, Object> e : data.entrySet()) { + log.trace(e.getKey()); + } + } + JAXXContextEntryDef<?> entry2 = getEntry(klass, name); + if (log.isDebugEnabled()) { + log.debug("[" + name + "] : try to find a changer for " + entry2); + } + if (entry2 != null) { + // entry find directly on this context + String propertyName = entryListened.get(entry2); + if (log.isTraceEnabled()) { + log.trace("registred property name = " + propertyName); + } + if (propertyName != null) { + if (log.isDebugEnabled()) { + log.debug("will notify modification on " + entry2); + } + // fires the removed + firePropertyChange(propertyName, oldValue, newValue); + } + } + } + } + + protected void fireEntryChanged(JAXXContextEntryDef<?> entryDef, + Object oldValue, + Object newValue) { + // a value was removed + if (entryListened != null) { + // look if the entry was listened + + if (log.isTraceEnabled()) { + log.trace("data size : " + data.size()); + for (Entry<JAXXContextEntryDef<?>, Object> e : data.entrySet()) { + log.trace(e.getKey()); + } + } +// JAXXContextEntryDef<?> entry2 = getEntry(klass, name); +// if (log.isDebugEnabled()) { +// log.debug("[" + name + "] : try to find a changer for " + entry2); +// } + if (entryDef != null) { + // entry find directly on this context + String propertyName = entryListened.get(entryDef); + if (log.isTraceEnabled()) { + log.trace("registred property name = " + propertyName); + } + if (propertyName != null) { + if (log.isDebugEnabled()) { + log.debug("will notify modification on " + entryDef); + } + // fires the removed + firePropertyChange(propertyName, oldValue, newValue); + } + } + } + } + + protected Object newInstance(Class<?> clazz) throws + IllegalArgumentException { + + Object value; + + Constructor<?> constructor; + try { + constructor = clazz.getConstructor(); + // auto instanciate the class + if (constructor == null) { + throw new IllegalArgumentException( + clazz + " has no public constructor"); + } + } catch (NoSuchMethodException ex) { + throw new IllegalArgumentException(ex); + } catch (SecurityException ex) { + throw new IllegalArgumentException(ex); + } + try { + value = constructor.newInstance(); + + } catch (InstantiationException ex) { + throw new IllegalArgumentException(ex); + } catch (IllegalAccessException ex) { + throw new IllegalArgumentException(ex); + } catch (InvocationTargetException ex) { + throw new IllegalArgumentException(ex); + } + return value; + } + + protected Object newAccess( + Class<?> clazz, + Object parent, + String methodName, + String name) throws IllegalArgumentException { + Object value; + try { + Method m = clazz.getMethod(methodName, String.class); + value = m.invoke(parent, name); + return value; + } catch (NoSuchMethodException ex) { + throw new IllegalArgumentException(ex); + } catch (SecurityException ex) { + throw new IllegalArgumentException(ex); + } catch (IllegalAccessException ex) { + throw new IllegalArgumentException(ex); + } catch (InvocationTargetException ex) { + throw new IllegalArgumentException(ex); + } + } + + protected Object newAccess( + Class<?> clazz, + Object parent, + String methodName) throws IllegalArgumentException { + Object value; + try { + Method m = clazz.getMethod(methodName); + value = m.invoke(parent); + return value; + } catch (NoSuchMethodException ex) { + throw new IllegalArgumentException(ex); + } catch (SecurityException ex) { + throw new IllegalArgumentException(ex); + } catch (IllegalAccessException ex) { + throw new IllegalArgumentException(ex); + } catch (InvocationTargetException ex) { + throw new IllegalArgumentException(ex); + } + } + + protected void firePropertyChange(String name, + Object oldValue, + Object newValue) { + pcs.firePropertyChange(name, oldValue, newValue); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/DefaultJAXXContext.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/DefaultJAXXContext.java new file mode 100644 index 0000000..5b71957 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/DefaultJAXXContext.java @@ -0,0 +1,229 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.context; + +import org.nuiton.jaxx.runtime.JAXXContext; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * The default {@link JAXXContext} to be used in a {@link JAXXObject} by + * delegation. + * + * The values are store in a {@link Map} but we can not use directly the values + * as key. + * + * Because, it does not work if we add for the same object multi entries (named + * and unamed)... + * + * We prefer use as entry the {@link JAXXContextEntryDef} associated with the + * value. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class DefaultJAXXContext implements JAXXContext { + + /** entry of the parent context */ + protected static final JAXXContextEntryDef<JAXXContext> + PARENT_CONTEXT_ENTRY = JAXXUtil.newContextEntryDef(JAXXContext.class); + + /** Logger */ + static private final Log log = LogFactory.getLog(DefaultJAXXContext.class); + + /** le context parent */ + protected JAXXContext parentContext; + + /** les données contenues dans le context */ + protected final Map<JAXXContextEntryDef<?>, Object> data; + + public DefaultJAXXContext() { + data = new HashMap<JAXXContextEntryDef<?>, Object>(); + } + + @Override + public <T> void setContextValue(T o) { + setContextValue(o, null); + } + + @Override + public <T> void setContextValue(T o, String name) { + if (name == null && PARENT_CONTEXT_ENTRY.accept2(o.getClass(), null)) { + setParentContext((JAXXContext) o); + return; + } + JAXXContextEntryDef<?> entry = getKey(name, o.getClass()); + // first remove entry + Object oldValue = remove0(o.getClass(), name); + if (oldValue != null) { + if (log.isDebugEnabled()) { + log.debug("remove value " + oldValue.getClass() + " for " + + entry); + } + } + // then can put safely + data.put(entry, o); + } + + @Override + public <T> T getContextValue(Class<T> clazz) { + return getContextValue(clazz, null); + } + + @SuppressWarnings({"unchecked"}) + @Override + public <T> T getContextValue(Class<T> clazz, String name) { + if (parentContext != null && + parentContext.getClass().equals(clazz) || + PARENT_CONTEXT_ENTRY.accept(clazz, name)) { + return (T) getParentContext(); + } + for (Entry<JAXXContextEntryDef<?>, Object> entry : data.entrySet()) { + if (entry.getKey().accept(clazz, name)) { + return (T) entry.getValue(); + } + } + + // no value found in this context, will try in the parent context + if (JAXXContext.class.equals(clazz)) { + // no seek in the parent context, since we are already looking + // for it + return null; + } + + JAXXContext parent = getParentContext(); + if (parent == null) { + // no parent context, so no value find + return null; + } + // seek in parent context + return parent.getContextValue(clazz, name); + } + + @Override + public <T> void removeContextValue(Class<T> klazz) { + removeContextValue(klazz, null); + } + + @Override + public <T> void removeContextValue(Class<T> klazz, String name) { + remove0(klazz, name); + } + + /** + * Obtain all the keys of data for a given type. + * + * @param klass the type of searched keys + * @return the array of all names of keys for the given type of data + * @since 1.3 + */ + public String[] getKeys(Class<?> klass) { + List<String> keys = new ArrayList<String>(); + for (JAXXContextEntryDef<?> key : data.keySet()) { + if (key.getKlass().equals(klass)) { + keys.add(key.getName()); + } + } + return keys.toArray(new String[keys.size()]); + + } + + public void clear() { + data.clear(); + } + + protected JAXXContextEntryDef<?> getKey(String name, Class<?> klass) { + //FIXME-TC20100322 : must change this to have a store, we instanciate + // a new object each time we wants to deal with the context... + return JAXXUtil.newContextEntryDef(name, klass); + } + + @SuppressWarnings({"unchecked"}) + protected <T> T remove0(Class<T> klass, String name) { + if (PARENT_CONTEXT_ENTRY.accept(klass, name)) { + JAXXContext old = getParentContext(); + setParentContext(null); + return (T) old; + } + JAXXContextEntryDef<?> entry = getEntry(klass, name); +// JAXXContextEntryDef<?> entry = null; +// for (JAXXContextEntryDef<?> entryDef : data.keySet()) { +// if (entryDef.accept(klass, name)) { +// entry = entryDef; +// break; +// } +// } + if (entry != null) { + return (T) data.remove(entry); + } + + if (JAXXContext.class.equals(klass)) { + return null; + } + + // try on parent + JAXXContext parent = getParentContext(); + + if (parent == null) { + // no parent, stop now, can not found entry + return null; + } + + if (parent instanceof DefaultJAXXContext) { + // try now on the parent + return ((DefaultJAXXContext) parent).remove0(klass, name); + } + + // can not find the entry anywhere, so says that nothing was removed + return null; + } + + protected JAXXContextEntryDef<?> getEntry(Class<?> klass, String name) { + JAXXContextEntryDef<?> entry = null; + for (JAXXContextEntryDef<?> entryDef : data.keySet()) { + if (entryDef.accept(klass, name)) { + entry = entryDef; + break; + } + } + return entry; + } + + protected JAXXContext getParentContext() { + return parentContext; + } + + protected void setParentContext(JAXXContext parentContext) { + if (parentContext instanceof JAXXObject) { + // keep the real context, not the ui + parentContext = ((JAXXObject) parentContext).getDelegateContext(); + } + this.parentContext = parentContext; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/JAXXContextEntryDef.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/JAXXContextEntryDef.java new file mode 100644 index 0000000..d64dde8 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/JAXXContextEntryDef.java @@ -0,0 +1,138 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.context; + +import org.nuiton.jaxx.runtime.JAXXContext; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * To qualify an entry in a {@link JAXXContext}. + * + * Use the factory methods <code>newContextEntryDef</code> and + * <code>newListContextEntryDef</code> to obtain new instances. + * + * @param <O> type of the entry associated to the definition + * @author Tony Chemit - chemit@codelutin.com + */ +public class JAXXContextEntryDef<O> implements Serializable { + + /** name of the entry, can be nuill for a unamed entry. */ + protected String name; + + /** class of the entry, can not be null */ + protected Class<O> klass; + + private static final long serialVersionUID = 1L; + + public String getName() { + return name; + } + + public Class<O> getKlass() { + return klass; + } + + public O getContextValue(JAXXContext context) { + return context.getContextValue(klass, name); + } + + public void removeContextValue(JAXXContext context) { + context.removeContextValue(klass, name); + } + + public void setContextValue(JAXXContext context, O value) { + context.setContextValue(value, name); + } + + @Override + public String toString() { + return super.toString() + "<" + klass + ":" + name + ">"; + } + + public JAXXContextEntryDef(Class<O> klass) { + this(null, klass); + } + + /** + * Special constructor for map, otherwise it is not possible to cast to O + * + * @param mapClass map class + * @param name name of content + * @since 2.0.2 + */ + @SuppressWarnings({"unchecked"}) + public JAXXContextEntryDef(Class<Map> mapClass, String name) { + this(name, (Class<O>) mapClass); + } + + @SuppressWarnings("unchecked") + public JAXXContextEntryDef(String name, Class<O> klass) { + if (klass == null) { + throw new IllegalArgumentException("class can not be null"); + } + this.name = name; + if (List.class.isAssignableFrom(klass)) { + klass = (Class<O>) List.class; + } + this.klass = klass; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof JAXXContextEntryDef<?>)) { + return false; + } + JAXXContextEntryDef<?> that = (JAXXContextEntryDef<?>) o; + return klass.equals(that.klass) && + !(name != null ? !name.equals(that.name) : that.name != null); + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + return 31 * result + klass.hashCode(); + } + + public boolean accept(Class<?> klass, String name) { + if (Object.class.equals(klass) && !Object.class.equals(this.klass)) { + // try on name only + return this.name != null && name != null && this.name.equals(name); + } + return klass.isAssignableFrom(this.klass) && (this.name == null && name == null + || (this.name != null && name != null && this.name.equals(name))); + } + + public boolean accept2(Class<?> klass, String name) { + return !(Object.class.equals(klass) && + !Object.class.equals(this.klass)) && + this.klass.isAssignableFrom(klass) && + (this.name == null && name == null || + (this.name != null && name != null && this.name.equals(name)) + ); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/JAXXInitialContext.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/JAXXInitialContext.java new file mode 100644 index 0000000..bb2a685 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/context/JAXXInitialContext.java @@ -0,0 +1,118 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.context; + +import org.nuiton.jaxx.runtime.JAXXContext; +import org.nuiton.jaxx.runtime.JAXXObject; + +import java.util.Map.Entry; + +/** + * An initial context to be inject in a {@link JAXXObject}. + * + * The method {@link #add(Object)} register a simple value. + * + * The method {@link #add(String, Object)} register a named value. + * + * The method {@link #to(JAXXContext)} inject in the {@link JAXXObject} the values registred in the initial context. + * + * The initial context is also a "limited" {@link JAXXContext}, since we can only use the two methods + * + * {@link #getContextValue(Class)} or {@link #getContextValue(Class, String)}. + * + * @see JAXXContext + */ +public class JAXXInitialContext extends DefaultJAXXContext { + + public JAXXInitialContext() { + super(); + } + + /** + * Register a simple (none named) value in the context. + * + * @param value the value to be registred in the context + * @return the instance of the context + */ + public JAXXInitialContext add(Object value) { + return add((String) null, value); + } + + /** + * Register a named value in the context. + * + * @param name the name of the value + * @param value the value to registred + * @return the instance of the context + */ + public JAXXInitialContext add(String name, Object value) { + super.setContextValue(value, name); + return this; + } + + /** + * Register a named (or not) value in the context. + * + * @param <O> type of data to add + * @param def definition of entry + * @param value the value to registred + * @return the instance of the context + */ + public <O> JAXXInitialContext add(JAXXContextEntryDef<O> def, O value) { + super.setContextValue(value, def.getName()); + return this; + } + + /** + * Inject all the registed values into the {@link JAXXObject} + * + * @param dst the object to fill. + */ + public void to(JAXXContext dst) { + if (parentContext != null) { + dst.setContextValue(parentContext); + } + for (Entry<JAXXContextEntryDef<?>, Object> entry : data.entrySet()) { + dst.setContextValue(entry.getValue(), entry.getKey().getName()); + } + } + + @Override + public void setContextValue(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public void setContextValue(Object o, String name) { + throw new UnsupportedOperationException(); + } + + @Override + public <T> void removeContextValue(Class<T> klazz) { + throw new UnsupportedOperationException(); + } + + @Override + public <T> void removeContextValue(Class<T> klazz, String name) { + throw new UnsupportedOperationException(); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/DataBinding.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/DataBinding.java new file mode 100644 index 0000000..89054be --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/DataBinding.java @@ -0,0 +1,49 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.css; + +/** + * Represents a data binding bound to an attribute at runtime. Used by {@link Pseudoclasses} to keep + * track of which data bindings are in effect. + */ +public class DataBinding { + + private String id; + + public DataBinding(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + @Override + public boolean equals(Object o) { + return o instanceof DataBinding && ((DataBinding) o).getId().equals(getId()); + } + + @Override + public int hashCode() { + return id.hashCode(); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/Pseudoclasses.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/Pseudoclasses.java new file mode 100644 index 0000000..b2ea026 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/Pseudoclasses.java @@ -0,0 +1,202 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.css; + +import org.nuiton.jaxx.runtime.JAXXObject; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + +public class Pseudoclasses { + + public static final String NO_PSEUDOCLASS = "no pseudoclass"; + + private static Map<Object, Map<String, List<PropertyValue>>> properties = new WeakHashMap<Object, Map<String, List<PropertyValue>>>(); + + private static class PropertyValue implements Comparable<PropertyValue> { + + private Object value; + + private int id; + + public PropertyValue(Object value, int id) { + this.value = value; + this.id = id; + } + + public Object getValue() { + return value; + } + + public int getId() { + return id; + } + + @Override + public int compareTo(PropertyValue o) { + return getId() - o.getId(); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof PropertyValue)) { + return false; + } + PropertyValue that = (PropertyValue) o; + if (that.getId() != getId()) { + return false; + } + if (that.getValue() == null) { + return getValue() == null; + } + return that.getValue().equals(getValue()); + } + + @Override + public int hashCode() { + return (value != null ? value.hashCode() : 0) ^ id; + } + + @Override + public String toString() { + return "PropertyValue[" + value + ", " + id + "]"; + } + } + + private static List<PropertyValue> getPropertyList(Object object, String property) { + Map<String, List<PropertyValue>> propertyMap = properties.get(object); + if (propertyMap == null) { + propertyMap = new HashMap<String, List<PropertyValue>>(); + properties.put(object, propertyMap); + } + + List<PropertyValue> propertyList = propertyMap.get(property); + if (propertyList == null) { + propertyList = new ArrayList<PropertyValue>(); + propertyMap.put(property, propertyList); + } + + return propertyList; + } + + public static boolean isPropertyApplied(Object object, String property, int id) { + for (PropertyValue aPropertyList : getPropertyList(object, property)) { + if (aPropertyList.getId() == id) { + return true; + } + } + return false; + } + + public static void propertyApplied(Object object, String property, Object value, int id) { + List<PropertyValue> propertyList = getPropertyList(object, property); + propertyList.add(new PropertyValue(value, id)); + Collections.sort(propertyList); + } + + public static void propertyRemoved(Object object, String property, Object value, int id) { + List<PropertyValue> propertyList = getPropertyList(object, property); + propertyList.remove(new PropertyValue(value, id)); + } + + public static Object getCurrentValue(Object object, String property) { + List<PropertyValue> propertyList = getPropertyList(object, property); + if (propertyList.size() > 0) { + return propertyList.get(propertyList.size() - 1).getValue(); + } + return NO_PSEUDOCLASS; + } + + public static Object applyProperty(JAXXObject parent, Object object, String property, Object newValue, Object currentValue, int id) { + if (!isPropertyApplied(object, property, id)) { + Object value = getCurrentValue(object, property); + if (value == NO_PSEUDOCLASS) { + propertyApplied(object, property, wrap(currentValue), -1); + } + propertyApplied(object, property, wrap(newValue), id); + value = getCurrentValue(object, property); + if (value instanceof DataBinding) { + parent.applyDataBinding(((DataBinding) value).getId()); + } + return value; + } else { + return currentValue; + } + } + + public static Object removeProperty(JAXXObject parent, Object object, String property, Object oldValue, Object currentValue, int id) { + if (isPropertyApplied(object, property, id)) { + Object value = getCurrentValue(object, property); + if (value == NO_PSEUDOCLASS) { + throw new IllegalStateException("found NO_PSEUDOCLASS value for a property which does not have a default value"); + } + if (value instanceof DataBinding) { + parent.removeDataBinding(((DataBinding) value).getId()); + } + propertyRemoved(object, property, wrap(oldValue), id); + value = getCurrentValue(object, property); + return value; + } else { + return currentValue; + } + } + + public static Object wrap(boolean value) { + return value; + } + + public static Object wrap(byte value) { + return value; + } + + public static Object wrap(short value) { + return value; + } + + public static Object wrap(int value) { + return value; + } + + public static Object wrap(long value) { + return value; + } + + public static Object wrap(float value) { + return value; + } + + public static Object wrap(double value) { + return value; + } + + public static Object wrap(char value) { + return value; + } + + public static Object wrap(Object value) { + return value; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/Rule.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/Rule.java new file mode 100644 index 0000000..41b7b9f --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/Rule.java @@ -0,0 +1,73 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.css; + +import java.util.Map; + +public class Rule implements java.io.Serializable, Comparable<Rule> { + + public static final String INLINE_ATTRIBUTE = "<inline attribute>"; + + public static final String DATA_BINDING = "<data binding>"; + + private Selector[] selectors; + + private Map<String, String> properties; + + private static final long serialVersionUID = 1L; + + public Rule(Selector[] selectors, Map<String, String> properties) { + this.selectors = selectors; + java.util.Arrays.sort(selectors); + this.properties = properties; + } + + public Rule(Selector[] selectors, String[] keys, String[] values) { + this.selectors = selectors; + java.util.Arrays.sort(selectors); + this.properties = new java.util.HashMap<String, String>(); + if (keys.length != values.length) { + throw new IllegalArgumentException("keys and values must have the same number of entries"); + } + for (int i = 0; i < keys.length; i++) { + properties.put(keys[i], values[i]); + } + } + + public Selector[] getSelectors() { + return selectors; + } + + public Map<String, String> getProperties() { + return properties; + } + + @Override + public int compareTo(Rule o) { + return selectors[0].compareTo(o.selectors[0]); // they are already sorted so we only need to compare the highest-ranked from each one + } + + @Override + public String toString() { + return "Rule[" + java.util.Arrays.asList(selectors) + ", " + properties + "]"; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/Selector.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/Selector.java new file mode 100644 index 0000000..954f339 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/Selector.java @@ -0,0 +1,119 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.css; + +public class Selector implements java.io.Serializable, Comparable<Selector> { + + public static final int NEVER_APPLIES = 0; + + public static final int PSEUDOCLASS_APPLIES_INHERIT_ONLY = 1; + + public static final int PSEUDOCLASS_APPLIES = 2; + + public static final int ALWAYS_APPLIES_INHERIT_ONLY = 3; + + public static final int ALWAYS_APPLIES = 4; + + private String javaClassName; + + private String styleClass; + + private String pseudoClass; + + private String id; + + private boolean inline; + + private static final long serialVersionUID = 1L; + + public Selector(String javaClassName, String styleClass, String pseudoClass, String id) { + this(javaClassName, styleClass, pseudoClass, id, false); + } + + public Selector(String javaClassName, String styleClass, String pseudoClass, String id, boolean inline) { + this.javaClassName = javaClassName; + this.styleClass = styleClass; + this.pseudoClass = pseudoClass; + this.id = id; + this.inline = inline; + } + + public String getJavaClassName() { + return javaClassName; + } + + public String getStyleClass() { + return styleClass; + } + + public String getPseudoClass() { + return pseudoClass; + } + + public String getId() { + return id; + } + + public boolean isInline() { + return inline; + } + + @Override + public int compareTo(Selector selector) { + if (inline && !selector.inline) { + return 1; + } + if (!inline && selector.inline) { + return -1; + } + if (pseudoClass != null && selector.pseudoClass == null) { + return 1; + } + if (pseudoClass == null && selector.pseudoClass != null) { + return -1; + } + if (id != null && selector.id == null) { + return 1; + } + if (id == null && selector.id != null) { + return -1; + } + if (styleClass != null && selector.styleClass == null) { + return 1; + } + if (styleClass == null && selector.styleClass != null) { + return -1; + } + if (javaClassName != null && selector.javaClassName == null) { + return 1; + } + if (javaClassName == null && selector.javaClassName != null) { + return -1; + } + return 0; + } + + @Override + public String toString() { + return "Selector[" + javaClassName + ", " + styleClass + ", " + pseudoClass + ", " + id + "]"; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/Stylesheet.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/Stylesheet.java new file mode 100644 index 0000000..bc8568c --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/css/Stylesheet.java @@ -0,0 +1,63 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.css; + +public class Stylesheet implements java.io.Serializable { + + private Rule[] rules; + + private static final long serialVersionUID = 1L; + + public Stylesheet() { + rules = new Rule[0]; + } + + public Stylesheet(Rule[] rules) { + this.rules = rules; + java.util.Arrays.sort(rules); + } + + public Rule[] getRules() { + return rules; + } + + public void add(Rule newRule) { + Rule[] oldRules = rules; + rules = new Rule[oldRules.length + 1]; + System.arraycopy(oldRules, 0, rules, 0, oldRules.length); + rules[rules.length - 1] = newRule; + java.util.Arrays.sort(rules); + } + + public void add(Rule[] newRules) { + Rule[] oldRules = rules; + rules = new Rule[oldRules.length + newRules.length]; + System.arraycopy(oldRules, 0, rules, 0, oldRules.length); + System.arraycopy(newRules, 0, rules, oldRules.length, newRules.length); + java.util.Arrays.sort(rules); + } + + @Override + public String toString() { + return "Stylesheet" + java.util.Arrays.asList(rules); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/spi/UIHandler.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/spi/UIHandler.java new file mode 100644 index 0000000..9f00bf9 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/spi/UIHandler.java @@ -0,0 +1,38 @@ +package org.nuiton.jaxx.runtime.spi; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.JAXXObject; + +/** + * Created on 11/26/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public interface UIHandler<UI extends JAXXObject> { + + void beforeInit(UI ui); + + void afterInit(UI ui); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/Application.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/Application.java new file mode 100644 index 0000000..1352701 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/Application.java @@ -0,0 +1,72 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import java.awt.GraphicsConfiguration; + +public class Application extends JFrame { + + private static final long serialVersionUID = 1L; + // Special: jaxxc will automatically add a main() method to any components which + // extend <Application> + + public Application() { + } + + public Application(GraphicsConfiguration gc) { + super(gc); + } + + public Application(String title) { + super(title); + } + + public Application(String title, GraphicsConfiguration gc) { + super(title, gc); + } + + public void setLookAndFeel(String lookAndFeel) { + if (lookAndFeel.equals("system")) { + lookAndFeel = UIManager.getSystemLookAndFeelClassName(); + } else if (lookAndFeel.equals("cross_platform")) { + lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName(); + } + try { + UIManager.setLookAndFeel(lookAndFeel); + if (isDisplayable()) { + SwingUtilities.updateComponentTreeUI(this); + } + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (UnsupportedLookAndFeelException e) { + throw new RuntimeException(e); + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/BlockingLayerUI.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/BlockingLayerUI.java new file mode 100644 index 0000000..bd32214 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/BlockingLayerUI.java @@ -0,0 +1,375 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import org.jdesktop.jxlayer.JXLayer; +import org.jdesktop.jxlayer.plaf.AbstractLayerUI; + +import javax.swing.Action; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.image.BufferedImage; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * A JXLayer ui implementation that permits to block a component but still + * allow an action when clicking on the right-top icon painted on the layer. + * + * You can change the blocking and accepting icon. + * + * To hook an click on the layer's icon, you can : + * + * <ul><li>pass an Action via method {@link #setAcceptAction(Action)}</li> + * <li>override the method {@link #acceptEvent(MouseEvent, JXLayer)}</li> + * </ul> + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.2 + */ +public class BlockingLayerUI extends AbstractLayerUI<JComponent> { + + public static final String CAN_CLICK_PROPERTY = "canClick"; + + public static final String ACCEPT_ICON_PROPERTY = "acceptIcon"; + + public static final String BLOCK_ICON_PROPERTY = "blockIcon"; + + public static final String BLOCK_PROPERTY = "block"; +// private static final long serialVersionUID = 1L; + + /** Action to be treated when click on icon */ + protected Action acceptAction; + + /** Icon when you can not click */ + protected BufferedImage blockIcon; + + /** Icon when you can click */ + protected BufferedImage acceptIcon; + + /** Optinal color to put fill background when blocking */ + protected Color blockingColor; + + /** Internal state to known when we can accept click */ + protected boolean canClick; + + /** + * A flag to enable or disable the use of the icon. + * + * If set to false, no icon will be displayed and no action + * will be possible. + * + * By default, this is active. + */ + protected boolean useIcon = true; + + /** Internal state when should block event and paint layer */ + protected boolean block; + + /** Extra components names to accept even in block mode */ + protected final Set<String> acceptedComponentNames; + + /** Extra components types to accept even in block mode */ + protected final Set<Class<?>> acceptedComponentTypes; + + public BlockingLayerUI() { + acceptedComponentNames = new HashSet<String>(); + acceptedComponentTypes = new HashSet<Class<?>>(); + } + + public void setAcceptedComponentNames(String... acceptedComponentNames) { + this.acceptedComponentNames.clear(); + this.acceptedComponentNames.addAll(Arrays.asList(acceptedComponentNames)); + setDirty(true); + } + + public void setAcceptedComponentTypes(Class<?>... acceptedComponentTypes) { + this.acceptedComponentTypes.clear(); + this.acceptedComponentTypes.addAll(Arrays.asList(acceptedComponentTypes)); + setDirty(true); + } + + public void setAcceptAction(Action acceptAction) { + this.acceptAction = acceptAction; + } + + public void setAcceptIcon(ImageIcon acceptIcon) { + this.acceptIcon = prepareIcon(acceptIcon); + firePropertyChange(ACCEPT_ICON_PROPERTY, null, acceptIcon); + setDirty(true); + } + + public void setBlockIcon(ImageIcon blockIcon) { + this.blockIcon = prepareIcon(blockIcon); + firePropertyChange(BLOCK_ICON_PROPERTY, null, blockIcon); + setDirty(true); + } + + public void setCanClick(boolean canClick) { + boolean oldvalue = this.canClick; + this.canClick = canClick; + firePropertyChange(CAN_CLICK_PROPERTY, oldvalue, canClick); + if (oldvalue != canClick) { + setDirty(true); + } + } + + public void setBlock(boolean block) { + boolean oldvalue = this.block; + this.block = block; + firePropertyChange(BLOCK_PROPERTY, oldvalue, block); + if (oldvalue != block) { + setDirty(true); + } + } + + @Override + public void setDirty(boolean isDirty) { + super.setDirty(isDirty); + } + + public void setBlockIcon(BufferedImage blockIcon) { + this.blockIcon = blockIcon; + } + + public void setBlockingColor(Color blockingColor) { + this.blockingColor = blockingColor; + } + + public BufferedImage getBlockIcon() { + return blockIcon; + } + + protected BufferedImage getAcceptIcon() { + return acceptIcon; + } + + public boolean isCanClick() { + return canClick; + } + + public void setUseIcon(boolean useIcon) { + boolean oldvalue = this.useIcon; + this.useIcon = useIcon; + if (oldvalue != useIcon) { + setDirty(true); + } + } + + @Override + public BlockingLayerUI clone() { + BlockingLayerUI clone = new BlockingLayerUI(); + clone.acceptAction = acceptAction; + clone.acceptIcon = acceptIcon; + clone.blockIcon = blockIcon; + clone.useIcon = useIcon; + clone.block = block; + clone.blockingColor = blockingColor; + clone.setCanClick(false); + return clone; + } + + @Override + protected void processKeyEvent(KeyEvent e, JXLayer<? extends JComponent> l) { + if (useIcon) { + e.consume(); + } else if (block) { + + acceptEventOrConsumeIt(e); + + } + } + + @Override + protected void processMouseMotionEvent(MouseEvent e, JXLayer<? extends JComponent> l) { + if (useIcon) { + updateCanClickState(l, e); + e.consume(); + } else if (block) { + + acceptEventOrConsumeIt(e); + + } + } + + @Override + protected void processMouseEvent(MouseEvent e, JXLayer<? extends JComponent> l) { + if (useIcon) { + switch (e.getID()) { + case MouseEvent.MOUSE_ENTERED: + updateCanClickState(l, e); + break; + case MouseEvent.MOUSE_EXITED: + setCanClick(false); + break; + case MouseEvent.MOUSE_CLICKED: + if (canClick) { + acceptEvent(e, l); + } + break; + } + e.consume(); + } else if (block) { + + if (acceptEventOrConsumeIt(e)) { + + switch (e.getID()) { + case MouseEvent.MOUSE_ENTERED: + break; + case MouseEvent.MOUSE_EXITED: + break; + case MouseEvent.MOUSE_CLICKED: + acceptEvent(e, l); + break; + } + + } + + } + + } + + @Override + protected void processMouseWheelEvent(MouseWheelEvent e, JXLayer<? extends JComponent> l) { + + if (useIcon) { + + e.consume(); + } else if (block) { + + if (acceptEventOrConsumeIt(e)) { + acceptEvent(e, l); + } + + } + + } + + protected boolean acceptEventOrConsumeIt(InputEvent e) { + + Object source = e.getSource(); + + boolean accept = source instanceof JComponent; + if (accept) { + + JComponent component = (JComponent) source; + + accept = acceptedComponentNames.contains(component.getName()); + + if (!accept) { + + for (Class<?> acceptedComponentType : acceptedComponentTypes) { + accept = acceptedComponentType.isAssignableFrom(component.getClass()); + if (accept) { + break; + } + } + + } + + } + + if (!accept) { + e.consume(); + } + + return accept; + + } + + @Override + protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { + super.paintLayer(g2, l); + if (block && blockingColor != null) { + // to be in sync with the view if the layer has a border + /*Insets layerInsets = l.getInsets(); + g2.translate(layerInsets.left, layerInsets.top); + + JComponent view = l.getView(); + // To prevent painting on view's border + Insets insets = view.getInsets(); + g2.clip(new Rectangle(insets.left, insets.top, + view.getWidth() - insets.left - insets.right, + view.getHeight() - insets.top - insets.bottom)); + */ + + g2.setColor(blockingColor); + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .1f)); + g2.fillRect(0, 0, l.getWidth(), l.getHeight()); + } + if (useIcon && getCurrentIcon() != null) { + g2.drawImage(getCurrentIcon(), l.getWidth() - getCurrentIcon().getWidth() - 1, 0, null); + } + } + + protected void acceptEvent(MouseEvent e, JXLayer<? extends JComponent> l) { + if (acceptAction != null) { + acceptAction.putValue("layer", l); + Component source = l.getView(); + acceptAction.actionPerformed(new ActionEvent(source, 0, "accept")); + } + } + + protected BufferedImage getCurrentIcon() { + return canClick ? acceptIcon : blockIcon; + } + + protected BufferedImage prepareIcon(ImageIcon image) { + BufferedImage icon = new BufferedImage(image.getIconWidth(), image.getIconHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = (Graphics2D) icon.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g2.drawImage(image.getImage(), 0, 0, null); + g2.dispose(); + return icon; + } + + protected void updateCanClickState(JXLayer<? extends JComponent> l, MouseEvent e) { + // udpate toolTipText + Point layerLocation = l.getView().getLocation(); + Point mousePoint = e.getPoint(); + BufferedImage currentIcon = getCurrentIcon(); + if (currentIcon == null) { + setCanClick(false); + return; + } + int minX = (int) layerLocation.getX() + l.getWidth() - currentIcon.getWidth(); + int maxX = (int) layerLocation.getX() + l.getWidth(); + int minY = 0; + int maxY = currentIcon.getHeight(); + boolean accept = minX <= mousePoint.getX() && mousePoint.getX() <= maxX; + accept &= minY <= mousePoint.getLocation().getY() && mousePoint.getLocation().getY() <= maxY; + setCanClick(accept); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/BlockingLayerUI2.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/BlockingLayerUI2.java new file mode 100644 index 0000000..e8de4ef --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/BlockingLayerUI2.java @@ -0,0 +1,241 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import org.jdesktop.jxlayer.JXLayer; +import org.jdesktop.jxlayer.plaf.AbstractLayerUI; + +import javax.swing.Action; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.image.BufferedImage; + +/** + * A JXLayer ui implementation that permits to block a component but still + * allow an action when clicking everywhere on the layer. + * + * Moreover, an icon can be added on the right-top icon painted and changed + * when the mouse is over the layer. + * + * You can change the blocking and accepting icon. + * + * To hook an click on the layer's icon, you can : + * + * <ul><li>pass an Action via method {@link #setAcceptAction(Action)}</li> + * <li>override the method {@link #acceptEvent(MouseEvent, JXLayer)}</li> + * </ul> + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.3 + */ +public class BlockingLayerUI2 extends AbstractLayerUI<JComponent> { + + public static final String CAN_CLICK_PROPERTY = "canClick"; + + public static final String ACCEPT_ICON_PROPERTY = "acceptIcon"; + + public static final String BLOCK_ICON_PROPERTY = "blockIcon"; + + /** Action to be treated when click on icon */ + protected Action acceptAction; + + /** Icon when you can not click */ + protected BufferedImage blockIcon; + + /** Icon when you can click */ + protected BufferedImage acceptIcon; + + /** Optinal color to put fill background when blocking */ + protected Color blockingColor; + + /** Internal state to known when we can accept click */ + protected boolean canClick; + + public void setAcceptAction(Action acceptAction) { + this.acceptAction = acceptAction; + } + + public void setAcceptIcon(ImageIcon acceptIcon) { + this.acceptIcon = prepareIcon(acceptIcon); + firePropertyChange(ACCEPT_ICON_PROPERTY, null, acceptIcon); + setDirty(true); + } + + public void setBlockIcon(ImageIcon blockIcon) { + this.blockIcon = prepareIcon(blockIcon); + firePropertyChange(BLOCK_ICON_PROPERTY, null, blockIcon); + setDirty(true); + } + + public void setCanClick(boolean canClick) { + boolean oldvalue = this.canClick; + this.canClick = canClick; + firePropertyChange(CAN_CLICK_PROPERTY, oldvalue, canClick); + if (oldvalue != canClick) { + setDirty(true); + } + } + + @Override + public void setDirty(boolean isDirty) { + super.setDirty(isDirty); + } + + public void setBlockingColor(Color blockingColor) { + this.blockingColor = blockingColor; + } + + public void setBlockIcon(BufferedImage blockIcon) { + this.blockIcon = blockIcon; + } + + public BufferedImage getBlockIcon() { + return blockIcon; + } + + protected BufferedImage getAcceptIcon() { + return acceptIcon; + } + + public boolean isCanClick() { + return canClick; + } + + @Override + public BlockingLayerUI2 clone() { + BlockingLayerUI2 clone = new BlockingLayerUI2(); + clone.acceptAction = acceptAction; + clone.acceptIcon = acceptIcon; + clone.blockIcon = blockIcon; + clone.blockingColor = blockingColor; + clone.setCanClick(false); + return clone; + } + + @Override + protected void processKeyEvent(KeyEvent e, JXLayer<? extends JComponent> l) { + e.consume(); + } + + @Override + protected void processMouseMotionEvent(MouseEvent e, JXLayer<? extends JComponent> l) { + e.consume(); + } + + @Override + protected void processMouseWheelEvent(MouseWheelEvent e, JXLayer<? extends JComponent> l) { + e.consume(); + } + + @Override + protected void processMouseEvent(MouseEvent e, JXLayer<? extends JComponent> l) { + switch (e.getID()) { + case MouseEvent.MOUSE_ENTERED: + setCanClick(true); + break; + case MouseEvent.MOUSE_EXITED: + setCanClick(false); + break; + case MouseEvent.MOUSE_CLICKED: + if (canClick) { + acceptEvent(e, l); + } + break; + } + e.consume(); + } + + @Override + protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { + super.paintLayer(g2, l); + if (blockingColor != null) { + // to be in sync with the view if the layer has a border + /*Insets layerInsets = l.getInsets(); + g2.translate(layerInsets.left, layerInsets.top); + + JComponent view = l.getView(); + // To prevent painting on view's border + Insets insets = view.getInsets(); + g2.clip(new Rectangle(insets.left, insets.top, + view.getWidth() - insets.left - insets.right, + view.getHeight() - insets.top - insets.bottom)); + */ + + g2.setColor(blockingColor); + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .1f)); + g2.fillRect(0, 0, l.getWidth(), l.getHeight()); + } + if (getCurrentIcon() != null) { + g2.drawImage(getCurrentIcon(), l.getWidth() - getCurrentIcon().getWidth() - 1, 0, null); + } + } + + protected void acceptEvent(MouseEvent e, JXLayer<? extends JComponent> l) { + if (acceptAction != null) { + acceptAction.putValue("layer", l); + Component source = l.getView(); + acceptAction.actionPerformed(new ActionEvent(source, 0, "accept")); + } + } + + protected BufferedImage getCurrentIcon() { + return canClick ? acceptIcon : blockIcon; + } + + protected BufferedImage prepareIcon(ImageIcon image) { + BufferedImage icon = new BufferedImage(image.getIconWidth(), image.getIconHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = (Graphics2D) icon.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g2.drawImage(image.getImage(), 0, 0, null); + g2.dispose(); + return icon; + } + + protected void updateCanClickState(JXLayer<JComponent> l, MouseEvent e) { + // udpate toolTipText + Point layerLocation = l.getView().getLocation(); + Point mousePoint = e.getPoint(); + BufferedImage currentIcon = getCurrentIcon(); + if (currentIcon == null) { + setCanClick(false); + return; + } + int minX = (int) layerLocation.getX() + l.getWidth() - currentIcon.getWidth(); + int maxX = (int) layerLocation.getX() + l.getWidth(); + int minY = 0; + int maxY = currentIcon.getHeight(); + boolean accept = minX <= mousePoint.getX() && mousePoint.getX() <= maxX; + accept &= minY <= mousePoint.getLocation().getY() && mousePoint.getLocation().getY() <= maxY; + setCanClick(accept); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/CardLayout2.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/CardLayout2.java new file mode 100644 index 0000000..7b01b64 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/CardLayout2.java @@ -0,0 +1,256 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.CardLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Insets; +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; + +/** + * An override of the awt {@link CardLayout}. + * + * Because in the original layout is not overridable : everything is package level accessible. + * + * This new class offers to test if a constrains (as a Serializable) is actually dealed by the layout, + * via the method {@link #contains(Serializable)}. + * + * We had also another method to obtain the current visible component in a container layouted by the class, + * via the method {@link #getVisibleComponent(Container)}. + * + * @author Tony Chemit - chemit@codelutin.com + * @version 1.0 + */ +public class CardLayout2 extends CardLayout { + + /** log */ + static private Log log = LogFactory.getLog(CardLayout2.class); + + private static final long serialVersionUID = 1L; + + /** list of already loaded context (since the {@link #vector} attribute is package visible... */ + protected List<Serializable> contexts = new LinkedList<Serializable>(); + + /** + * A flag to compute dimension only on visible component. + * + * This is usefull when we only care of the visible component. + */ + protected boolean useOnlyVisibleComponentDimension; + + @Override + public void addLayoutComponent(Component comp, Object constraints) { + super.addLayoutComponent(comp, constraints); + contexts.remove(constraints); + contexts.add((Serializable) constraints); + if (log.isDebugEnabled()) { + log.debug(this + " new constraints : " + constraints); + } + } + + public void removeLayoutComponent(Component comp, Serializable constraints) { + removeLayoutComponent(comp); + contexts.remove(constraints); + } + + /** + * Test if a constrains is contained in the layout. + * + * @param constraints l'identifiant a tester + * @return {@code true} si l'identifiant est deja present dans le + * layout, {@code false} otherwise. + */ + public boolean contains(Serializable constraints) { + return contexts.contains(constraints); + } + + /** + * Obtain the visible component in the container. + * + * @param container the container using this layout + * @return the component visible in the container. + */ + public Component getVisibleComponent(Container container) { + checkContainer(container); + for (Component component : container.getComponents()) { + if (component.isVisible()) { + return component; + } + } + // no component actually visible + return null; + } + + public Component getComponent(Container container, String constraints) { + checkContainer(container); + checkConstraints(constraints); + int index = contexts.indexOf(constraints); + return container.getComponents()[index]; + } + + /** + * Determines the preferred size of the container argument using + * this card layout. + * + * @param parent the parent container in which to do the layout + * @return the preferred dimensions to lay out the subcomponents + * of the specified container + * @see Container#getPreferredSize + * @see CardLayout#minimumLayoutSize + */ + @Override + public Dimension preferredLayoutSize(Container parent) { + Dimension dimension = null; + if (useOnlyVisibleComponentDimension) { + Component comp = getVisibleComponent(parent); + if (comp != null) { + dimension = comp.getPreferredSize(); + } + } + if (dimension == null) { + dimension = super.preferredLayoutSize(parent); + } + return dimension; + } + + /** + * Calculates the minimum size for the specified panel. + * + * @param parent the parent container in which to do the layout + * @return the minimum dimensions required to lay out the + * subcomponents of the specified container + * @see Container#doLayout + * @see CardLayout#preferredLayoutSize + */ + @Override + public Dimension minimumLayoutSize(Container parent) { + Dimension dimension = null; + if (useOnlyVisibleComponentDimension) { + Component comp = getVisibleComponent(parent); + if (comp != null) { + dimension = comp.getMinimumSize(); + } + } + if (dimension == null) { + dimension = super.minimumLayoutSize(parent); + } + return dimension; + } + + /** + * Returns the maximum dimensions for this layout given the components + * in the specified target container. + * + * @param target the component which needs to be laid out + * @see Container + * @see #minimumLayoutSize + * @see #preferredLayoutSize + */ + @Override + public Dimension maximumLayoutSize(Container target) { + Dimension dimension = null; + if (useOnlyVisibleComponentDimension) { + Component comp = getVisibleComponent(target); + if (comp != null) { + dimension = comp.getMaximumSize(); + } + } + if (dimension == null) { + dimension = super.maximumLayoutSize(target); + } + return dimension; + } + + /** + * Lays out the specified container using this card layout. + * + * Each component in the <code>parent</code> container is reshaped + * to be the size of the container, minus space for surrounding + * insets, horizontal gaps, and vertical gaps. + * + * @param parent the parent container in which to do the layout + * @see Container#doLayout + */ + @Override + public void layoutContainer(Container parent) { + if (useOnlyVisibleComponentDimension) { + Component comp = getVisibleComponent(parent); + if (comp != null) { + //dimension = comp.getMinimumSize(); + Insets insets = parent.getInsets(); + comp.setBounds(getHgap() + insets.left, getVgap() + insets.top, + parent.getWidth() - (getHgap() * 2 + insets.left + insets.right), + parent.getHeight() - (getVgap() * 2 + insets.top + insets.bottom)); + } else { + super.layoutContainer(parent); + } + } else { + super.layoutContainer(parent); + } + } + + public boolean isUseOnlyVisibleComponentDimension() { + return useOnlyVisibleComponentDimension; + } + + public void setUseOnlyVisibleComponentDimension(boolean useOnlyVisibleComponentDimension) { + this.useOnlyVisibleComponentDimension = useOnlyVisibleComponentDimension; + } + + /** + * remove from cardlayout and linked container all his components. + * + * @param parent the parent container linked with the layout + */ + public void reset(Container parent) { + checkContainer(parent); + for (Component component : parent.getComponents()) { + removeLayoutComponent(component); + parent.remove(component); + } + contexts.clear(); + + } + + protected void checkContainer(Container container) { + if (!equals(container.getLayout())) { + throw new IllegalArgumentException("the container is not managed by the current layout"); + } + } + + protected void checkConstraints(String constraints) { + if (!contains(constraints)) { + throw new IllegalArgumentException("the constraints '" + constraints + "' is not supported by this layout : " + contexts); + } + } + + public Serializable[] getContexts() { + return contexts.toArray(new Serializable[contexts.size()]); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/CardLayout2Ext.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/CardLayout2Ext.java new file mode 100644 index 0000000..a07a7ca --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/CardLayout2Ext.java @@ -0,0 +1,128 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import org.nuiton.jaxx.runtime.JAXXObject; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Container; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +/** + * Une extension de {@link CardLayout2} pour pouvoir automatiquement afficher un + * contenu à partir de la propriété {@link #selected}. + * + * Ainsi, en changeant cette propriété via la méthode {@link #setSelected(String)}, + * le contenu sera changé automatiquement, ce qui permet une utilisation direct + * dans jaxx sans à avoir à écrire d'écouteur. + * + * @author Tony Chemit - chemit@codelutin.com + * @see CardLayout2 + * @since 1.3 + */ +public class CardLayout2Ext extends CardLayout2 { + + /** log */ + static private Log log = LogFactory.getLog(CardLayout2.class); + + private static final long serialVersionUID = 1L; + + public static final String SELECTED_PROPERTY_NAME = "selected"; + + /** pour propager les changements dans le modèle vers l'ui */ + protected PropertyChangeSupport pcs; + + /** le contenu sélectionné */ + protected String selected; + + private String containerName; + + private JAXXObject ui; + + private Container container; + + public CardLayout2Ext(JAXXObject ui, String containerName) { + pcs = new PropertyChangeSupport(this); + this.ui = ui; + this.containerName = containerName; + } + + public String getSelected() { + return selected; + } + + public String getPreviousSelected() { + int index = contexts.indexOf(selected); + if (index < 1) { + return null; + } + return contexts.get(index - 1) + ""; + } + + public String getNextSelected() { + int index = contexts.indexOf(selected); + if (index >= contexts.size()) { + return null; + } + return contexts.get(index + 1) + ""; + } + + public void setSelected(String selected) { + String oldSelected = this.selected; + this.selected = selected; + show(getContainer(), selected); + pcs.firePropertyChange(SELECTED_PROPERTY_NAME, oldSelected, selected); + } + + public Container getContainer() { + if (container == null) { + container = (Container) ui.getObjectById(containerName); + } + return container; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListeners() { + for (PropertyChangeListener l : pcs.getPropertyChangeListeners()) { + pcs.removePropertyChangeListener(l); + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/ComponentMover.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/ComponentMover.java new file mode 100644 index 0000000..120052e --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/ComponentMover.java @@ -0,0 +1,380 @@ +package org.nuiton.jaxx.runtime.swing; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + + +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * This class allows you to move a Component by using a mouse. The Component + * moved can be a high level Window (ie. Window, Frame, Dialog) in which case + * the Window is moved within the desktop. Or the Component can belong to a + * Container in which case the Component is moved within the Container. + * + * When moving a Window, the listener can be added to a child Component of + * the Window. In this case attempting to move the child will result in the + * Window moving. For example, you might create a custom "Title Bar" for an + * undecorated Window and moving of the Window is accomplished by moving the + * title bar only. Multiple components can be registered as "window movers". + * + * Components can be registered when the class is created. Additional + * components can be added at any time using the registerComponent() method. + * + * @since 2.5.10 + */ +public class ComponentMover extends MouseAdapter { + private Insets dragInsets = new Insets(0, 0, 0, 0); + + private Dimension snapSize = new Dimension(1, 1); + + private Insets edgeInsets = new Insets(0, 0, 0, 0); + + private boolean changeCursor = true; + + private boolean autoLayout = false; + + private Class destinationClass; + + private Component destinationComponent; + + private Component destination; + + private Component source; + + private Point pressed; + + private Point location; + + private Cursor originalCursor; + + private boolean autoscrolls; + + private boolean potentialDrag; + + + /** + * Constructor for moving individual components. The components must be + * regisetered using the registerComponent() method. + */ + public ComponentMover() { + } + + /** + * Constructor to specify a Class of Component that will be moved when + * drag events are generated on a registered child component. The events + * will be passed to the first ancestor of this specified class. + * + * @param destinationClass the Class of the ancestor component + * @param components the Components to be registered for forwarding + * drag events to the ancestor Component. + */ + public ComponentMover(Class destinationClass, Component... components) { + this.destinationClass = destinationClass; + registerComponent(components); + } + + /** + * Constructor to specify a parent component that will be moved when drag + * events are generated on a registered child component. + * + * @param destinationComponent the component drage events should be forwareded to + * @param components the Components to be registered for forwarding drag + * events to the parent component to be moved + */ + public ComponentMover(Component destinationComponent, Component... components) { + this.destinationComponent = destinationComponent; + registerComponent(components); + } + + /** + * Get the auto layout property + * + * @return the auto layout property + */ + public boolean isAutoLayout() { + return autoLayout; + } + + /** + * Set the auto layout property + * + * @param autoLayout when true layout will be invoked on the parent container + */ + public void setAutoLayout(boolean autoLayout) { + this.autoLayout = autoLayout; + } + + /** + * Get the change cursor property + * + * @return the change cursor property + */ + public boolean isChangeCursor() { + return changeCursor; + } + + /** + * Set the change cursor property + * + * @param changeCursor when true the cursor will be changed to the + * Cursor.MOVE_CURSOR while the mouse is pressed + */ + public void setChangeCursor(boolean changeCursor) { + this.changeCursor = changeCursor; + } + + /** + * Get the drag insets + * + * @return the drag insets + */ + public Insets getDragInsets() { + return dragInsets; + } + + /** + * Set the drag insets. The insets specify an area where mouseDragged + * events should be ignored and therefore the component will not be moved. + * This will prevent these events from being confused with a + * MouseMotionListener that supports component resizing. + * + * @param dragInsets + */ + public void setDragInsets(Insets dragInsets) { + this.dragInsets = dragInsets; + } + + /** + * Get the bounds insets + * + * @return the bounds insets + */ + public Insets getEdgeInsets() { + return edgeInsets; + } + + /** + * Set the edge insets. The insets specify how close to each edge of the parent + * component that the child component can be moved. Positive values means the + * component must be contained within the parent. Negative values means the + * component can be moved outside the parent. + * + * @param edgeInsets + */ + public void setEdgeInsets(Insets edgeInsets) { + this.edgeInsets = edgeInsets; + } + + /** + * Remove listeners from the specified component + * + * @param components the component the listeners are removed from + */ + public void deregisterComponent(Component... components) { + for (Component component : components) + component.removeMouseListener(this); + } + + /** + * Add the required listeners to the specified component + * + * @param components the component the listeners are added to + */ + public void registerComponent(Component... components) { + for (Component component : components) + component.addMouseListener(this); + } + + /** + * Get the snap size + * + * @return the snap size + */ + public Dimension getSnapSize() { + return snapSize; + } + + /** + * Set the snap size. Forces the component to be snapped to + * the closest grid position. Snapping will occur when the mouse is + * dragged half way. + */ + public void setSnapSize(Dimension snapSize) { + if (snapSize.width < 1 + || snapSize.height < 1) + throw new IllegalArgumentException("Snap sizes must be greater than 0"); + + this.snapSize = snapSize; + } + + /** + * Setup the variables used to control the moving of the component: + * + * source - the source component of the mouse event + * destination - the component that will ultimately be moved + * pressed - the Point where the mouse was pressed in the destination + * component coordinates. + */ + @Override + public void mousePressed(MouseEvent e) { + source = e.getComponent(); + int width = source.getSize().width - dragInsets.left - dragInsets.right; + int height = source.getSize().height - dragInsets.top - dragInsets.bottom; + Rectangle r = new Rectangle(dragInsets.left, dragInsets.top, width, height); + + if (r.contains(e.getPoint())) + setupForDragging(e); + } + + private void setupForDragging(MouseEvent e) { + source.addMouseMotionListener(this); + potentialDrag = true; + + // Determine the component that will ultimately be moved + + if (destinationComponent != null) { + destination = destinationComponent; + } else if (destinationClass == null) { + destination = source; + } else // forward events to destination component + { + destination = SwingUtilities.getAncestorOfClass(destinationClass, source); + } + + pressed = e.getLocationOnScreen(); + location = destination.getLocation(); + + if (changeCursor) { + originalCursor = source.getCursor(); + source.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); + } + + // Making sure autoscrolls is false will allow for smoother dragging of + // individual components + + if (destination instanceof JComponent) { + JComponent jc = (JComponent) destination; + autoscrolls = jc.getAutoscrolls(); + jc.setAutoscrolls(false); + } + } + + /** + * Move the component to its new location. The dragged Point must be in + * the destination coordinates. + */ + @Override + public void mouseDragged(MouseEvent e) { + Point dragged = e.getLocationOnScreen(); + int dragX = getDragDistance(dragged.x, pressed.x, snapSize.width); + int dragY = getDragDistance(dragged.y, pressed.y, snapSize.height); + + int locationX = location.x + dragX; + int locationY = location.y + dragY; + + // Mouse dragged events are not generated for every pixel the mouse + // is moved. Adjust the location to make sure we are still on a + // snap value. + + while (locationX < edgeInsets.left) + locationX += snapSize.width; + + while (locationY < edgeInsets.top) + locationY += snapSize.height; + + Dimension d = getBoundingSize(destination); + + while (locationX + destination.getSize().width + edgeInsets.right > d.width) + locationX -= snapSize.width; + + while (locationY + destination.getSize().height + edgeInsets.bottom > d.height) + locationY -= snapSize.height; + + // Adjustments are finished, move the component + + destination.setLocation(locationX, locationY); + } + + /* + * Determine how far the mouse has moved from where dragging started + * (Assume drag direction is down and right for positive drag distance) + */ + private int getDragDistance(int larger, int smaller, int snapSize) { + int halfway = snapSize / 2; + int drag = larger - smaller; + drag += (drag < 0) ? -halfway : halfway; + drag = (drag / snapSize) * snapSize; + + return drag; + } + + /* + * Get the bounds of the parent of the dragged component. + */ + private Dimension getBoundingSize(Component source) { + if (source instanceof Window) { + GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); + Rectangle bounds = env.getMaximumWindowBounds(); + return new Dimension(bounds.width, bounds.height); + } else { + return source.getParent().getSize(); + } + } + + /** Restore the original state of the Component */ + @Override + public void mouseReleased(MouseEvent e) { + if (!potentialDrag) return; + + source.removeMouseMotionListener(this); + potentialDrag = false; + + if (changeCursor) + source.setCursor(originalCursor); + + if (destination instanceof JComponent) { + ((JComponent) destination).setAutoscrolls(autoscrolls); + } + + // Layout the components on the parent container + + if (autoLayout) { + if (destination instanceof JComponent) { + ((JComponent) destination).revalidate(); + } else { + destination.validate(); + } + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/ComponentResizer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/ComponentResizer.java new file mode 100644 index 0000000..e2254de --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/ComponentResizer.java @@ -0,0 +1,475 @@ +package org.nuiton.jaxx.runtime.swing; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + + +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.HashMap; +import java.util.Map; + +/** + * The ComponentResizer allows you to resize a component by dragging a border + * of the component. + * + * @since 2.5.10 + */ +public class ComponentResizer extends MouseAdapter { + + public static final String DIRECTION_VERTICAL = "vertical"; + public static final String DIRECTION_HORIZONTAL = "horizontal"; + public static final String DIRECTION_BOTH = "both"; + + private final static Dimension MINIMUM_SIZE = new Dimension(10, 10); + + private final static Dimension MAXIMUM_SIZE = + new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + + private static Map<Integer, Integer> cursors = new HashMap<Integer, Integer>(); + + static { + cursors.put(1, Cursor.N_RESIZE_CURSOR); + cursors.put(2, Cursor.W_RESIZE_CURSOR); + cursors.put(4, Cursor.S_RESIZE_CURSOR); + cursors.put(8, Cursor.E_RESIZE_CURSOR); + cursors.put(3, Cursor.NW_RESIZE_CURSOR); + cursors.put(9, Cursor.NE_RESIZE_CURSOR); + cursors.put(6, Cursor.SW_RESIZE_CURSOR); + cursors.put(12, Cursor.SE_RESIZE_CURSOR); + } + + private Insets dragInsets; + + private Dimension snapSize; + + private int direction; + + protected static final int NORTH = 1; + + protected static final int WEST = 2; + + protected static final int SOUTH = 4; + + protected static final int EAST = 8; + + private Cursor sourceCursor; + + private boolean resizing; + + private Rectangle bounds; + + private Point pressed; + + private boolean autoscrolls; + + private Dimension minimumSize = MINIMUM_SIZE; + + private Dimension maximumSize = MAXIMUM_SIZE; + + protected Map<Component, String> authorizedDirectionByComponent = new HashMap<Component, String>(); + + /** + * Convenience contructor. All borders are resizable in increments of + * a single pixel. Components must be registered separately. + */ + public ComponentResizer() { + this(new Insets(5, 5, 5, 5), new Dimension(1, 1)); + } + + /** + * Convenience contructor. All borders are resizable in increments of + * a single pixel. Components can be registered when the class is created + * or they can be registered separately afterwards. + * + * @param components components to be automatically registered + */ + public ComponentResizer(Component... components) { + this(new Insets(5, 5, 5, 5), new Dimension(1, 1), components); + } + + /** + * Convenience contructor. Eligible borders are resisable in increments of + * a single pixel. Components can be registered when the class is created + * or they can be registered separately afterwards. + * + * @param dragInsets Insets specifying which borders are eligible to be + * resized. + * @param components components to be automatically registered + */ + public ComponentResizer(Insets dragInsets, Component... components) { + this(dragInsets, new Dimension(1, 1), components); + } + + /** + * Create a ComponentResizer. + * + * @param dragInsets Insets specifying which borders are eligible to be + * resized. + * @param snapSize Specify the dimension to which the border will snap to + * when being dragged. Snapping occurs at the halfway mark. + * @param components components to be automatically registered + */ + public ComponentResizer(Insets dragInsets, Dimension snapSize, Component... components) { + setDragInsets(dragInsets); + setSnapSize(snapSize); + registerComponent(components); + } + + /** + * Get the drag insets + * + * @return the drag insets + */ + public Insets getDragInsets() { + return dragInsets; + } + + /** + * Set the drag dragInsets. The insets specify an area where mouseDragged + * events are recognized from the edge of the border inwards. A value of + * 0 for any size will imply that the border is not resizable. Otherwise + * the appropriate drag cursor will appear when the mouse is inside the + * resizable border area. + * + * @param dragInsets Insets to control which borders are resizeable. + */ + public void setDragInsets(Insets dragInsets) { + validateMinimumAndInsets(minimumSize, dragInsets); + + this.dragInsets = dragInsets; + } + + /** + * Get the components maximum size. + * + * @return the maximum size + */ + public Dimension getMaximumSize() { + return maximumSize; + } + + /** + * Specify the maximum size for the component. The component will still + * be constrained by the size of its parent. + * + * @param maximumSize the maximum size for a component. + */ + public void setMaximumSize(Dimension maximumSize) { + this.maximumSize = maximumSize; + } + + /** + * Get the components minimum size. + * + * @return the minimum size + */ + public Dimension getMinimumSize() { + return minimumSize; + } + + /** + * Specify the minimum size for the component. The minimum size is + * constrained by the drag insets. + * + * @param minimumSize the minimum size for a component. + */ + public void setMinimumSize(Dimension minimumSize) { + validateMinimumAndInsets(minimumSize, dragInsets); + + this.minimumSize = minimumSize; + } + + /** + * Remove listeners from the specified component + * + * @param components the component the listeners are removed from + */ + public void deregisterComponent(Component... components) { + for (Component component : components) { + component.removeMouseListener(this); + component.removeMouseMotionListener(this); + authorizedDirectionByComponent.remove(component); + } + } + + /** + * Add the required listeners to the specified component + * + * @param components the component the listeners are added to + */ + public void registerComponent(Component... components) { + registerComponent(DIRECTION_BOTH, components); + } + + public void registerComponent(String authorizedDirection, Component... components) { + for (Component component : components) { + component.addMouseListener(this); + component.addMouseMotionListener(this); + authorizedDirectionByComponent.put(component, authorizedDirection); + } + } + + /** + * Get the snap size. + * + * @return the snap size. + */ + public Dimension getSnapSize() { + return snapSize; + } + + /** + * Control how many pixels a border must be dragged before the size of + * the component is changed. The border will snap to the size once + * dragging has passed the halfway mark. + * + * @param snapSize Dimension object allows you to separately spcify a + * horizontal and vertical snap size. + */ + public void setSnapSize(Dimension snapSize) { + this.snapSize = snapSize; + } + + /** + * When the components minimum size is less than the drag insets then + * we can't determine which border should be resized so we need to + * prevent this from happening. + */ + private void validateMinimumAndInsets(Dimension minimum, Insets drag) { + int minimumWidth = drag.left + drag.right; + int minimumHeight = drag.top + drag.bottom; + + if (minimum.width < minimumWidth + || minimum.height < minimumHeight) { + String message = "Minimum size cannot be less than drag insets"; + throw new IllegalArgumentException(message); + } + } + + /** + */ + @Override + public void mouseMoved(MouseEvent e) { + Component source = e.getComponent(); + Point location = e.getPoint(); + direction = 0; + + String authorizedDirection = authorizedDirectionByComponent.get(source); + + if (location.x < dragInsets.left && !DIRECTION_VERTICAL.equals(authorizedDirection)) + direction += WEST; + + if (location.x > source.getWidth() - dragInsets.right - 1 && !DIRECTION_VERTICAL.equals(authorizedDirection)) + direction += EAST; + + if (location.y < dragInsets.top && !DIRECTION_HORIZONTAL.equals(authorizedDirection)) + direction += NORTH; + + if (location.y > source.getHeight() - dragInsets.bottom - 1 && !DIRECTION_HORIZONTAL.equals(authorizedDirection)) + direction += SOUTH; + + // Mouse is no longer over a resizable border + + if (direction == 0) { + source.setCursor(sourceCursor); + } else // use the appropriate resizable cursor + { + int cursorType = cursors.get(direction); + Cursor cursor = Cursor.getPredefinedCursor(cursorType); + source.setCursor(cursor); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + if (!resizing) { + Component source = e.getComponent(); + sourceCursor = source.getCursor(); + } + } + + @Override + public void mouseExited(MouseEvent e) { + if (!resizing) { + Component source = e.getComponent(); + source.setCursor(sourceCursor); + } + } + + @Override + public void mousePressed(MouseEvent e) { + // The mouseMoved event continually updates this variable + + if (direction == 0) return; + + // Setup for resizing. All future dragging calculations are done based + // on the original bounds of the component and mouse pressed location. + + resizing = true; + + Component source = e.getComponent(); + pressed = e.getPoint(); + SwingUtilities.convertPointToScreen(pressed, source); + bounds = source.getBounds(); + + // Making sure autoscrolls is false will allow for smoother resizing + // of components + + if (source instanceof JComponent) { + JComponent jc = (JComponent) source; + autoscrolls = jc.getAutoscrolls(); + jc.setAutoscrolls(false); + } + } + + /** Restore the original state of the Component */ + @Override + public void mouseReleased(MouseEvent e) { + resizing = false; + + Component source = e.getComponent(); + source.setCursor(sourceCursor); + + if (source instanceof JComponent) { + ((JComponent) source).setAutoscrolls(autoscrolls); + } + } + + /** + * Resize the component ensuring location and size is within the bounds + * of the parent container and that the size is within the minimum and + * maximum constraints. + * + * All calculations are done using the bounds of the component when the + * resizing started. + */ + @Override + public void mouseDragged(MouseEvent e) { + if (resizing == false) return; + + Component source = e.getComponent(); + Point dragged = e.getPoint(); + SwingUtilities.convertPointToScreen(dragged, source); + + changeBounds(source, direction, bounds, pressed, dragged); + } + + protected void changeBounds(Component source, int direction, Rectangle bounds, Point pressed, Point current) { + // Start with original locaton and size + + int x = bounds.x; + int y = bounds.y; + int width = bounds.width; + int height = bounds.height; + + // Resizing the West or North border affects the size and location + + if (WEST == (direction & WEST)) { + int drag = getDragDistance(pressed.x, current.x, snapSize.width); + int maximum = Math.min(width + x, maximumSize.width); + drag = getDragBounded(drag, snapSize.width, width, minimumSize.width, maximum); + + x -= drag; + width += drag; + } + + if (NORTH == (direction & NORTH)) { + int drag = getDragDistance(pressed.y, current.y, snapSize.height); + int maximum = Math.min(height + y, maximumSize.height); + drag = getDragBounded(drag, snapSize.height, height, minimumSize.height, maximum); + + y -= drag; + height += drag; + } + + // Resizing the East or South border only affects the size + + if (EAST == (direction & EAST)) { + int drag = getDragDistance(current.x, pressed.x, snapSize.width); + Dimension boundingSize = getBoundingSize(source); + int maximum = Math.min(boundingSize.width - x, maximumSize.width); + drag = getDragBounded(drag, snapSize.width, width, minimumSize.width, maximum); + width += drag; + } + + if (SOUTH == (direction & SOUTH)) { + int drag = getDragDistance(current.y, pressed.y, snapSize.height); + Dimension boundingSize = getBoundingSize(source); + int maximum = Math.min(boundingSize.height - y, maximumSize.height); + drag = getDragBounded(drag, snapSize.height, height, minimumSize.height, maximum); + height += drag; + } + + source.setBounds(x, y, width, height); + source.validate(); + } + + /* + * Determine how far the mouse has moved from where dragging started + */ + private int getDragDistance(int larger, int smaller, int snapSize) { + int halfway = snapSize / 2; + int drag = larger - smaller; + drag += (drag < 0) ? -halfway : halfway; + drag = (drag / snapSize) * snapSize; + + return drag; + } + + /* + * Adjust the drag value to be within the minimum and maximum range. + */ + private int getDragBounded(int drag, int snapSize, int dimension, int minimum, int maximum) { + while (dimension + drag < minimum) + drag += snapSize; + + while (dimension + drag > maximum) + drag -= snapSize; + + + return drag; + } + + /* + * Keep the size of the component within the bounds of its parent. + */ + private Dimension getBoundingSize(Component source) { + if (source instanceof Window) { + GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); + Rectangle bounds = env.getMaximumWindowBounds(); + return new Dimension(bounds.width, bounds.height); + } else { + return source.getParent().getSize(); + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/GBC.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/GBC.java new file mode 100644 index 0000000..64881bc --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/GBC.java @@ -0,0 +1,132 @@ +/* %%Ignore-License +GBC - A convenience class to tame the GridBagLayout + +Copyright (C) 2002 Cay S. Horstmann (http://horstmann.com) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +package org.nuiton.jaxx.runtime.swing; + +import java.awt.GridBagConstraints; +import java.awt.Insets; + +/** + * This class simplifies the use of the GridBagConstraints + * class. + */ +public class GBC extends GridBagConstraints { + private static final long serialVersionUID = -3626882543530638704L; + + /** + * Constructs a GBC with a given gridx and gridy position and + * all other grid bag constraint values set to the default. + * + * @param gridx the gridx position + * @param gridy the gridy position + */ + public GBC(int gridx, int gridy) { + this.gridx = gridx; + this.gridy = gridy; + } + + /** + * Constructs a GBC with given gridx, gridy, gridwidth, gridheight + * and all other grid bag constraint values set to the default. + * + * @param gridx the gridx position + * @param gridy the gridy position + * @param gridwidth the cell span in x-direction + * @param gridheight the cell span in y-direction + */ + public GBC(int gridx, int gridy, int gridwidth, int gridheight) { + this.gridx = gridx; + this.gridy = gridy; + this.gridwidth = gridwidth; + this.gridheight = gridheight; + } + + /** + * Sets the anchor. + * + * @param anchor the anchor value + * @return this object for further modification + */ + public GBC setAnchor(int anchor) { + this.anchor = anchor; + return this; + } + + /** + * Sets the fill direction. + * + * @param fill the fill direction + * @return this object for further modification + */ + public GBC setFill(int fill) { + this.fill = fill; + return this; + } + + /** + * Sets the cell weights. + * + * @param weightx the cell weight in x-direction + * @param weighty the cell weight in y-direction + * @return this object for further modification + */ + public GBC setWeight(double weightx, double weighty) { + this.weightx = weightx; + this.weighty = weighty; + return this; + } + + /** + * Sets the insets of this cell. + * + * @param distance the spacing to use in all directions + * @return this object for further modification + */ + public GBC setInsets(int distance) { + this.insets = new Insets(distance, distance, distance, distance); + return this; + } + + /** + * Sets the insets of this cell. + * + * @param top the spacing to use on top + * @param left the spacing to use to the left + * @param bottom the spacing to use on the bottom + * @param right the spacing to use to the right + * @return this object for further modification + */ + public GBC setInsets(int top, int left, int bottom, int right) { + this.insets = new Insets(top, left, bottom, right); + return this; + } + + /** + * Sets the internal padding + * + * @param ipadx the internal padding in x-direction + * @param ipady the internal padding in y-direction + * @return this object for further modification + */ + public GBC setIpad(int ipadx, int ipady) { + this.ipadx = ipadx; + this.ipady = ipady; + return this; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/HBox.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/HBox.java new file mode 100644 index 0000000..cc26da5 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/HBox.java @@ -0,0 +1,116 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.JPanel; +import java.awt.Insets; + +/** + * Panel which uses an {@link HBoxLayout} by default. + * + * @author Ethan Nicholas + */ +public class HBox extends JPanel { + + private static final long serialVersionUID = 1L; + + public static final String SPACING_PROPERTY = "spacing"; + + public static final String MARGIN_PROPERTY = "margin"; + + public static final String HORIZONTAL_ALIGNMENT_PROPERTY = "horizontalAlignment"; + + public static final String VERTICAL_ALIGNMENT_PROPERTY = "verticalAlignment"; + + private Insets margin; + + public HBox() { + super(new HBoxLayout()); + } + + /** + * Returns the spacing between components, in pixels. Spacing is applied between components only, + * not to the top or bottom of the container. + * + * @return spacing between components + */ + public int getSpacing() { + return ((HBoxLayout) getLayout()).getSpacing(); + } + + /** + * Sets the spacing between components. Spacing is applied between components only, + * not to the top or bottom of the container. + * + * @param spacing new spacing value + */ + public void setSpacing(int spacing) { + int oldValue = getSpacing(); + ((HBoxLayout) getLayout()).setSpacing(spacing); + firePropertyChange(SPACING_PROPERTY, oldValue, spacing); + revalidate(); + } + + public int getHorizontalAlignment() { + return ((HBoxLayout) getLayout()).getHorizontalAlignment(); + } + + public void setHorizontalAlignment(int horizontalAlignment) { + int oldValue = getHorizontalAlignment(); + ((HBoxLayout) getLayout()).setHorizontalAlignment(horizontalAlignment); + firePropertyChange(HORIZONTAL_ALIGNMENT_PROPERTY, oldValue, horizontalAlignment); + revalidate(); + } + + public int getVerticalAlignment() { + return ((HBoxLayout) getLayout()).getVerticalAlignment(); + } + + public void setVerticalAlignment(int verticalAlignment) { + int oldValue = getVerticalAlignment(); + ((HBoxLayout) getLayout()).setVerticalAlignment(verticalAlignment); + firePropertyChange(VERTICAL_ALIGNMENT_PROPERTY, oldValue, verticalAlignment); + revalidate(); + } + + public Insets getMargin() { + return margin; + } + + public void setMargin(Insets margin) { + Insets oldValue = this.margin; + this.margin = (Insets) margin.clone(); + firePropertyChange(MARGIN_PROPERTY, oldValue, margin); + } + + @Override + public Insets getInsets() { + Insets result = super.getInsets(); + if (margin != null) { + result.top += margin.top; + result.left += margin.left; + result.right += margin.right; + result.bottom += margin.bottom; + } + return result; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/HBoxBeanInfo.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/HBoxBeanInfo.java new file mode 100644 index 0000000..a0202b1 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/HBoxBeanInfo.java @@ -0,0 +1,73 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.beans.SimpleBeanInfo; + +public class HBoxBeanInfo extends SimpleBeanInfo { + + @Override + public BeanInfo[] getAdditionalBeanInfo() { + try { + return new BeanInfo[]{Introspector.getBeanInfo(JPanel.class)}; + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + } + + @Override + public PropertyDescriptor[] getPropertyDescriptors() { + try { + PropertyDescriptor spacing = new PropertyDescriptor("spacing", HBox.class); + spacing.setBound(true); + + PropertyDescriptor margin = new PropertyDescriptor("margin", HBox.class); + margin.setBound(true); + + PropertyDescriptor horizontalAlignment = new PropertyDescriptor("horizontalAlignment", HBox.class); + horizontalAlignment.setBound(true); + horizontalAlignment.setValue("enumerationValues", new Object[]{ + "left", SwingConstants.LEFT, "SwingConstants.LEFT", + "center", SwingConstants.CENTER, "SwingConstants.CENTER", + "right", SwingConstants.RIGHT, "SwingConstants.RIGHT" + }); + + PropertyDescriptor verticalAlignment = new PropertyDescriptor("verticalAlignment", HBox.class); + verticalAlignment.setBound(true); + verticalAlignment.setValue("enumerationValues", new Object[]{ + "top", SwingConstants.TOP, "SwingConstants.TOP", + "middle", SwingConstants.CENTER, "SwingConstants.CENTER", + "bottom", SwingConstants.BOTTOM, "SwingConstants.BOTTOM" + }); + + return new PropertyDescriptor[]{spacing, margin, horizontalAlignment, verticalAlignment}; + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/HBoxLayout.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/HBoxLayout.java new file mode 100644 index 0000000..7044f95 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/HBoxLayout.java @@ -0,0 +1,146 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.SwingConstants; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.LayoutManager; + +/** + * Horizontal box layout. The layout rules followed by this class are quite different than the core BoxLayout class, + * and in general represent a more useful algorithm. + * + * @author Ethan Nicholas + */ +public class HBoxLayout implements LayoutManager { + + private int spacing = 6; + + private int horizontalAlignment = SwingConstants.LEFT; + + private int verticalAlignment = SwingConstants.TOP; + + public int getSpacing() { + return spacing; + } + + public void setSpacing(int spacing) { + this.spacing = spacing; + } + + public int getHorizontalAlignment() { + return horizontalAlignment; + } + + public void setHorizontalAlignment(int horizontalAlignment) { + this.horizontalAlignment = horizontalAlignment; + } + + public int getVerticalAlignment() { + return verticalAlignment; + } + + public void setVerticalAlignment(int verticalAlignment) { + this.verticalAlignment = verticalAlignment; + } + + @Override + public void addLayoutComponent(String name, Component comp) { + } + + @Override + public void layoutContainer(Container parent) { + Insets insets = parent.getInsets(); + int parentHeight = parent.getSize().height - insets.top - insets.bottom; + int count = parent.getComponentCount(); + Dimension preferredSize = parent.getPreferredSize(); + int x; + switch (horizontalAlignment) { + case SwingConstants.LEFT: + x = insets.left; + break; + case SwingConstants.CENTER: + x = insets.left + (parent.getWidth() - preferredSize.width) / 2; + break; + case SwingConstants.RIGHT: + x = insets.left + (parent.getWidth() - preferredSize.width); + break; + default: + throw new IllegalArgumentException("invalid horizontal alignment: " + horizontalAlignment); + } + + for (int i = 0; i < count; i++) { + Component component = parent.getComponent(i); + Dimension childPreferredSize = component.getPreferredSize(); + int height = Math.min(childPreferredSize.height, parentHeight); + int y; + switch (verticalAlignment) { + case SwingConstants.TOP: + y = insets.top; + break; + case SwingConstants.CENTER: + y = insets.top + (parentHeight - childPreferredSize.height) / 2; + break; + case SwingConstants.BOTTOM: + y = insets.top + (parentHeight - childPreferredSize.height); + break; + default: + throw new IllegalArgumentException("invalid vertical alignment: " + verticalAlignment); + } + component.setBounds(x, y, childPreferredSize.width, height); + x += childPreferredSize.width + spacing; + } + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + int width = (parent.getComponentCount() - 1) * spacing; + int height = 0; + for (int i = parent.getComponentCount() - 1; i >= 0; i--) { + Dimension minimumSize = parent.getComponent(i).getMinimumSize(); + width += minimumSize.width; + height = Math.max(height, minimumSize.height); + } + Insets insets = parent.getInsets(); + return new Dimension(width + insets.left + insets.right, height + insets.top + insets.bottom); + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + int width = (parent.getComponentCount() - 1) * spacing; + int height = 0; + for (int i = parent.getComponentCount() - 1; i >= 0; i--) { + Dimension preferredSize = parent.getComponent(i).getPreferredSize(); + width += preferredSize.width; + height = Math.max(height, preferredSize.height); + } + Insets insets = parent.getInsets(); + return new Dimension(width + insets.left + insets.right, height + insets.top + insets.bottom); + } + + @Override + public void removeLayoutComponent(Component comp) { + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/Item.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/Item.java new file mode 100644 index 0000000..38875ec --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/Item.java @@ -0,0 +1,250 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.event.SwingPropertyChangeSupport; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.List; + +// This needs to be split into two classes, Item and TreeItem + +/** + * An item in a component such as <code>JComboBox</code> or <code>JTree</code>. The <code>Item</code> + * class corresponds to the <code><item></code> tag in JAXX source files. + */ +public class Item { + + public static final String LABEL_PROPERTY = "label"; + + public static final String VALUE_PROPERTY = "value"; + + public static final String SELECTED_PROPERTY = "selected"; + + private String id; + + private String label; + + private Object value; + + private boolean selected; + + private List<Item> children; + + private Item parent; + + private PropertyChangeSupport propertyChangeSupport; + + /** + * Creates a new Item. This should only be called from compiled JAXX files. + * + * @param id the item's ID + * @param label the string that should be used to represent the item visually + * @param value the item's actual value + * @param selected <code>true</code> if the item should be selected by default + */ + public Item(String id, String label, Object value, boolean selected) { + this.id = id; + this.label = label; + this.value = value; + this.selected = selected; + } + + /** + * Returns this item's ID. + * + * @return the JAXX ID attribute + */ + public String getId() { + return id; + } + + /** + * Returns the string that should be used to represent the item at display time. If <code>null</code>, + * <code>String.valueOf(getValue())</code> will be used instead. + * + * @return this item's display string + * @see #setLabel + */ + public String getLabel() { + return label; + } + + /** + * Sets the item's display string. If <code>null, String.valueOf(getValue())</code> will be used instead. + * + * @param label the new display string + * @see #getLabel + */ + public void setLabel(String label) { + String oldLabel = this.label; + this.label = label; + firePropertyChange(LABEL_PROPERTY, oldLabel, label); + } + + /** + * Returns the item's actual value as it appears in the component's model. The <code>Item</code> itself is not + * visible from the model, only the value. + * + * @return the item's value + * @see #setValue + */ + public Object getValue() { + return value; + } + + /** + * Sets the item's value as it appears in the component's model. The <code>Item</code> itself is not + * visible from the model, only the value. + * + * @param value the new value + * @see #getValue + */ + public void setValue(Object value) { + Object oldValue = this.value; + this.value = value; + firePropertyChange(VALUE_PROPERTY, oldValue, value); + } + + /** + * Returns <code>true</code> if this item is currently selected. This is a bound property. + * + * @return <code>true</code> if item is selected + * @see #setSelected + */ + public boolean isSelected() { + return selected; + } + + /** + * Sets the item's selection state. This is a bound property. + * + * @param selected the new selection state + * @see #isSelected + */ + public void setSelected(boolean selected) { + boolean oldSelected = this.selected; + this.selected = selected; + firePropertyChange(SELECTED_PROPERTY, oldSelected, selected); + } + + /** + * Adds a new child node (Items can be nested in trees). + * + * @param item the new child item + */ + public void addChild(Item item) { + if (children == null) { + children = new ArrayList<Item>(); + } + children.add(item); + item.parent = this; + } + + /** + * Remove child node a new child node + * + * @param item to remove + */ + public void removeChild(Item item) { + if (children != null) { + children.remove(item); + } + } + + /** + * Remove all childs nodes + * + * @param items list of items to remove + */ + public void removeChilds(List<Item> items) { + if (children != null) { + children.removeAll(items); + } + } + + /** + * Returns a list of this item's children. + * + * @return a list of all nested child nodes + */ + public List<Item> getChildren() { + if (children == null) { + children = new ArrayList<Item>(); + } + return children; + } + + /** + * Returns the <code>Item</code> containing this <code>Item</code>, or <code>null</code> for a top-level + * <code>Item</code>. + * + * @return the item parent (or null) + */ + public Item getParent() { + return parent; + } + + /** + * Set the parent of this item + * + * @param parent the item parent (or null) + */ + public void setParent(Item parent) { + this.parent = parent; + } + + private PropertyChangeSupport getPropertyChangeSupport() { + if (propertyChangeSupport == null) { + propertyChangeSupport = new SwingPropertyChangeSupport(this); + } + return propertyChangeSupport; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + getPropertyChangeSupport().addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String property, PropertyChangeListener listener) { + getPropertyChangeSupport().addPropertyChangeListener(property, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + getPropertyChangeSupport().removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String property, PropertyChangeListener listener) { + getPropertyChangeSupport().removePropertyChangeListener(property, listener); + } + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + if (propertyChangeSupport != null) { + getPropertyChangeSupport().firePropertyChange(propertyName, oldValue, newValue); + } + } + + @Override + public String toString() { + return getClass().getName() + "[" + value + "]"; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXButtonGroup.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXButtonGroup.java new file mode 100644 index 0000000..9deeba0 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXButtonGroup.java @@ -0,0 +1,250 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.AbstractButton; +import javax.swing.ButtonGroup; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Enumeration; + +public class JAXXButtonGroup extends ButtonGroup { + + public static final String SELECTED_VALUE_PROPERTY = "selectedValue"; + + public static final String BUTTON8GROUP_CLIENT_PROPERTY = "$buttonGroup"; + + public static final String VALUE_CLIENT_PROPERTY = "$value"; + + public static final String SELECTED_TIP_CLIENT_PROPERTY = "$selected.toolTipText"; + + public static final String NOT_SELECTED_TIP_CLIENT_PROPERTY = "$not.selected.toolTipText"; + + protected EventListenerList listenerList = new EventListenerList(); + + private PropertyChangeSupport propertyChangeSupport; + + private transient Object selectedValue; + + protected boolean useToolTipText; + + protected transient ChangeEvent changeEvent = new ChangeEvent(this); + + private transient ChangeListener changeListener = new ChangeListener() { + + @Override + public void stateChanged(ChangeEvent e) { + updateSelectedValue(); + if (useToolTipText) { + updateToolTipText(); + } + } + }; + + private static final long serialVersionUID = 1L; + + @Override + public void add(AbstractButton button) { + super.add(button); + button.addChangeListener(changeListener); + updateSelectedValue(); + } + + @Override + public void remove(AbstractButton button) { + super.remove(button); + button.removeChangeListener(changeListener); + updateSelectedValue(); + } + + public void updateSelectedValue() { + Enumeration<AbstractButton> e = getElements(); + while (e.hasMoreElements()) { + AbstractButton button = e.nextElement(); + if (button.isSelected()) { + Object buttonValue = button.getClientProperty(VALUE_CLIENT_PROPERTY); + if (buttonValue != getSelectedValue()) { + setSelectedValue(buttonValue); + } + } + } + } + + public void updateToolTipText() { + Enumeration<AbstractButton> e = getElements(); + while (e.hasMoreElements()) { + AbstractButton button = e.nextElement(); + String key = button.isSelected() ? SELECTED_TIP_CLIENT_PROPERTY : NOT_SELECTED_TIP_CLIENT_PROPERTY; + button.setToolTipText((String) button.getClientProperty(key)); + } + } + + public boolean isUseToolTipText() { + return useToolTipText; + } + + public Object getSelectedValue() { + return selectedValue; + } + + public AbstractButton getSelectedButton() { + Enumeration<AbstractButton> e = getElements(); + while (e.hasMoreElements()) { + AbstractButton button = e.nextElement(); + if (button.isSelected()) { + return button; + } + } + return null; + } + + public AbstractButton getButton(Object value) { + Enumeration<AbstractButton> e = getElements(); + while (e.hasMoreElements()) { + AbstractButton button = e.nextElement(); + Object buttonValue = button.getClientProperty(VALUE_CLIENT_PROPERTY); + if (value.equals(buttonValue)) { + return button; + } + } + return null; + } + + public void setSelectedValue(Object value) { + Object oldValue = getSelectedValue(); + this.selectedValue = value; + firePropertyChange(oldValue); + } + + public void setUseToolTipText(boolean useToolTipText) { + this.useToolTipText = useToolTipText; + } + + public void setSelectedButton(Object value) { + setSelectedValue(value); + if (value == null) { + Enumeration<AbstractButton> e = getElements(); + while (e.hasMoreElements()) { + AbstractButton button = e.nextElement(); + setSelected(button.getModel(), false); + } + return; + } + + Enumeration<AbstractButton> e = getElements(); + while (e.hasMoreElements()) { + AbstractButton button = e.nextElement(); + Object buttonValue = button.getClientProperty(VALUE_CLIENT_PROPERTY); + if (value.equals(buttonValue)) { + button.setSelected(true); + break; + } + } + } + + protected PropertyChangeSupport getPropertyChangeSupport() { + if (propertyChangeSupport == null) { + propertyChangeSupport = new PropertyChangeSupport(this); + } + return propertyChangeSupport; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + getPropertyChangeSupport().addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String property, PropertyChangeListener listener) { + getPropertyChangeSupport().addPropertyChangeListener(property, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + getPropertyChangeSupport().removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String property, PropertyChangeListener listener) { + getPropertyChangeSupport().removePropertyChangeListener(property, listener); + } + + private void firePropertyChange(Object oldValue) { + if (propertyChangeSupport != null) { + getPropertyChangeSupport().firePropertyChange(SELECTED_VALUE_PROPERTY, + oldValue, getSelectedValue()); + } + fireStateChanged(); + } + + /** + * Adds a <code>ChangeListener</code> to the button. + * + * @param l the listener to be added + */ + public void addChangeListener(ChangeListener l) { + listenerList.add(ChangeListener.class, l); + } + + /** + * Removes a ChangeListener from the button. + * + * @param l the listener to be removed + */ + public void removeChangeListener(ChangeListener l) { + listenerList.remove(ChangeListener.class, l); + } + + /** + * Returns an array of all the <code>ChangeListener</code>s added + * to this AbstractButton with addChangeListener(). + * + * @return all of the <code>ChangeListener</code>s added or an empty + * array if no listeners have been added + * @since 1.4 + */ + public ChangeListener[] getChangeListeners() { + return listenerList.getListeners(ChangeListener.class); + } + + /** + * Notifies all listeners that have registered interest for + * notification on this event type. The event instance + * is lazily created. + * + * @see EventListenerList + */ + protected void fireStateChanged() { + // Guaranteed to return a non-null array + Object[] listeners = listenerList.getListenerList(); + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + // Lazily create the event: + if (changeEvent == null) { + changeEvent = new ChangeEvent(this); + } + ((ChangeListener) listeners[i + 1]).stateChanged(changeEvent); + } + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXComboBox.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXComboBox.java new file mode 100644 index 0000000..101a062 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXComboBox.java @@ -0,0 +1,312 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.AbstractListModel; +import javax.swing.ComboBoxModel; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JComboBox; +import javax.swing.JList; +import javax.swing.ListModel; +import java.awt.Component; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class JAXXComboBox extends JComboBox { + + private static final long serialVersionUID = 1L; + + public class JAXXComboBoxModel extends AbstractListModel implements ComboBoxModel { + + private List<Item> items; + + private Object selectedItem; + + private static final long serialVersionUID = -8940733376638766414L; + + public JAXXComboBoxModel(List<Item> items) { + this.items = items; + + PropertyChangeListener listener = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent e) { + if (e.getPropertyName().equals(Item.SELECTED_PROPERTY)) { + Item item = (Item) e.getSource(); + int itemIndex = JAXXComboBoxModel.this.items.indexOf(item); + // TODO: fix cut-and-pasting badness + int[] oldSelection = new int[]{getSelectedIndex()}; + int[] newSelection; + int index = -1; + for (int i = 0; i < oldSelection.length; i++) { + if (oldSelection[i] == itemIndex) { + index = i; + break; + } + } + if (item.isSelected()) { + if (index != -1) // it was already selected + { + return; + } + newSelection = new int[oldSelection.length + 1]; + System.arraycopy(oldSelection, 0, newSelection, 0, oldSelection.length); + newSelection[newSelection.length - 1] = itemIndex; + } else { + if (index == -1) // it already wasn't selected + { + return; + } + newSelection = new int[oldSelection.length - 1]; + System.arraycopy(oldSelection, 0, newSelection, 0, index); + System.arraycopy(oldSelection, index + 1, newSelection, index, oldSelection.length - 1 - index); + } + if (newSelection.length > 0) { + setSelectedIndex(newSelection[0]); + } + } else { + // TODO: more cut-and-pasting badness + for (int i = 0; i < getSize(); i++) { + if (getElementAt(i) == ((Item) e.getSource()).getValue()) { + fireContentsChanged(JAXXComboBoxModel.this, i, i); + if (getSelectedIndex() == i) { + fireItemStateChanged(new ItemEvent(JAXXComboBox.this, ItemEvent.ITEM_STATE_CHANGED, getElementAt(i), ItemEvent.DESELECTED)); + } + return; + } + } + } + } + }; + for (Item item : items) { + item.addPropertyChangeListener(listener); + } + } + + public List<Item> getItems() { + return items; + } + + @Override + public Object getElementAt(int i) { + return items.get(i).getValue(); + } + + @Override + public int getSize() { + return items.size(); + } + + @Override + public Object getSelectedItem() { + return selectedItem; + } + + @Override + public void setSelectedItem(Object selectedItem) { + if (this.selectedItem != null && !this.selectedItem.equals(selectedItem) || + this.selectedItem == null && selectedItem != null) { + this.selectedItem = selectedItem; + fireContentsChanged(this, -1, -1); + } + } + } + + public JAXXComboBox() { + setRenderer(new DefaultListCellRenderer() { + + private static final long serialVersionUID = 1L; + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + ListModel model = list.getModel(); + if (model instanceof JAXXComboBoxModel) { + List/*<Item>*/ items = ((JAXXComboBoxModel) model).items; + Item item = null; + if (index == -1) { + for (Object item1 : items) { + Item testItem = (Item) item1; + if (testItem.getValue() == value) { + item = testItem; + break; + } + } + } else { + item = (Item) items.get(index); + } + + if (item != null) { + String label = item.getLabel(); + if (label != null) { + value = label; + } + } + } + return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } + }); + + addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent e) { + ListModel model = getModel(); + if (model instanceof JAXXComboBoxModel) { + List<Item> items = ((JAXXComboBoxModel) model).items; + for (int i = items.size() - 1; i >= 0; i--) { + boolean selected = getSelectedIndex() == i; + Item item = items.get(i); + if (selected != item.isSelected()) { + item.setSelected(selected); + } + } + } + } + }); + } + + /** + * Fill a combo box model with some datas, and select after all the given object + * + * @param data data ot inject in combo + * @param select the object to select in combo after reflling his model + * @param methodName method to invoke to display data's name + */ + public void fillComboBox(Collection<?> data, Object select, String methodName) { + // prepare method to use + Method m; + try { + m = select.getClass().getMethod(methodName); + m.setAccessible(true); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("could not find method " + methodName + " on " + select.getClass()); + } + + List<Item> items = new ArrayList<Item>(); + for (Object o : data) { + boolean selected = o.equals(select); + try { + items.add(new Item(o.toString(), (String) m.invoke(o), o, selected)); + } catch (IllegalAccessException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } + } + setItems(items); + } + + // this way we can keep it marked protected and still allow code in this file to call it + + @Override + protected void fireItemStateChanged(ItemEvent e) { + super.fireItemStateChanged(e); + } + + public void setItems(List<Item> items) { + setModel(new JAXXComboBoxModel(items)); + List<Integer> selectedIndexList = new ArrayList<Integer>(); + for (int i = 0; i < items.size(); i++) { + if (items.get(i).isSelected()) { + selectedIndexList.add(i); + } + } + int[] selectedIndices = new int[selectedIndexList.size()]; + for (int i = 0; i < selectedIndexList.size(); i++) { + selectedIndices[i] = selectedIndexList.get(i); + } + if (selectedIndices.length > 0) { + setSelectedIndex(selectedIndices[0]); + } + } + + public List<Item> getItems() { + if (getModel() instanceof JAXXComboBoxModel) { + return ((JAXXComboBoxModel) getModel()).getItems(); + } + return null; + } + + public void setSelectedItem(Item item) { + //TC-20092004 Anomalie #73 fix npe when want to call with a null + // value + super.setSelectedItem(item == null ? null : item.getValue()); + } + + public Item getSelectedJaxxItem() { + Object selected = super.getSelectedItem(); + return findItem(selected); + } + + public Item findItem(Object value) { + List<Item> items = getItems(); + if (items != null) { + for (Item i : items) { + if (i.getValue().equals(value)) { + return i; + } + } + } + return null; + } + + public void addItem(Item item) { + List<Item> items = getItems(); + if (items != null) { + items.add(item); + setItems(items); + } + } + + public void addAllItems(Collection<Item> itemsToAdd) { + List<Item> items = getItems(); + if (items != null) { + items.addAll(itemsToAdd); + setItems(items); + } + } + + public void removeItem(Item item) { + List<Item> items = getItems(); + if (items != null) { + items.remove(item); + setItems(items); + } + } + + public void removeAllItems(Collection<Item> itemsToRemove) { + List<Item> items = getItems(); + if (items != null) { + items.removeAll(itemsToRemove); + setItems(items); + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXList.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXList.java new file mode 100644 index 0000000..d39bd8c --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXList.java @@ -0,0 +1,414 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.AbstractListModel; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JList; +import javax.swing.ListModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class JAXXList extends JList { + + private static final long serialVersionUID = 1L; + + public class JAXXListModel extends AbstractListModel { + + private List<Item> items; + + private static final long serialVersionUID = -1598924187490122036L; + + public JAXXListModel(List<Item> items) { + this.items = items; + + PropertyChangeListener listener = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent e) { + if (e.getPropertyName().equals(Item.SELECTED_PROPERTY)) { + Item item = (Item) e.getSource(); + int itemIndex = JAXXListModel.this.items.indexOf(item); + int[] oldSelection = getSelectedIndices(); + int[] newSelection; + int index = -1; + for (int i = 0; i < oldSelection.length; i++) { + if (oldSelection[i] == itemIndex) { + index = i; + break; + } + } + if (item.isSelected()) { + if (index != -1) // it was already selected + { + return; + } + newSelection = new int[oldSelection.length + 1]; + System.arraycopy(oldSelection, 0, newSelection, 0, oldSelection.length); + newSelection[newSelection.length - 1] = itemIndex; + } else { + if (index == -1) // it already wasn't selected + { + return; + } + newSelection = new int[oldSelection.length - 1]; + System.arraycopy(oldSelection, 0, newSelection, 0, index); + System.arraycopy(oldSelection, index + 1, newSelection, index, oldSelection.length - 1 - index); + } + setSelectedIndices(newSelection); + } else { + for (int i = 0; i < getSize(); i++) { + if (getElementAt(i) == ((Item) e.getSource()).getValue()) { + fireContentsChanged(JAXXListModel.this, i, i); + if (isSelectedIndex(i)) { + fireSelectionValueChanged(i, i, false); + } + return; + } + } + } + } + }; + for (Item item : items) { + item.addPropertyChangeListener(listener); + } + } + + public List<Item> getItems() { + return items; + } + + @Override + public Object getElementAt(int i) { + return items.get(i).getValue(); + } + + @Override + public int getSize() { + return items.size(); + } + } + + public JAXXList() { + setCellRenderer(new DefaultListCellRenderer() { + + private static final long serialVersionUID = 1L; + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + ListModel model = list.getModel(); + if (model instanceof JAXXListModel) { + Item item = ((JAXXListModel) model).items.get(index); + String label = item.getLabel(); + if (label != null) { + value = label; + } + } + return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } + }); + + addListSelectionListener(new ListSelectionListener() { + + @Override + public void valueChanged(ListSelectionEvent e) { + ListModel model = getModel(); + if (model instanceof JAXXListModel) { + List<Item> items = ((JAXXListModel) model).items; + for (int i = items.size() - 1; i >= 0; i--) { + boolean selected = isSelectedIndex(i); + Item item = items.get(i); + if (selected != item.isSelected()) { + item.setSelected(selected); + } + } + } + } + }); + } + + // this way we can keep it marked protected and still allow code in this file to call it + + @Override + protected void fireSelectionValueChanged(int firstIndex, int lastIndex, boolean isAdjusting) { + super.fireSelectionValueChanged(firstIndex, lastIndex, isAdjusting); + } + + public void setItems(List<Item> items) { + setModel(new JAXXListModel(items)); + List<Integer> selectedIndexList = new ArrayList<Integer>(); + for (int i = 0; i < items.size(); i++) { + if (items.get(i).isSelected()) { + selectedIndexList.add(i); + } + } + int[] selectedIndices = new int[selectedIndexList.size()]; + for (int i = 0; i < selectedIndexList.size(); i++) { + selectedIndices[i] = selectedIndexList.get(i); + } + setSelectedIndices(selectedIndices); + } + + public List<Item> getItems() { + if (getModel() instanceof JAXXListModel) { + return ((JAXXListModel) getModel()).getItems(); + } + return null; + } + + public void setSelectedValue(Object value) { + super.setSelectedValue(value, true); + } + + /** + * Set the selected Objects + * + * @param values Objects must be selected in the list + */ + public void setSelectedValues(Object[] values) { + if (values != null) { + List<Integer> selectedIndices = new ArrayList<Integer>(); + ListModel model = getModel(); + for (int i = 0; i < model.getSize(); i++) { + Object o = model.getElementAt(i); + for (Object value : values) { + if (o.equals(value)) { + selectedIndices.add(i); + break; + } + } + } + int[] ints = new int[selectedIndices.size()]; + for (int i = 0; i < ints.length; i++) { + ints[i] = selectedIndices.get(i).intValue(); + } + setSelectedIndices(ints); + } else { + // No selection if values is null + setSelectedIndex(-1); + } + } + + public void setSelectedItem(Item item) { + super.setSelectedValue(item.getValue(), true); + } + + public void setSelectedItems(List<Item> itemsToSelect) { + if (itemsToSelect != null) { + List<Item> items = getItems(); + int[] indices = new int[itemsToSelect.size()]; + int i = 0; + for (Item item : itemsToSelect) { + indices[i] = items.indexOf(item); + i++; + } + super.setSelectedIndices(indices); + } + } + + public Item getSelectedItem() { + Object selected = super.getSelectedValue(); + return findItem(selected); + } + + public List<Item> getSelectedItems() { + Object[] selected = super.getSelectedValues(); + java.util.List<Item> itemsSelected = new ArrayList<Item>(); + for (Object s : selected) { + itemsSelected.add(findItem(s)); + } + return itemsSelected; + } + + public Item findItem(Object value) { + List<Item> items = getItems(); + if (items != null) { + for (Item i : items) { + if (i.getValue().equals(value)) { + return i; + } + } + } + return null; + } + + public void addItem(Item item) { + List<Item> items = getItems(); + if (items != null) { + items.add(item); + setItems(items); + } + } + + public void addAllItems(Collection<Item> itemsToAdd) { + List<Item> items = getItems(); + if (items != null) { + items.addAll(itemsToAdd); + setItems(items); + } + } + + public void removeItem(Item item) { + List<Item> items = getItems(); + if (items != null) { + items.remove(item); + setItems(items); + } + } + + public void removeAllItems(Collection<Item> itemsToRemove) { + List<Item> items = getItems(); + if (items != null) { + items.removeAll(itemsToRemove); + setItems(items); + } + } + + /** + * Fill a list model with some datas, and select after all the given object + * + * @param data data ot inject in combo + * @param selects the objects to select in list after reflling his model + */ + public void fillList(Collection<?> data, Collection<?> selects) { + if (selects == null) { + selects = java.util.Collections.EMPTY_LIST; + } + List<Item> items = new ArrayList<Item>(); + for (Object o : data) { + boolean selected = false; + for (Object select : selects) { + if (selected = o.equals(select)) { + break; + } + } + items.add(new Item(o.toString(), o.toString(), o, selected)); + } + setItems(items); + } + + /** + * Fill a list model with some datas, and select after all the given object + * + * @param data data ot inject in combo + * @param select object to select in list after reflling his model + */ + public void fillList(Collection<?> data, Object select) { + List<Item> items = new ArrayList<Item>(); + for (Object o : data) { + boolean selected = o.equals(select); + items.add(new Item(o.toString(), o.toString(), o, selected)); + } + setItems(items); + } + + /** + * Fill a list model with some datas, and select after all the given object + * + * @param data data ot inject in combo + * @param select object to select in list after reflling his model + * @param methodName method to invoke to display data's name + */ + public void fillList(Collection<?> data, Object select, String methodName) { + // prepare method to use + Method m = null; + + List<Item> items = new ArrayList<Item>(); + for (Object o : data) { + boolean selected = o.equals(select); + if (m == null) { + try { + m = o.getClass().getMethod(methodName); + m.setAccessible(true); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("could not find method " + methodName + " on " + o.getClass()); + } + } + try { + items.add(new Item(o.toString(), (String) m.invoke(o), o, selected)); + } catch (SecurityException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } catch (IllegalArgumentException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } + } + setItems(items); + } + + /** + * Fill a list model with some datas, and select after all the given object + * + * @param data data ot inject in combo + * @param selects the objects to select in list after reflling his model + * @param methodName method to invoke to display data's name + */ + public void fillList(Collection<?> data, Collection<?> selects, String methodName) { + // prepare method to use + Method m = null; + + List<Item> items = new ArrayList<Item>(); + for (Object o : data) { + boolean selected = selects.contains(o); + if (m == null) { + try { + m = o.getClass().getMethod(methodName); + m.setAccessible(true); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("could not find method " + methodName + " on " + o.getClass()); + } + } + try { + items.add(new Item(o.toString(), (String) m.invoke(o), o, selected)); + } catch (SecurityException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } catch (IllegalArgumentException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } + } + setItems(items); + } + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXTab.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXTab.java new file mode 100644 index 0000000..6ff64bf --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXTab.java @@ -0,0 +1,28 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +/** @author Tony Chemit - chemit@codelutin.com */ +public class JAXXTab extends Table { + + private static final long serialVersionUID = 1L; +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXToggleButton.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXToggleButton.java new file mode 100644 index 0000000..826755d --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXToggleButton.java @@ -0,0 +1,122 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.JToggleButton; + +public class JAXXToggleButton extends JToggleButton { + + private static final long serialVersionUID = 1L; + + protected String glueText; + + protected String normalText; + + protected String glueTooltipText; + + protected String normalTooltipText; + + protected int normalMnemonic; + + protected int glueMnemonic; + + protected boolean _init; + + public String getGlueText() { + return glueText; + } + + public String getNormalText() { + return normalText; + } + + public String getGlueTooltipText() { + return glueTooltipText; + } + + public String getNormalTooltipText() { + return normalTooltipText; + } + + public void setGlueText(String glueText) { + this.glueText = glueText; + + } + + public void setNormalText(String normalText) { + this.normalText = normalText; + + } + + public void setGlueTooltipText(String glueTooltipText) { + this.glueTooltipText = glueTooltipText; + } + + public int getNormalMnemonic() { + return normalMnemonic; + } + + public void setNormalMnemonic(int normalMnemonic) { + this.normalMnemonic = normalMnemonic; + } + + public int getGlueMnemonic() { + return glueMnemonic; + } + + public void setGlueMnemonic(int glueMnemonic) { + this.glueMnemonic = glueMnemonic; + } + + public void setNormalTooltipText(String normalTooltipText) { + this.normalTooltipText = normalTooltipText; + if (!_init) { + init(); + _init = true; + } + } + + @Override + public void setSelected(boolean b) { + super.setSelected(b); + if (isSelected()) { + setText(getGlueText()); + setToolTipText(getGlueTooltipText()); + setMnemonic(getGlueMnemonic()); + } else { + setText(getNormalText()); + setToolTipText(getNormalTooltipText()); + setMnemonic(getNormalMnemonic()); + } + revalidate(); + } + + public void init() { + setSelected(false); + } + + /* end raw body code */ + public JAXXToggleButton() { + super(); + _init = false; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXTree.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXTree.java new file mode 100644 index 0000000..9dc26e7 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXTree.java @@ -0,0 +1,278 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.JTree; +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreePath; +import java.awt.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.List; + +public class JAXXTree extends JTree { + + private static final long serialVersionUID = 1L; + + private static final String SYNTHETIC = "<synthetic root node>"; + + public class JAXXTreeModel implements TreeModel { + + private Item root; + + private List<TreeModelListener> listeners = new ArrayList<TreeModelListener>(); + + public JAXXTreeModel(List<Item> items) { + if (items.size() == 1) { + root = items.get(0); + } else { + root = new Item(null, null, SYNTHETIC, false); + for (Item item : items) { + root.addChild(item); + } + } + + PropertyChangeListener listener = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent e) { + if (e.getPropertyName().equals(Item.SELECTED_PROPERTY)) { + Item item = (Item) e.getSource(); + if (item.isSelected()) { + addSelectionPath(getTreePath(item)); + } else { + removeSelectionPath(getTreePath(item)); + } + } else { + Item item = (Item) e.getSource(); + boolean root = item.getParent() == null; + TreePath path = !root ? getTreePath(item.getParent()) : null; + fireTreeNodesChanged(new TreeModelEvent(JAXXTreeModel.this, path, + !root ? new int[]{item.getParent().getChildren().indexOf(item)} : null, + new Object[]{item.getValue()})); + } + } + }; + addPropertyChangeListener(root, listener); + } + + private void addPropertyChangeListener(Item item, PropertyChangeListener listener) { + item.addPropertyChangeListener(listener); + List<Item> children = item.getChildren(); + for (Item aChildren : children) { + addPropertyChangeListener(aChildren, listener); + } + } + + @Override + public void addTreeModelListener(TreeModelListener listener) { + listeners.add(listener); + } + + + /* This is an inefficient implementation, but hand-coded tree structures are unlikely to contain + enough nodes for that to really matter. This could be sped up with caching. */ + public Item findItem(Object value) { + return findItem(root, value); + } + + private Item findItem(Item node, Object value) { + if (node.getValue() == value) { + return node; + } else { + List<Item> children = node.getChildren(); + for (Item aChildren : children) { + Item result = findItem(aChildren, value); + if (result != null) { + return result; + } + } + return null; + } + } + + private TreePath getTreePath(Item node) { + List<Object> path = new ArrayList<Object>(); + while (node != null) { + path.add(0, node.getValue()); + node = node.getParent(); + } + return new TreePath(path.toArray()); + } + + @Override + public Object getChild(Object parent, int index) { + Item node = findItem(parent); + return node.getChildren().get(index).getValue(); + } + + @Override + public int getChildCount(Object parent) { + Item node = findItem(parent); + if (node == null) { + return 0; + } + return node.getChildren().size(); + } + + @Override + public int getIndexOfChild(Object parent, Object child) { + Item node = findItem(parent); + List<Item> children = node.getChildren(); + for (int i = 0, j = children.size(); i < j; i++) { + if (children.get(i).getValue() == child) { + return i; + } + } + return -1; + } + + @Override + public Object getRoot() { + return root.getValue(); + } + + public Item getRootItem() { + return root; + } + + @Override + public boolean isLeaf(Object node) { + Item item = findItem(node); + return item != null && item.getChildren().size() == 0; + } + + @Override + public void removeTreeModelListener(TreeModelListener listener) { + listeners.remove(listener); + } + + public void fireTreeNodesChanged(TreeModelEvent e) { + for (TreeModelListener listener : listeners) { + listener.treeNodesChanged(e); + } + } + + @Override + public void valueForPathChanged(TreePath path, Object newValue) { + } + } + + public JAXXTree(TreeModel model) { + super(model); + } + + public JAXXTree() { + setCellRenderer(new DefaultTreeCellRenderer() { + + private static final long serialVersionUID = 1L; + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { + TreeModel model = tree.getModel(); + if (model instanceof JAXXTreeModel) { + Item item = ((JAXXTreeModel) model).findItem(value); + if (item != null) { + String label = item.getLabel(); + if (label != null) { + value = label; + } + } + } + return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + } + }); + + addTreeSelectionListener(new TreeSelectionListener() { + + @Override + public void valueChanged(TreeSelectionEvent e) { + TreeModel model = getModel(); + if (model instanceof JAXXTreeModel) { + scan((JAXXTreeModel) model, ((JAXXTreeModel) model).root); + } + } + + private void scan(JAXXTreeModel model, Item item) { + TreePath path = model.getTreePath(item); + if (item.isSelected() != isPathSelected(path)) { + item.setSelected(!item.isSelected()); + } + List<Item> children = item.getChildren(); + for (Item aChildren : children) { + scan(model, aChildren); + } + } + }); + } + + public void setItem(Item items) { + List<Item> newItems = new ArrayList<Item>(); + newItems.add(items); + setItems(newItems); + } + + public void setItems(List<Item> items) { + // Create model + JAXXTreeModel model = new JAXXTreeModel(items); + if (model.getRoot() != null) { + setRootVisible(model.getRoot() != SYNTHETIC); + } + // Atach model + setModel(model); + + // Appli selected items + if (items != null) { + List<TreePath> treePathSelected = new ArrayList<TreePath>(); + for (Item i : items) { + if (i.isSelected()) { + treePathSelected.add(model.getTreePath(i)); + } + } + setSelectionPaths(convertToTreePathArray(treePathSelected.toArray())); + } + } + + public Object getSelectionValue() { + TreePath selectionPath = getSelectionPath(); + return selectionPath != null ? selectionPath.getLastPathComponent() : null; + } + + public Item getRootItem() { + if (getModel() instanceof JAXXTreeModel) { + return ((JAXXTreeModel) getModel()).getRootItem(); + } + return null; + } + + protected TreePath[] convertToTreePathArray(Object[] datas) { + TreePath[] params = new TreePath[datas.length]; + System.arraycopy(datas, 0, params, 0, datas.length); + return params; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JTables.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JTables.java new file mode 100644 index 0000000..21370e1 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/JTables.java @@ -0,0 +1,117 @@ +package org.nuiton.jaxx.runtime.swing; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JTable; + +/** + * Some usefull methods on {@link JTable}. + * + * Created on 12/4/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.18 + */ +public class JTables { + + /** Logger. */ + private static final Log log = LogFactory.getLog(JTables.class); + + public static void selectFirstCellOnFirstRowAndStopEditing(JTable table) { + + // select first cell + doSelectCell(table, 0, 0); + + if (table.isEditing()) { + + // but no edit it + table.getCellEditor().stopCellEditing(); + } + } + + public static void selectFirstCellOnLastRow(JTable table) { + + // select first cell + doSelectCell(table, table.getRowCount() - 1, 0); + } + + public static void selectFirstCellOnRow(JTable table, int row, boolean stopEdit) { + + // select first cell + doSelectCell(table, row, 0); + + if (stopEdit && table.isEditing()) { + + table.getCellEditor().stopCellEditing(); + } + } + + public static void doSelectCell(JTable table, + int rowIndex, + int columnIndex) { + + int rowCount = table.getRowCount(); + if (rowCount == 0) { + + // no row, can not selected any cell + if (log.isWarnEnabled()) { + log.warn("No row in table, can not select any cell"); + } + return; + } + int columnCount = table.getColumnCount(); + if (columnCount == 0) { + + // no column, can not selected any cell + if (log.isWarnEnabled()) { + log.warn("No column in table, can not select any cell"); + } + return; + } + if (columnIndex > columnCount) { + if (log.isWarnEnabled()) { + log.warn(String.format("ColumnIndex: %s is more than columnCount %s", columnIndex, columnCount)); + } + columnIndex = columnCount - 1; + } + if (columnIndex < 0) { + columnIndex = 0; + } + if (rowIndex >= rowCount) { + if (log.isWarnEnabled()) { + log.warn(String.format("RowIndex: %s is more than rowCount %s", rowIndex, rowCount)); + } + rowIndex = rowCount - 1; + } + if (rowIndex < 0) { + rowIndex = 0; + } + + table.setColumnSelectionInterval(columnIndex, columnIndex); + table.setRowSelectionInterval(rowIndex, rowIndex); + table.editCellAt(rowIndex, columnIndex); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/OneClicListSelectionModel.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/OneClicListSelectionModel.java new file mode 100644 index 0000000..a9c40b3 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/OneClicListSelectionModel.java @@ -0,0 +1,224 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JList; +import javax.swing.ListModel; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionListener; +import java.util.Arrays; + +/** + * @author Tony Chemit - chemit@codelutin.com + * @since 1.5 + */ +public class OneClicListSelectionModel implements ListSelectionModel { + + /** Logger */ + static private Log log = LogFactory.getLog(OneClicListSelectionModel.class); + + protected ListSelectionModel delegate; + + protected final ListModel model; + + private boolean[] _states; + + /** + * Convinient method to install a new {@link OneClicListSelectionModel} on + * a given {@link JList}. + * + * @param list the list onwhcih install the selection model + * @since 2.5.4 + */ + public static void installModel(JList list) { + OneClicListSelectionModel newModel = new OneClicListSelectionModel(list); + list.setSelectionModel(newModel); + } + + public OneClicListSelectionModel(JList list) { + this.delegate = list.getSelectionModel(); + this.model = list.getModel(); + delegate.clearSelection(); + } + + public OneClicListSelectionModel(ListSelectionModel delegate, ListModel model) { + this.delegate = delegate; + this.model = model; + delegate.clearSelection(); + } + + protected boolean[] getStates(int selectedIndex) { + int max = model.getSize(); + if (_states == null || _states.length != max) { + _states = new boolean[max]; + } else { + Arrays.fill(_states, false); + } + for (int i = 0; i < max; i++) { + _states[i] = i != selectedIndex && delegate.isSelectedIndex(i); + } + return _states; + } + + @Override + public void setSelectionInterval(int index0, int index1) { + if (index0 != index1) { + // not a single selection (come from a click) + // use default behaviour + delegate.setSelectionInterval(index0, index1); + return; + } + delegate.setValueIsAdjusting(true); + + try { + int max = model.getSize(); + + if (log.isDebugEnabled()) { + log.debug("single [index:" + index0 + "] [selected:" + isSelectedIndex(index0) + "] [size:" + max + "] [anchor:" + delegate.getAnchorSelectionIndex() + "] [lead:" + delegate.getLeadSelectionIndex() + "]"); + } + + if (!isSelectedIndex(index0)) { + // select it + delegate.addSelectionInterval(index0, index1); + return; + } + if (max == index0) { + // last selected index, so can directly remove it + delegate.removeIndexInterval(index0, index0); + return; + } + + // must recompute the selection removing only the index0 item + boolean[] state = getStates(index0); + + if (log.isDebugEnabled()) { + log.debug("state : " + Arrays.toString(state)); + } + delegate.clearSelection(); + for (int i = 0; i < max; i++) { + if (state[i]) { + delegate.addSelectionInterval(i, i); + } + } + } finally { + delegate.setValueIsAdjusting(false); + } + } + + @Override + public void addSelectionInterval(int index0, int index1) { + delegate.addSelectionInterval(index0, index1); + } + + @Override + public void removeSelectionInterval(int index0, int index1) { + delegate.removeSelectionInterval(index0, index1); + } + + @Override + public int getMinSelectionIndex() { + return delegate.getMinSelectionIndex(); + } + + @Override + public int getMaxSelectionIndex() { + return delegate.getMaxSelectionIndex(); + } + + @Override + public boolean isSelectedIndex(int index) { + return delegate.isSelectedIndex(index); + } + + @Override + public int getAnchorSelectionIndex() { + return delegate.getAnchorSelectionIndex(); + } + + @Override + public void setAnchorSelectionIndex(int index) { + delegate.setAnchorSelectionIndex(index); + } + + @Override + public int getLeadSelectionIndex() { + return delegate.getLeadSelectionIndex(); + } + + @Override + public void setLeadSelectionIndex(int index) { + delegate.setLeadSelectionIndex(index); + } + + @Override + public void clearSelection() { + delegate.clearSelection(); + } + + @Override + public boolean isSelectionEmpty() { + return delegate.isSelectionEmpty(); + } + + @Override + public void insertIndexInterval(int index, int length, boolean before) { + delegate.insertIndexInterval(index, length, before); + } + + @Override + public void removeIndexInterval(int index0, int index1) { + delegate.removeIndexInterval(index0, index1); + } + + @Override + public void setValueIsAdjusting(boolean valueIsAdjusting) { + delegate.setValueIsAdjusting(valueIsAdjusting); + } + + @Override + public boolean getValueIsAdjusting() { + return delegate.getValueIsAdjusting(); + } + + @Override + public void setSelectionMode(int selectionMode) { + delegate.setSelectionMode(selectionMode); + } + + @Override + public int getSelectionMode() { + return delegate.getSelectionMode(); + } + + @Override + public void addListSelectionListener(ListSelectionListener x) { + delegate.addListSelectionListener(x); + } + + @Override + public void removeListSelectionListener(ListSelectionListener x) { + delegate.removeListSelectionListener(x); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/Spacer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/Spacer.java new file mode 100644 index 0000000..7352cd7 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/Spacer.java @@ -0,0 +1,29 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.JComponent; + +public class Spacer extends JComponent { + + private static final long serialVersionUID = 1L; +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/TabInfo.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/TabInfo.java new file mode 100644 index 0000000..24893c1 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/TabInfo.java @@ -0,0 +1,231 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.event.SwingPropertyChangeSupport; +import java.awt.Color; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +public class TabInfo { + + public static String BACKGROUND_PROPERTY = "background"; + + public static String TAB_COMPONENT_PROPERTY = "tabComponent"; + + public static String TAB_COMPONENT_STR_PROPERTY = "tabComponentStr"; + + public static String DISABLED_ICON_PROPERTY = "disabledIcon"; + + public static String DISPLAYED_MNEMONIC_INDEX_PROPERTY = "displayedMnemonicIndex"; + + public static String ENABLED_PROPERTY = "enabled"; + + public static String FOREGROUND_PROPERTY = "foreground"; + + public static String ICON_PROPERTY = "icon"; + + public static String MNEMONIC_PROPERTY = "mnemonic"; + + public static String TITLE_PROPERTY = "title"; + + public static String TOOL_TIP_TEXT_PROPERTY = "toolTipText"; + + private String id; + + private Color background; + + private Icon disabledIcon; + + private int displayedMnemonicIndex = -1; + + private boolean enabled = true; + + private Color foreground; + + private Icon icon; + + private int mnemonic = -1; + + private String title; + + private String toolTipText; + + private JComponent tabComponent; + + private String tabComponentStr; + + private PropertyChangeSupport propertyChangeSupport; + + public TabInfo() { + } + + public TabInfo(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public Color getBackground() { + return background; + } + + public void setBackground(Color background) { + Color oldValue = this.background; + this.background = background; + firePropertyChange(BACKGROUND_PROPERTY, oldValue, background); + } + + public Icon getDisabledIcon() { + return disabledIcon; + } + + public void setDisabledIcon(Icon disabledIcon) { + Icon oldValue = this.disabledIcon; + this.disabledIcon = disabledIcon; + firePropertyChange(DISABLED_ICON_PROPERTY, oldValue, disabledIcon); + } + + public int getDisplayedMnemonicIndex() { + return displayedMnemonicIndex; + } + + public void setDisplayedMnemonicIndex(int displayedMnemonicIndex) { + int oldValue = this.displayedMnemonicIndex; + this.displayedMnemonicIndex = displayedMnemonicIndex; + firePropertyChange(DISPLAYED_MNEMONIC_INDEX_PROPERTY, oldValue, displayedMnemonicIndex); + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + boolean oldValue = this.enabled; + this.enabled = enabled; + firePropertyChange(ENABLED_PROPERTY, oldValue, enabled); + } + + public Color getForeground() { + return foreground; + } + + public void setForeground(Color foreground) { + Color oldValue = this.foreground; + this.foreground = foreground; + firePropertyChange(FOREGROUND_PROPERTY, oldValue, foreground); + } + + public Icon getIcon() { + return icon; + } + + public void setIcon(Icon icon) { + Icon oldValue = this.icon; + this.icon = icon; + firePropertyChange(ICON_PROPERTY, oldValue, icon); + } + + public int getMnemonic() { + return mnemonic; + } + + public void setMnemonic(int mnemonic) { + int oldValue = this.mnemonic; + this.mnemonic = mnemonic; + firePropertyChange(MNEMONIC_PROPERTY, oldValue, mnemonic); + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + String oldValue = this.title; + this.title = title; + firePropertyChange(TITLE_PROPERTY, oldValue, title); + } + + public String getToolTipText() { + return toolTipText; + } + + public void setToolTipText(String toolTipText) { + String oldValue = this.toolTipText; + this.toolTipText = toolTipText; + firePropertyChange(TOOL_TIP_TEXT_PROPERTY, oldValue, toolTipText); + } + + public JComponent getTabComponent() { + return tabComponent; + } + + public void setTabComponent(JComponent tabComponent) { + JComponent oldValue = this.tabComponent; + this.tabComponent = tabComponent; + firePropertyChange(TAB_COMPONENT_PROPERTY, oldValue, tabComponent); + } + + + public String getTabComponentStr() { + return tabComponentStr; + } + + public void setTabComponentStr(String tabComponentStr) { + String oldValue = this.tabComponentStr; + this.tabComponentStr = tabComponentStr; + firePropertyChange(TAB_COMPONENT_STR_PROPERTY, oldValue, tabComponent); + } + + private PropertyChangeSupport getPropertyChangeSupport() { + if (propertyChangeSupport == null) { + propertyChangeSupport = new SwingPropertyChangeSupport(this); + } + return propertyChangeSupport; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + getPropertyChangeSupport().addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String property, PropertyChangeListener listener) { + getPropertyChangeSupport().addPropertyChangeListener(property, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + getPropertyChangeSupport().removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String property, PropertyChangeListener listener) { + getPropertyChangeSupport().removePropertyChangeListener(property, listener); + } + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + if (propertyChangeSupport != null) { + getPropertyChangeSupport().firePropertyChange(propertyName, oldValue, newValue); + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/TabInfoPropertyChangeListener.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/TabInfoPropertyChangeListener.java new file mode 100644 index 0000000..4289ca7 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/TabInfoPropertyChangeListener.java @@ -0,0 +1,67 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.Icon; +import javax.swing.JTabbedPane; +import java.awt.Color; +import java.awt.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +public class TabInfoPropertyChangeListener implements PropertyChangeListener { + + private JTabbedPane tabs; + + private int tabIndex; + + public TabInfoPropertyChangeListener(JTabbedPane tabs, int tabIndex) { + this.tabs = tabs; + this.tabIndex = tabIndex; + } + + @Override + public void propertyChange(PropertyChangeEvent e) { + String name = e.getPropertyName(); + if (name.equals(TabInfo.TITLE_PROPERTY)) { + tabs.setTitleAt(tabIndex, (String) e.getNewValue()); + } else if (name.equals(TabInfo.TOOL_TIP_TEXT_PROPERTY)) { + tabs.setToolTipTextAt(tabIndex, (String) e.getNewValue()); + } else if (name.equals(TabInfo.FOREGROUND_PROPERTY)) { + tabs.setForegroundAt(tabIndex, (Color) e.getNewValue()); + } else if (name.equals(TabInfo.BACKGROUND_PROPERTY)) { + tabs.setBackgroundAt(tabIndex, (Color) e.getNewValue()); + } else if (name.equals(TabInfo.MNEMONIC_PROPERTY)) { + tabs.setMnemonicAt(tabIndex, (Integer) e.getNewValue()); + } else if (name.equals(TabInfo.DISPLAYED_MNEMONIC_INDEX_PROPERTY)) { + tabs.setDisplayedMnemonicIndexAt(tabIndex, (Integer) e.getNewValue()); + } else if (name.equals(TabInfo.ICON_PROPERTY)) { + tabs.setIconAt(tabIndex, (Icon) e.getNewValue()); + } else if (name.equals(TabInfo.DISABLED_ICON_PROPERTY)) { + tabs.setDisabledIconAt(tabIndex, (Icon) e.getNewValue()); + } else if (name.equals(TabInfo.TAB_COMPONENT_PROPERTY)) { + tabs.setTabComponentAt(tabIndex, (Component) e.getNewValue()); + } else if (name.equals(TabInfo.ENABLED_PROPERTY)) { + tabs.setEnabledAt(tabIndex, (Boolean) e.getNewValue()); + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/Table.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/Table.java new file mode 100644 index 0000000..df4a3b7 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/Table.java @@ -0,0 +1,79 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.JPanel; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.LayoutManager; + +/** + * Panel which uses a {@link GridBagLayout} by default. + * + * @author Ethan Nicholas + */ +public class Table extends JPanel { + + private static final long serialVersionUID = 1L; + + public static final Insets DEFAULT_INSETS = new Insets(3, 3, 3, 3); + + private GridBagConstraints tableConstraints = new GridBagConstraints(); + + private GridBagConstraints rowConstraints; + + private GridBagConstraints cellConstraints; + + public Table() { + super.setLayout(new GridBagLayout()); + + tableConstraints.insets = DEFAULT_INSETS; + } + + @Override + public void setLayout(LayoutManager layout) { + // do nothing + } + + public GridBagConstraints getTableConstraints() { + return tableConstraints; + } + + public GridBagConstraints getRowConstraints() { + return rowConstraints; + } + + public GridBagConstraints getCellConstraints() { + return cellConstraints; + } + + public void newRow() { + tableConstraints.gridy++; + rowConstraints = (GridBagConstraints) tableConstraints.clone(); + } + + public void newCell() { + rowConstraints.gridx++; + cellConstraints = (GridBagConstraints) rowConstraints.clone(); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/VBox.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/VBox.java new file mode 100644 index 0000000..ef42b18 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/VBox.java @@ -0,0 +1,116 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.JPanel; +import java.awt.Insets; + +/** + * Panel which uses a {@link VBoxLayout} by default. + * + * @author Ethan Nicholas + */ +public class VBox extends JPanel { + + private static final long serialVersionUID = 1L; + + public static final String SPACING_PROPERTY = "spacing"; + + public static final String MARGIN_PROPERTY = "margin"; + + public static final String HORIZONTAL_ALIGNMENT_PROPERTY = "horizontalAlignment"; + + public static final String VERTICAL_ALIGNMENT_PROPERTY = "verticalAlignment"; + + private Insets margin; + + public VBox() { + super(new VBoxLayout()); + } + + /** + * Returns the spacing between components, in pixels. Spacing is applied between components only, + * not to the top or bottom of the container. + * + * @return spacing between components + */ + public int getSpacing() { + return ((VBoxLayout) getLayout()).getSpacing(); + } + + /** + * Sets the spacing between components. Spacing is applied between components only, + * not to the top or bottom of the container. + * + * @param spacing new spacing value + */ + public void setSpacing(int spacing) { + int oldValue = getSpacing(); + ((VBoxLayout) getLayout()).setSpacing(spacing); + firePropertyChange(SPACING_PROPERTY, oldValue, spacing); + revalidate(); + } + + public int getHorizontalAlignment() { + return ((VBoxLayout) getLayout()).getHorizontalAlignment(); + } + + public void setHorizontalAlignment(int horizontalAlignment) { + int oldValue = getHorizontalAlignment(); + ((VBoxLayout) getLayout()).setHorizontalAlignment(horizontalAlignment); + firePropertyChange(HORIZONTAL_ALIGNMENT_PROPERTY, oldValue, horizontalAlignment); + revalidate(); + } + + public int getVerticalAlignment() { + return ((VBoxLayout) getLayout()).getVerticalAlignment(); + } + + public void setVerticalAlignment(int verticalAlignment) { + int oldValue = getVerticalAlignment(); + ((VBoxLayout) getLayout()).setVerticalAlignment(verticalAlignment); + firePropertyChange(VERTICAL_ALIGNMENT_PROPERTY, oldValue, verticalAlignment); + revalidate(); + } + + public Insets getMargin() { + return margin; + } + + public void setMargin(Insets margin) { + Insets oldValue = this.margin; + this.margin = (Insets) margin.clone(); + firePropertyChange(MARGIN_PROPERTY, oldValue, margin); + } + + @Override + public Insets getInsets() { + Insets result = super.getInsets(); + if (margin != null) { + result.top += margin.top; + result.left += margin.left; + result.right += margin.right; + result.bottom += margin.bottom; + } + return result; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/VBoxBeanInfo.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/VBoxBeanInfo.java new file mode 100644 index 0000000..825b4a4 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/VBoxBeanInfo.java @@ -0,0 +1,73 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.beans.SimpleBeanInfo; + +public class VBoxBeanInfo extends SimpleBeanInfo { + + @Override + public BeanInfo[] getAdditionalBeanInfo() { + try { + return new BeanInfo[]{Introspector.getBeanInfo(JPanel.class)}; + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + } + + @Override + public PropertyDescriptor[] getPropertyDescriptors() { + try { + PropertyDescriptor spacing = new PropertyDescriptor("spacing", VBox.class); + spacing.setBound(true); + + PropertyDescriptor margin = new PropertyDescriptor("margin", VBox.class); + margin.setBound(true); + + PropertyDescriptor horizontalAlignment = new PropertyDescriptor("horizontalAlignment", VBox.class); + horizontalAlignment.setBound(true); + horizontalAlignment.setValue("enumerationValues", new Object[]{ + "left", SwingConstants.LEFT, "SwingConstants.LEFT", + "center", SwingConstants.CENTER, "SwingConstants.CENTER", + "right", SwingConstants.RIGHT, "SwingConstants.RIGHT" + }); + + PropertyDescriptor verticalAlignment = new PropertyDescriptor("verticalAlignment", VBox.class); + verticalAlignment.setBound(true); + verticalAlignment.setValue("enumerationValues", new Object[]{ + "top", SwingConstants.TOP, "SwingConstants.TOP", + "middle", SwingConstants.CENTER, "SwingConstants.CENTER", + "bottom", SwingConstants.BOTTOM, "SwingConstants.BOTTOM" + }); + + return new PropertyDescriptor[]{spacing, margin, horizontalAlignment, verticalAlignment}; + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/VBoxLayout.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/VBoxLayout.java new file mode 100644 index 0000000..f0ca7e4 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/VBoxLayout.java @@ -0,0 +1,146 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.SwingConstants; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.LayoutManager; + +/** + * Vertical box layout. The layout rules followed by this class are quite different than the core BoxLayout class, + * and in general represent a more useful algorithm. + * + * @author Ethan Nicholas + */ +public class VBoxLayout implements LayoutManager { + + private int spacing = 6; + + private int horizontalAlignment = SwingConstants.LEFT; + + private int verticalAlignment = SwingConstants.TOP; + + public int getSpacing() { + return spacing; + } + + public void setSpacing(int spacing) { + this.spacing = spacing; + } + + public int getHorizontalAlignment() { + return horizontalAlignment; + } + + public void setHorizontalAlignment(int horizontalAlignment) { + this.horizontalAlignment = horizontalAlignment; + } + + public int getVerticalAlignment() { + return verticalAlignment; + } + + public void setVerticalAlignment(int verticalAlignment) { + this.verticalAlignment = verticalAlignment; + } + + @Override + public void addLayoutComponent(String name, Component comp) { + } + + @Override + public void layoutContainer(Container parent) { + Insets insets = parent.getInsets(); + int parentWidth = parent.getSize().width - insets.left - insets.right; + int count = parent.getComponentCount(); + Dimension preferredSize = parent.getPreferredSize(); + int y; + switch (verticalAlignment) { + case SwingConstants.TOP: + y = insets.top; + break; + case SwingConstants.CENTER: + y = insets.top + (parent.getHeight() - preferredSize.height) / 2; + break; + case SwingConstants.BOTTOM: + y = insets.top + (parent.getHeight() - preferredSize.height); + break; + default: + throw new IllegalArgumentException("invalid vertical alignment: " + verticalAlignment); + } + + for (int i = 0; i < count; i++) { + Component component = parent.getComponent(i); + Dimension childPreferredSize = component.getPreferredSize(); + int width = Math.min(childPreferredSize.width, parentWidth); + int x; + switch (horizontalAlignment) { + case SwingConstants.LEFT: + x = insets.left; + break; + case SwingConstants.CENTER: + x = insets.left + (parentWidth - childPreferredSize.width) / 2; + break; + case SwingConstants.RIGHT: + x = insets.left + (parentWidth - childPreferredSize.width); + break; + default: + throw new IllegalArgumentException("invalid horizontal alignment: " + horizontalAlignment); + } + component.setBounds(x, y, width, childPreferredSize.height); + y += childPreferredSize.height + spacing; + } + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + int width = 0; + int height = (parent.getComponentCount() - 1) * spacing; + for (int i = parent.getComponentCount() - 1; i >= 0; i--) { + Dimension minimumSize = parent.getComponent(i).getMinimumSize(); + width = Math.max(width, minimumSize.width); + height += minimumSize.height; + } + Insets insets = parent.getInsets(); + return new Dimension(width + insets.left + insets.right, height + insets.top + insets.bottom); + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + int width = 0; + int height = (parent.getComponentCount() - 1) * spacing; + for (int i = parent.getComponentCount() - 1; i >= 0; i--) { + Dimension preferredSize = parent.getComponent(i).getPreferredSize(); + width = Math.max(width, preferredSize.width); + height += preferredSize.height; + } + Insets insets = parent.getInsets(); + return new Dimension(width + insets.left + insets.right, height + insets.top + insets.bottom); + } + + @Override + public void removeLayoutComponent(Component comp) { + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/application/ActionExecutor.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/application/ActionExecutor.java new file mode 100644 index 0000000..f0951e4 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/application/ActionExecutor.java @@ -0,0 +1,276 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.application; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.ReflectUtil; + +import javax.swing.SwingWorker; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +/** + * Executor of {@link ActionWorker}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public abstract class ActionExecutor { + + /** Logger */ + private static final Log log = + LogFactory.getLog(ActionExecutor.class); + + /** current tasks */ + protected final Set<ActionWorker<?, ?>> tasks = + new HashSet<ActionWorker<?, ?>>(); + + /** the listener of running action */ + protected final PropertyChangeListener workerListener; + + /** + * Hook when a action is about to start. + * + * @param source the action worker containing the action to perform + */ + public abstract void onActionStart(ActionWorker<?, ?> source); + + /** + * Hook when a action has failed. + * + * @param source the action worker containing the action to perform + */ + public abstract void onActionFail(ActionWorker<?, ?> source); + + /** + * Hook when a action has been canceled. + * + * @param source the action worker containing the action to perform + */ + public abstract void onActionCancel(ActionWorker<?, ?> source); + + /** + * Hook when a action has end with no failure or cancel. + * + * @param source the action worker containing the action to perform + */ + public abstract void onActionEnd(ActionWorker<?, ?> source); + + /** + * Hook atfer action is consumed. + * + * @param source the action worker containing the action to perform + */ + public abstract void onAfterAction(ActionWorker<?, ?> source); + + public ActionExecutor() { + workerListener = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (log.isDebugEnabled()) { + log.debug("action " + evt.getSource() + " property " + + evt.getPropertyName() + " changed <" + + evt.getOldValue() + " - " + evt.getNewValue() + + '>'); + } + + if ("state".equals(evt.getPropertyName())) { + ActionWorker<?, ?> source = (ActionWorker<?, ?>) evt.getSource(); + SwingWorker.StateValue state = + (SwingWorker.StateValue) evt.getNewValue(); + + if (state == SwingWorker.StateValue.STARTED) { + // starting new action + + onActionStart(source); + return; + } + + if (state == SwingWorker.StateValue.DONE) { + // on rend la main au thread pour qu'il attende une + // prochaine operation + + ActionWorker.ActionStatus status = source.getStatus(); + if (log.isDebugEnabled()) { + log.debug("Action [" + source.getActionLabel() + + "] status = " + status); + } + try { + switch (status) { + + case OK: + onActionEnd(source); + break; + case CANCEL: + onActionCancel(source); + break; + case FAIL: + onActionFail(source); + break; + } + } finally { + tasks.remove(source); + onAfterAction(source); + } + } + } + } + }; + } + + /** + * Add an new action to perform. + * + * @param actionLabel the name of the action to perform + * @param action the action to perform + * @return the worker that will launch the action + */ + public ActionWorker<?, ?> addAction(String actionLabel, Runnable action) { + + ActionWorker<?, ?> worker; + if (action instanceof ActionWorker) { + + worker = (ActionWorker<?, ?>) action; + } else { + + worker = new ActionWorker(actionLabel, action); + } + worker.addPropertyChangeListener(workerListener); + tasks.add(worker); + worker.execute(); + return worker; + } + + /** + * Ask the thread to stop. + * + * It will finish all incoming files (but will not accept more tasks). + * + * <b>Note:</b> The method does not return until all tasks are not + * consumed. + * + * @throws InterruptedException if something wrong while waiting end of + * executor + */ + public void terminatesAndWaits() throws InterruptedException { + + if (log.isDebugEnabled()) { + log.debug("Executor " + this + " is terminating..."); + } + + // ask executor to terminate + for (ActionWorker<?, ?> task : tasks) { + task.cancel(true); + } + + if (log.isDebugEnabled()) { + log.debug("Executor " + this + " is terminated at " + new Date()); + } + } + + public int getNbActions() { + return getTasks().size(); + } + + public Set<ActionWorker<?, ?>> getTasks() { + return tasks; + } + + /** + * Creates a runnable instance (via a Proxy) to a method given by his name + * ({@code methodName}) to invoke on {@code methodcontainer} with given + * {@code arguments}. + * + * This is a great feature to create runnable code with a real context. + * + * @param methodContainer the container of the method to invoke + * @param methodName the name of the method to invoke + * @param arguments parameters to pass to method to invke. + * @return the proxy instance + */ + public Runnable createRunnable(final Object methodContainer, + String methodName, + final Object... arguments) { + + // find method + + Class<?> klass = methodContainer.getClass(); + final Method targetMethod = ReflectUtil.getDeclaredMethod(klass, + methodName, + true, + arguments + ); + targetMethod.setAccessible(true); + Runnable result; + + // create runnable proxy + + result = (Runnable) Proxy.newProxyInstance( + getClass().getClassLoader(), + new Class<?>[]{Runnable.class}, + new InvocationHandler() { + + @Override + public Object invoke(Object proxy, + Method method, + Object[] args) { + String methodName = method.getName(); + + if ("run".equals(methodName)) { + try { + if (log.isDebugEnabled()) { + log.debug("will invoke run method"); + } + return targetMethod.invoke(methodContainer, arguments); + } catch (IllegalAccessException e) { + throw new RuntimeException( + "could not invoke on container " + + methodContainer, e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + if (methodName.equals("toString")) { + return toString(); + } + if (methodName.equals("equals")) { + return equals(args[0]); + } + if (methodName.equals("hashCode")) { + return hashCode(); + } + return null; + } + } + ); + return result; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/application/ActionWorker.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/application/ActionWorker.java new file mode 100644 index 0000000..196c686 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/application/ActionWorker.java @@ -0,0 +1,175 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.application; + +import com.google.common.base.Preconditions; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.StringUtil; + +import javax.swing.SwingWorker; +import java.util.concurrent.Callable; + +/** + * Action worker to execute a incoming action. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public class ActionWorker<R, P> extends SwingWorker<R, P> { + + /** Logger */ + private static final Log log = LogFactory.getLog(ActionWorker.class); + + protected final String actionLabel; + + protected Callable<R> target; + + protected ActionStatus status; + + protected Exception error; + + protected long startTime; + + protected long endTime; + + public ActionWorker(String actionLabel) { + this.actionLabel = actionLabel; + } + + public ActionWorker(String actionLabel, Runnable target) { + this.target = new RunnableBridge<R>(target); + this.actionLabel = actionLabel; + } + + public Callable<R> getTarget() { + return target; + } + + public void setTarget(Runnable target) { + setTarget(new RunnableBridge<R>(target)); + } + + /** + * Set the target to execute. + * + * @param target the target to execute + * @since 2.5.1 + */ + public void setTarget(Callable<R> target) { + this.target = target; + } + + @Override + protected R doInBackground() throws Exception { + Preconditions.checkNotNull(target != null, "Targe field can not be null here."); + startTime = System.nanoTime(); + if (log.isDebugEnabled()) { + log.debug("Action [" + getActionLabel() + "] is starting..."); + } + R result = null; + try { + + result = getTarget().call(); + } catch (Exception e) { + error = e; + } finally { + if (log.isDebugEnabled()) { + log.debug("Action [" + getActionLabel() + "] is ending..."); + } + } + return result; + } + + public boolean isFailed() { + return (isDone() || isCancelled()) && error != null; + } + + public Exception getError() { + return error; + } + + public ActionStatus getStatus() { + return status; + } + + public String getActionLabel() { + return actionLabel; + } + + @Override + protected void done() { + super.done(); + endTime = System.nanoTime(); + if (error != null) { + status = ActionStatus.FAIL; + } else if (isCancelled()) { + status = ActionStatus.CANCEL; + } else { + status = ActionStatus.OK; + } + if (log.isDebugEnabled()) { + log.debug("Action [" + getActionLabel() + "] ends with status : " + status + " in " + getTime()); + } + } + + public String getTime() { + return StringUtil.convertTime(endTime - startTime); + } + + public long getStartTime() { + return startTime; + } + + public long getEndTime() { + return endTime; + } + + /** State of a running action */ + public enum ActionStatus { + OK, + CANCEL, + FAIL + } + + /** + * Transform a {@link Runnable} into a {@link Callable}. + * + * @param <R> type of return (used to maintain generic checks in this class). + * @since 2.5.1 + */ + private static class RunnableBridge<R> implements Callable<R> { + + private final Runnable target; + + public RunnableBridge(Runnable target) { + this.target = target; + } + + @Override + public R call() throws Exception { + target.run(); + return null; + } + } + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/application/ApplicationRunner.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/application/ApplicationRunner.java new file mode 100644 index 0000000..eccf3e4 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/application/ApplicationRunner.java @@ -0,0 +1,247 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.application; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Simple application runner which authorize to reload an application. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public abstract class ApplicationRunner { + + /** Logger */ + private static Log log = LogFactory.getLog(ApplicationRunner.class); + + private static final Object lock = new Object(); + + private static ApplicationRunner runner; + + public static ApplicationRunner getRunner() { + if (runner == null) { + throw new IllegalStateException("No runner initialized"); + } + return runner; + } + + public static void lock() throws InterruptedException { + synchronized (lock) { + // on arrete le thread principal + // pour rendre la main a la methode main + lock.wait(); + } + } + + public static void unlock() { + synchronized (lock) { + // on arrete le thread principal + // pour rendre la main a la methode main + lock.notifyAll(); + } + } + + /** arguments given to runner at launch time */ + protected final String[] args; + + /** flag to reload the runner when closing it */ + protected boolean reload; + + /** the runner to start application */ + protected final Runnable runnable; + + protected long startingTime; + + protected Exception error; + + /** + * To execute some code only once. + * + * This code will not be re-execute when reloading the runner. + */ + protected abstract void initOnce(); + + /** + * Hook to init runner. + * + * @throws Exception if any problem + */ + protected abstract void onInit() throws Exception; + + /** + * Hook to start runner. + * + * @throws Exception if any problem + */ + protected abstract void onStart() throws Exception; + + /** + * Hook to close runner. + * + * @param reload if reload was asked + * @throws Exception if any problme + */ + protected abstract void onClose(boolean reload) throws Exception; + + /** + * Hook to shutdown launcher + * + * @throws Exception if any problem + */ + protected abstract void onShutdown() throws Exception; + + /** + * Hook to shutdown launcher when an exception occurs on clsoing. + * + * @param ex the error catched while closing launcher + */ + protected abstract void onShutdown(Exception ex); + + /** + * Hook when an error occurs in runner. + * + * @param e the error catched + */ + protected abstract void onError(Exception e); + + protected ApplicationRunner(String... args) { + runner = this; + this.args = args; + + initOnce(); + + runnable = new Runnable() { + @Override + public void run() { + startingTime = System.nanoTime(); + try { + + onInit(); + + onStart(); + + } catch (Exception e) { + error = e; + onError(e); + unlock(); + } + } + }; + + Thread shutdownHook = new Thread(new Runnable() { + + @Override + public void run() { + try { + + //onClose(false); + onShutdown(); + + } catch (Exception e) { + error = e; + onShutdown(e); + } + } + }, "ShutDown " + getClass().getSimpleName()); + + Runtime.getRuntime().addShutdownHook(shutdownHook); + } + + public boolean isReload() { + return reload; + } + + public void setReload(boolean reload) { + this.reload = reload; + } + + protected Thread mainThread; + + public final void launch() { + + // au demarrage le reload est toujours desactive + reload = false; + + // preparation du thread de l'application principale + // que l'on démarre + mainThread = new Thread(runnable, getClass().getSimpleName()); + mainThread.start(); + + try { + + // on attend que l'application se termine ou demande un redémarrage + lock(); + + // on va libérer le runner + log.info("Application [" + mainThread + "] is closing..."); + + } catch (InterruptedException e) { + if (log.isErrorEnabled()) { + log.error(mainThread + " was interrupted for reason " + e.getMessage(), e); + } + } finally { + + close(); + + } + } + + public final void close() { + boolean doReload = isReload(); + + try { + + // fermeture du runner + onClose(doReload); + + if (doReload) { + + // redemarrage du runner + + if (log.isInfoEnabled()) { + log.info("Will reload application"); + } + + System.runFinalization(); + + launch(); + } + + } catch (Exception e) { + onError(e); + } finally { + if (!doReload) { + if (log.isDebugEnabled()) { + log.debug("Will shutdown application ..."); + } + + unlock(); + + // force to shutdown + Runtime.getRuntime().exit(0); + } + } + } + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/BooleanCellEditor.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/BooleanCellEditor.java new file mode 100644 index 0000000..08eb6a2 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/BooleanCellEditor.java @@ -0,0 +1,80 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.editor; + +import java.awt.Component; +import javax.swing.AbstractCellEditor; +import javax.swing.Icon; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import org.jdesktop.swingx.JXTable; + +/** + * @author Tony Chemit - chemit@codelutin.com + * @since 1.5 + */ +public class BooleanCellEditor extends AbstractCellEditor implements TableCellRenderer, TableCellEditor { + + private static final long serialVersionUID = 1L; + + protected TableCellRenderer rendererDelegate; + protected TableCellEditor editorDelegate; + + protected Icon icon; + + public BooleanCellEditor(TableCellRenderer delegate) { + this(delegate, null); + } + + public BooleanCellEditor(TableCellRenderer delegate, Icon icon) { + this.rendererDelegate = delegate; + this.editorDelegate = new JXTable.BooleanEditor(); + this.icon = icon; + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + JComponent rendered = (JComponent) rendererDelegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + if (rendered instanceof JCheckBox) { + JCheckBox checkBox = (JCheckBox)rendered; + checkBox.setHorizontalAlignment(JLabel.CENTER); + checkBox.setVerticalTextPosition(JLabel.TOP); + checkBox.setBorderPainted(true); + checkBox.setIcon(icon); + } + return rendered; + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + return editorDelegate.getTableCellEditorComponent(table, value, isSelected, row, column); + } + + @Override + public Object getCellEditorValue() { + return editorDelegate.getCellEditorValue(); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/ClassCellEditor.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/ClassCellEditor.java new file mode 100644 index 0000000..7ce09a4 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/ClassCellEditor.java @@ -0,0 +1,129 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.editor; + +import org.apache.commons.beanutils.Converter; +import org.nuiton.converter.ConverterUtil; + +import javax.swing.DefaultCellEditor; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.event.CellEditorListener; +import javax.swing.table.TableCellEditor; +import java.awt.Component; +import java.util.EventObject; + +/** + * A class cell editor (fork from comandline project). + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class ClassCellEditor implements TableCellEditor { + + protected TableCellEditor delegate; + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + + String valStr; + + if (value instanceof Class<?>) { + valStr = ((Class<?>) value).getName(); + } else { + valStr = (value + "").trim(); + if (valStr.equals("null")) { + valStr = ""; + } else if (valStr.startsWith("class ")) { + valStr = valStr.substring(6); + } + } + Component comp; + comp = getDelegate().getTableCellEditorComponent(table, valStr, isSelected, row, column); + return comp; + } + + @Override + public Object getCellEditorValue() { + Object o = !hasDelegate() ? null : delegate.getCellEditorValue(); + if (o == null) { + return null; + } + Converter converter = ConverterUtil.getConverter(Class.class); + + try { + if (converter != null) { + return converter.convert(Class.class, o); + } + o = Class.forName(o + ""); + } catch (Exception e) { + o = null; + } + return o; + } + + @Override + public boolean isCellEditable(EventObject anEvent) { + return !hasDelegate() || delegate.isCellEditable(anEvent); + } + + @Override + public boolean shouldSelectCell(EventObject anEvent) { + return hasDelegate() && delegate.shouldSelectCell(anEvent); + } + + @Override + public boolean stopCellEditing() { + return !hasDelegate() || delegate.stopCellEditing(); + } + + @Override + public void cancelCellEditing() { + if (hasDelegate()) { + delegate.cancelCellEditing(); + } + } + + @Override + public void addCellEditorListener(CellEditorListener l) { + if (hasDelegate()) { + delegate.addCellEditorListener(l); + } + } + + @Override + public void removeCellEditorListener(CellEditorListener l) { + if (hasDelegate()) { + delegate.removeCellEditorListener(l); + } + } + + protected TableCellEditor getDelegate() { + if (delegate == null) { + delegate = new DefaultCellEditor(new JTextField()); + } + return delegate; + } + + protected boolean hasDelegate() { + return delegate != null; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/ColorCellEditor.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/ColorCellEditor.java new file mode 100644 index 0000000..5b3d9b3 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/ColorCellEditor.java @@ -0,0 +1,128 @@ +package org.nuiton.jaxx.runtime.swing.editor; +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import javax.swing.AbstractCellEditor; +import javax.swing.JButton; +import javax.swing.JColorChooser; +import javax.swing.JDialog; +import javax.swing.JTable; +import javax.swing.table.TableCellEditor; +import java.awt.Color; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * A {@link Color} cell editor. + * + * @author Matthieu Allon + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.4 + */ +public class ColorCellEditor extends AbstractCellEditor + implements TableCellEditor, + ActionListener { + + private static final long serialVersionUID = 1L; + + protected Color currentColor; + + protected JButton button; + + protected JColorChooser colorChooser; + + protected JDialog dialog; + + protected static final String EDIT = "edit"; + + public ColorCellEditor() { + //Set up the editor (from the table's point of view), + //which is a button. + //This button brings up the color chooser dialog, + //which is the editor from the user's point of view. + button = new JButton(); + button.setActionCommand(EDIT); + button.addActionListener(this); + button.setBorderPainted(false); + + //Set up the dialog that the button brings up. + colorChooser = new JColorChooser(); + dialog = JColorChooser.createDialog(button, + "", + true, //modal + colorChooser, + this, //OK button handler + null); //no CANCEL button handler + } + + /** + * Handles events from the editor button and from + * the dialog's OK button. + */ + @Override + public void actionPerformed(ActionEvent e) { + if (EDIT.equals(e.getActionCommand())) { + //The user has clicked the cell, so + //bring up the dialog. + button.setBackground(currentColor); + colorChooser.setColor(currentColor); + dialog.setVisible(true); + + //Make the renderer reappear. + fireEditingStopped(); + + } else { //User pressed dialog's "OK" button. + currentColor = colorChooser.getColor(); + } + } + + @Override + public Color getCellEditorValue() { + //String currentColorHexa = toHex(currentColor.getRed(), currentColor.getGreen(), currentColor.getBlue()); + return currentColor; + } + + protected static String toHex(int r, int g, int b) { + return "#" + toBrowserHexValue(r) + toBrowserHexValue(g) + toBrowserHexValue(b); + } + + protected static String toBrowserHexValue(int number) { + StringBuilder builder = new StringBuilder(Integer.toHexString(number & 0xff)); + while (builder.length() < 2) { + builder.append("0"); + } + return builder.toString().toUpperCase(); + } + + + @Override + public Component getTableCellEditorComponent(JTable table, + Object value, + boolean isSelected, + int row, + int column) { + currentColor = (Color) value; + button.setBackground(currentColor); + return button; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/EnumEditor.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/EnumEditor.java new file mode 100644 index 0000000..487ccb4 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/EnumEditor.java @@ -0,0 +1,146 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* + * *##% + * JAXX Runtime + * Copyright (C) 2008 - 2009 CodeLutin + * + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * ##%* */ +package org.nuiton.jaxx.runtime.swing.editor; + +import org.nuiton.util.ReflectUtil; + +import javax.swing.JComboBox; +import java.util.EnumSet; +import java.util.Iterator; + +/** + * Une éditeur d'enum. + * + * @param <E> le type d'enumeration a editer. + * @author Tony Chemit - chemit@codelutin.com + * @since 1.6.0 + */ +public class EnumEditor<E extends Enum<E>> extends JComboBox { + + private static final long serialVersionUID = 2L; + + /** Type of enumeration */ + protected Class<E> type; + + /** + * Creates a {@link EnumEditor} for the given enumeration {@code type}, with + * all values of enumeration. + * + * @param type type of enumeration + * @param <E> generci type of enumeration + * @return the instanciated editor + */ + public static <E extends Enum<E>> EnumEditor<E> newEditor(Class<E> type) { + return new EnumEditor<E>(type); + } + + + /** + * Creates a {@link EnumEditor} for the given enumeration {@code type}, with + * all values of enumeration which {@code ordinal} is strictly lower than + * the given {@code maxOrdinal}. + * + * @param type type of enumeration + * @param maxOrdinal the upper (strict) bound of ordinal values allowed + * @param <E> generic type of enumeration + * @return the instanciated editor + */ + public static <E extends Enum<E>> EnumEditor<E> newEditor(Class<E> type, + int maxOrdinal) { + return new EnumEditor<E>(type, maxOrdinal); + } + + /** + * Creates a {@link EnumEditor} for the given enumeration {@code type}, with + * all given {@code universe} values of enumeration. + * + * @param universe enumerations to put in editor + * @param <E> generci type of enumeration + * @return the instanciated editor + */ + public static <E extends Enum<E>> EnumEditor<E> newEditor(E... universe) { + return new EnumEditor<E>(universe); + } + + public EnumEditor(Class<E> type) { + super(buildModel(type)); + this.type=type; + } + + public EnumEditor(Class<E> type, int maxOrdinal) { + super(buildModel(type, maxOrdinal)); + this.type=type; + } + + public EnumEditor(E... universe) { + super(universe); + } + + @Override + public E getSelectedItem() { + return (E) super.getSelectedItem(); + } + + public Class<E> getType() { + return type; + } + + protected static <E extends Enum<E>> Object[] buildModel(Class<E> type) { + Class<E> enumClass = ReflectUtil.getEnumClass(type); + EnumSet<E> result = EnumSet.allOf(enumClass); + return result.toArray(new Object[result.size()]); + } + + + protected static <E extends Enum<E>> Object[] buildModel(Class<E> type, + int maxOrdinal) { + Class<E> enumClass = ReflectUtil.getEnumClass(type); + EnumSet<E> result = EnumSet.allOf(enumClass); + Iterator<E> itr = result.iterator(); + while (itr.hasNext()) { + E e = itr.next(); + if (e.ordinal() > maxOrdinal) { + itr.remove(); + } + } + return result.toArray(new Object[result.size()]); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/LocaleEditor.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/LocaleEditor.java new file mode 100644 index 0000000..747242b --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/LocaleEditor.java @@ -0,0 +1,71 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.editor; + +import org.nuiton.i18n.I18n; +import org.nuiton.i18n.I18nStore; + +import javax.swing.JComboBox; +import java.util.Locale; + +/** + * A {@link Locale} editor. + * + * use the static method to have an instance of editor + * {@link #newEditor(Locale...)} + * + * If no locale is given to this method, it will go and seek via + * {@link I18nStore#getLocales()} all loaded locales in i18n system + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.6.0 + */ +public class LocaleEditor extends JComboBox { + + /** serialVersionUID */ + private static final long serialVersionUID = -6777873426011538807L; + + protected Locale[] type; + + public static LocaleEditor newEditor(Locale... type) { + return new LocaleEditor(type); + } + + public LocaleEditor(Locale... type) { + super(buildModel(type)); + } + + @Override + public Locale getSelectedItem() { + return (Locale) super.getSelectedItem(); + } + + protected static Locale[] buildModel(Locale... type) { + if (type.length > 0) { + return type; + } + // get availables locales registred in I18n system + type = I18n.getStore().getLocales(); + return type; + } + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/MyDefaultCellEditor.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/MyDefaultCellEditor.java new file mode 100644 index 0000000..50d9eff --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/editor/MyDefaultCellEditor.java @@ -0,0 +1,124 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.editor; + +import javax.swing.DefaultCellEditor; +import javax.swing.Icon; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.table.TableCellEditor; +import java.awt.Component; + +/** + * @author Tony Chemit - chemit@codelutin.com + * @since 1.5 + */ +public class MyDefaultCellEditor extends DefaultCellEditor { + + private static final long serialVersionUID = 1L; + + public static TableCellEditor newTextEditor() { + return new MyDefaultCellEditor(new JTextField()); + } + + public static TableCellEditor newBooleanEditor() { + return new MyDefaultCellEditor(new JCheckBox()); + } + + public static TableCellEditor newListEditor() { + return newListEditor(new JComboBox()); + } + + public static TableCellEditor newListEditor(JComboBox editor) { + return new MyDefaultCellEditor(editor); + } + + public static TableCellEditor newEnumEditor(EnumEditor<?> editor) { + return new MyDefaultCellEditor(editor) { + + private static final long serialVersionUID = 1L; + + @Override + public Object getCellEditorValue() { + Object value = super.getCellEditorValue(); + if (value != null) { + value = ((Enum) value).ordinal(); + } else { + value = -1; + } + return value; + } + }; + } + + public static TableCellEditor newBooleanEditor(Icon icon) { + return new MyDefaultCellEditor(new JCheckBox(icon)); + } + + public static TableCellEditor newBooleanEditor(Icon icon, boolean requireSelect) { + TableCellEditor cellEditor = newBooleanEditor(icon); + ((MyDefaultCellEditor) cellEditor).setRequireSelect(requireSelect); + return cellEditor; + } + + public static TableCellEditor newBooleanEditor(boolean requireSelect) { + TableCellEditor cellEditor = newBooleanEditor(); + ((MyDefaultCellEditor) cellEditor).setRequireSelect(requireSelect); + return cellEditor; + } + + protected boolean requireSelect = true; + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + if (!isSelected && requireSelect) { + // force to have select the cell before editing, a way to not modify edition for nothing... + return null; + } + return super.getTableCellEditorComponent(table, value, isSelected, row, column); + } + + public boolean isRequireSelect() { + return requireSelect; + } + + public void setRequireSelect(boolean requireSelect) { + this.requireSelect = requireSelect; + } + + protected MyDefaultCellEditor(JTextField textField) { + super(textField); + setClickCountToStart(1); + } + + protected MyDefaultCellEditor(JCheckBox checkBox) { + super(checkBox); + setClickCountToStart(1); + } + + protected MyDefaultCellEditor(JComboBox comboBox) { + super(comboBox); + setClickCountToStart(1); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/help/JAXXHelpBroker.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/help/JAXXHelpBroker.java new file mode 100644 index 0000000..c13c9b8 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/help/JAXXHelpBroker.java @@ -0,0 +1,613 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.help; + +import com.google.common.base.Preconditions; +import org.nuiton.jaxx.runtime.JAXXContext; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.awt.visitor.BuildTreeVisitor; +import org.nuiton.jaxx.runtime.awt.visitor.ComponentTreeNode; +import org.nuiton.jaxx.runtime.awt.visitor.GetCompopentAtPointVisitor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.help.CSH; +import javax.help.HelpBroker; +import javax.help.HelpSet; +import javax.help.plaf.basic.BasicCursorFactory; +import javax.swing.AbstractButton; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import java.applet.Applet; +import java.awt.AWTEvent; +import java.awt.ActiveEvent; +import java.awt.Component; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.MenuComponent; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.net.URL; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Map; +import java.util.Vector; + +/** + * La classe pour encapsuler l'aide de l'application. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.4 + */ +public class JAXXHelpBroker { + + public static final String JAXX_CONTEXT_ENTRY = "jaxxcontext"; + + /** Logger */ + static private Log log = LogFactory.getLog(JAXXHelpBroker.class); + + /** name of helpset */ + protected final String helpsetName; + + /** default id to use if none given */ + protected final String defaultID; + + /** help key */ + protected final String helpKey; + + /** helpset to use */ + protected HelpSet helpset; + + /** help broker */ + protected HelpBroker helpBroker; + + /** current locale used */ + protected Locale locale; + + /** cache of cursors modified when in context-sensitive mode */ + protected Hashtable<Component, Cursor> cursors; + + /** cursor to use in context-sensitive mode */ + protected Cursor onItemCursor; + + /** cache of component which cursor have been modified */ + protected final Map<Component, String> cache; + + /** help ui handler */ + protected JAXXHelpUIHandler handler; + + public JAXXHelpBroker(String helpsetName, String helpKey, String defaultID, JAXXHelpUIHandler handler) { + this(null, helpsetName, helpKey, defaultID, handler); + } + + public JAXXHelpBroker(Locale locale, String helpsetName, String helpKey, String defaultID, JAXXHelpUIHandler handler) { + if (helpsetName == null) { + throw new NullPointerException("parameter helpsetName can not be null!"); + } + if (handler == null) { + throw new NullPointerException("handler can not be null"); + } + this.locale = locale; + this.helpsetName = helpsetName; + this.helpKey = helpKey; + this.defaultID = defaultID; + this.handler = handler; + this.cache = new HashMap<Component, String>(); + } + + public void prepareUI(JAXXObject c) { + if (c == null) { + throw new NullPointerException("parameter c can not be null!"); + } + + // l'ui doit avoir un boutton showHelp + AbstractButton help = getShowHelpButton(c); + + if (help == null) { + // no showHelp button + return; + } + + // attach context to button + if (log.isDebugEnabled()) { + log.debug("attach context to showhelp button " + c); + } + help.putClientProperty(JAXX_CONTEXT_ENTRY, c); + + // add tracking action + ActionListener listener = getShowHelpAction(); + if (log.isDebugEnabled()) { + log.debug("adding tracking action " + listener); + } + help.addActionListener(listener); + + if (log.isDebugEnabled()) { + log.debug("done for " + c); + } + + + getHelpBroker().enableHelpKey(((Component) c), getDefaultID(), getHelpset()); + } + + public void showHelp(JAXXContext context, String helpId) { + getHandler().showHelp(context, this, helpId); + } + + public JAXXHelpUIHandler getHandler() { + return handler; + } + + public HelpBroker getHelpBroker() { + if (helpBroker == null) { + helpBroker = getHelpset().createHelpBroker(); + } + return helpBroker; + } + + public String getHelpKey() { + return helpKey; + } + + public HelpSet getHelpset() { + if (helpset == null) { + try { + ClassLoader cl = getClass().getClassLoader(); + URL url = HelpSet.findHelpSet(cl, helpsetName, locale); + helpset = new HelpSet(cl, url); + } catch (Exception ee) { + throw new IllegalStateException("could not find help set " + helpsetName + " for reason " + ee.getMessage(), ee); + } + } + return helpset; + } + + public String getHelpsetName() { + return helpsetName; + } + + public String getDefaultID() { + return defaultID; + } + + public void setLocale(Locale locale) { + this.locale = locale; + // need to reload helpset and helpbroker + helpset = null; + helpBroker = null; + getHelpset(); + getHelpBroker(); + } + + public void showHelpSet() { + if (log.isDebugEnabled()) { + log.debug(this); + } + new CSH.DisplayHelpFromSource(getHelpBroker()); + } + + public void installUI(Component comp, String helpId) { + CSH.setHelpIDString(comp, helpId); + if (log.isDebugEnabled()) { + log.debug(helpId + " : " + comp.getName()); + } + cache.put(comp, helpId); + } + + public class ShowHelpForTrackedComponentAction implements ActionListener { + + @Override + public void actionPerformed(ActionEvent e) { + AbstractButton source = (AbstractButton) e.getSource(); + + JAXXContext context = (JAXXContext) source.getClientProperty(JAXX_CONTEXT_ENTRY); + + // prepare cursor + onItemCursor = (Cursor) UIManager.get("HelpOnItemCursor"); + + if (onItemCursor == null) { + onItemCursor = BasicCursorFactory.getOnItemCursor(); + UIManager.put("HelpOnItemCursor", onItemCursor); + } + Preconditions.checkNotNull(onItemCursor, "A cursor is missing (add HelpOnItemCursor cursor in UIManager)."); + Vector<?> topComponents = null; + cursors = null; + + if (onItemCursor != null) { + cursors = new Hashtable<Component, Cursor>(); + topComponents = getTopContainers(source); + for (Object topComponent : topComponents) { + setAndStoreCursors((Container) topComponent, onItemCursor); + } + } + + // get the tracked component + Component comp = null; + try { + MouseEvent event = getMouseEvent(); + if (event == null) { + // tracking canceled + return; + } + comp = (Component) event.getSource(); + if (log.isDebugEnabled()) { + log.debug("component traking " + comp.getName() + " : " + comp.getClass().getName()); + } + comp = getDeppestComponent(comp, event); + if (log.isDebugEnabled()) { + log.debug("deepest component " + comp.getName() + " : " + comp.getClass().getName()); + } + } finally { + // restore the old cursors + if (topComponents != null) { + for (Object topComponent : topComponents) { + resetAndRestoreCursors((Container) topComponent); + } + } + cursors = null; + } + + String helpID = findHelpId(comp); + showHelp(context, helpID); + } + } + + protected AbstractButton getShowHelpButton(JAXXObject c) { + return (AbstractButton) c.getObjectById("showHelp"); + } + + protected ActionListener getShowHelpAction() { + return new ShowHelpForTrackedComponentAction(); + } + + protected Component getDeppestComponent(Component mouseComponent, MouseEvent event) { + ComponentTreeNode tree = BuildTreeVisitor.buildTree(mouseComponent); + + Point point = event.getLocationOnScreen(); + + Component component = GetCompopentAtPointVisitor.get(tree, point); + if (log.isDebugEnabled()) { + log.debug("Component at (" + point + "): " + component); + } + return component; +// return SwingUtil.getDeepestObjectAt(mouseComponent, event.getX(), event.getY()); + } + + public String findHelpId(Component comp) { + String helpID = CSH.getHelpIDString(comp); + if (defaultID.equals(helpID)) { + String id = cache.get(comp); + // on verifie qu'on est bien sur sur le bon id + if (helpID.equals(id)) { + // ok + return helpID; + } + if (log.isDebugEnabled()) { + log.debug("will try to find better id for comp : " + comp.getName()); + } + // on est pas sur le bon id + // on recherche parmis les parents + helpID = findExtactHelpId(comp); + } + if (log.isInfoEnabled()) { + log.info("helpID " + helpID + " for comp " + comp.getName() + " : " + comp.getClass().getName()); + } + return helpID; + } + + protected String findExtactHelpId(Component comp) { + Container parent = comp.getParent(); + while (parent != null) { + String id = cache.get(parent); + if (id == null) { + // ce container n'a pas d'id + // on va directement sur le parent + parent = parent.getParent(); + continue; + } + // le parent possède un id + // on utilise cet id + return id; + } + // on a pas trouve d'id + // on retourne l'id par defaut + return defaultID; + } + + //------------------------------------------------------------------------- + //--- Copy CSH code but with accessible modifiers and little improvments + //------------------------------------------------------------------------- + /* + * Get all top level containers to change it's cursors + */ + + protected Vector<?> getTopContainers(Object source) { + // This method is used to obtain all top level components of application + // for which the changing of cursor to question mark is wanted. + // Method Frame.getFrames() is used to get list of Frames and + // Frame.getOwnedWindows() method on elements of the list + // returns all Windows, Dialogs etc. It works correctly in application. + // Problem is in applets. There is no way how to get reference to applets + // from elsewhere than applet itself. So, if request for CSH (this means + // pressing help button or select help menu item) does't come from component + // in a Applet, cursor for applets is not changed to question mark. Only for + // Frames, Windows and Dialogs is cursor changed properly. + + Vector<Component> containers = new Vector<Component>(); + Component topComponent = null; + topComponent = getRoot(source); + if (topComponent instanceof Applet) { + try { + Enumeration<Applet> applets = ((Applet) topComponent).getAppletContext().getApplets(); + while (applets.hasMoreElements()) { + containers.add(applets.nextElement()); + } + } catch (NullPointerException npe) { + containers.add(topComponent); + } + } + Frame frames[] = Frame.getFrames(); + for (Frame frame : frames) { + Window[] windows = frame.getOwnedWindows(); + Collections.addAll(containers, windows); + if (!containers.contains(frame)) { + containers.add(frame); + } + } + return containers; + } + + protected Component getRoot(Object comp) { + Object parent = comp; + while (parent != null) { + comp = parent; + if (comp instanceof MenuComponent) { + parent = ((MenuComponent) comp).getParent(); + } else if (comp instanceof Component) { + if (comp instanceof Window) { + break; + } + if (comp instanceof Applet) { + break; + } + parent = ((Component) comp).getParent(); + } else { + break; + } + } + if (comp instanceof Component) { + return ((Component) comp); + } + return null; + } + + /* + * Set the cursor for a component and its children. + * Store the old cursors for future resetting + */ + + protected void setAndStoreCursors(Component comp, Cursor cursor) { + if (comp == null) { + return; + } + if (cache.containsKey(comp)) { + Cursor compCursor = comp.getCursor(); + if (compCursor != cursor) { + cursors.put(comp, compCursor); + if (log.isDebugEnabled()) { + log.debug("set cursor on " + comp); + } + comp.setCursor(cursor); + } + } + + if (comp instanceof Container) { + Component component[] = ((Container) comp).getComponents(); + for (Component aComponent : component) { + setAndStoreCursors(aComponent, cursor); + } + } + } + + /* + * Actually restore the cursor for a component and its children + */ + + protected void resetAndRestoreCursors(Component comp) { + if (comp == null) { + return; + } + Cursor oldCursor = cursors.get(comp); + if (oldCursor != null) { + log.debug("restored cursor " + oldCursor + " on " + comp); + comp.setCursor(oldCursor); + } + if (comp instanceof Container) { + Component component[] = ((Container) comp).getComponents(); + for (Component aComponent : component) { + resetAndRestoreCursors(aComponent); + } + } + } + + /** + * Context Sensitive Event Tracking + * + * Creates a new EventDispatchThread from which to dispatch events. This + * method returns when stopModal is invoked. + * + * @return MouseEvent The mouse event occurred. Null if + * cancelled on an undetermined object. + */ + public static MouseEvent getMouseEvent() { + // Should the cursor change to a quesiton mark here or + // require the user to change the cursor externally to this method? + // The problem is that each component can have it's own cursor. + // For that reason it might be better to have the user change the + // cusor rather than us. + + // To track context-sensitive events get the event queue and process + // the events the same way EventDispatchThread does. Filter out + // ContextSensitiveEvents SelectObject & Cancel (MouseDown & ???). + // Note: This code only handles mouse events. Accessiblity might + // require additional functionality or event trapping + + // If the eventQueue can't be retrieved, the thread gets interrupted, + // or the thread isn't a instanceof EventDispatchThread then return + // a null as we won't be able to trap events. + try { + if (EventQueue.isDispatchThread()) { + EventQueue eq = null; + + // Find the eventQueue. If we can't get to it then just return + // null since we won't be able to trap any events. + + try { + eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); + } catch (Exception ee) { + log.debug(ee); + } + + // Safe guard + if (eq == null) { + return null; + } + + int eventNumber = -1; + + // Process the events until an object has been selected or + // the context-sensitive search has been canceled. + while (true) { + // This is essentially the body of EventDispatchThread + // modified to trap context-senstive events and act + // appropriately + eventNumber++; + AWTEvent event = eq.getNextEvent(); + Object src = event.getSource(); + // can't call eq.dispatchEvent + // so I pasted it's body here + + if (log.isDebugEnabled()) { + log.debug(event); + } + + // Not sure if I should suppress ActiveEvents or not + // Modal dialogs do. For now we will not suppress the + // ActiveEvent events + + if (event instanceof ActiveEvent) { + ((ActiveEvent) event).dispatch(); + continue; + } + + if (src instanceof Component) { + // Trap the context-sensitive events here + if (event instanceof KeyEvent) { + KeyEvent e = (KeyEvent) event; + // if this is the cancel key then exit + // otherwise pass all other keys up + if (e.getKeyCode() == KeyEvent.VK_CANCEL || + e.getKeyCode() == KeyEvent.VK_ESCAPE) { + e.consume(); + return null; + } else { + e.consume(); + // dispatchEvent(event); + } + } else if (event instanceof MouseEvent) { + MouseEvent e = (MouseEvent) event; + int eID = e.getID(); + + if ((eID == MouseEvent.MOUSE_CLICKED || + eID == MouseEvent.MOUSE_PRESSED || + eID == MouseEvent.MOUSE_RELEASED) && + SwingUtilities.isRightMouseButton(e)) { + // cancel tracking + e.consume(); + if (log.isDebugEnabled()) { + log.debug("tracking canceled!!!"); + } + return null; + } + + if ((eID == MouseEvent.MOUSE_CLICKED || + eID == MouseEvent.MOUSE_PRESSED || + eID == MouseEvent.MOUSE_RELEASED) && + SwingUtilities.isLeftMouseButton(e)) { + if (eID == MouseEvent.MOUSE_CLICKED) { + if (eventNumber == 0) { + dispatchEvent(event); + continue; + } + } + e.consume(); + return e; + } else { + e.consume(); + } + } else { + dispatchEvent(event); + } + } else if (src instanceof MenuComponent) { + if (event instanceof InputEvent) { + ((InputEvent) event).consume(); + } + } else { + log.error("unable to dispatch event: " + event); + } + } + } + } catch (InterruptedException e) { + if (log.isDebugEnabled()) { + log.debug(e); + } + } + if (log.isDebugEnabled()) { + log.debug("Fall Through code"); + } + return null; + } + + protected static void dispatchEvent(AWTEvent event) { + Object src = event.getSource(); + if (event instanceof ActiveEvent) { + // This could become the sole method of dispatching in time. + ((ActiveEvent) event).dispatch(); + } else if (src instanceof Component) { + ((Component) src).dispatchEvent(event); + } else if (src instanceof MenuComponent) { + ((MenuComponent) src).dispatchEvent(event); + } else { + log.error("unable to dispatch event: " + event); + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/help/JAXXHelpUI.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/help/JAXXHelpUI.java new file mode 100644 index 0000000..f02173f --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/help/JAXXHelpUI.java @@ -0,0 +1,41 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.help; + +import java.awt.Component; + +/** + * Contract to be added on JAXXObject which wants to use javax help. + * + * @param <B> type of broker. + * @author Tony Chemit - chemit@codelutin.com + * @see JAXXHelpBroker + * @since 1.3 + */ +public interface JAXXHelpUI<B extends JAXXHelpBroker> { + + B getBroker(); + + void registerHelpId(B broker, Component component, String helpId); + + void showHelp(String helpId); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/help/JAXXHelpUIHandler.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/help/JAXXHelpUIHandler.java new file mode 100644 index 0000000..2988a4f --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/help/JAXXHelpUIHandler.java @@ -0,0 +1,30 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.help; + +import org.nuiton.jaxx.runtime.JAXXContext; + +/** @author Tony Chemit - chemit@codelutin.com */ +public interface JAXXHelpUIHandler { + + void showHelp(JAXXContext context, JAXXHelpBroker broker, String helpID); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/AbstractGenericListSelectionModel.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/AbstractGenericListSelectionModel.java new file mode 100644 index 0000000..30bbcbd --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/AbstractGenericListSelectionModel.java @@ -0,0 +1,273 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.model; + +import com.google.common.collect.Lists; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Collection; +import java.util.List; +import javax.swing.DefaultListSelectionModel; +import javax.swing.event.EventListenerList; + +/** + * @author Sylvain Lletellier + */ +public abstract class AbstractGenericListSelectionModel<B> extends DefaultListSelectionModel { + + public static final String PROPERTY_SELECTED_VALUE = "selectedValues"; + + protected EventListenerList listenerList = new EventListenerList(); + protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + + protected List<B> selectedValues; + + public AbstractGenericListSelectionModel() { + this.selectedValues = Lists.newArrayList(); + } + + public B getSelectedValue() { + return selectedValues.get(0); + } + + public List<B> getSelectedValues() { + return Lists.newArrayList(selectedValues); + } + + public void setSelectedValues(List<B> selectedValues) { + this.selectedValues = selectedValues; + } + + protected void unSelectItems(Collection<B> values) { + Collection<B> oldValue = Lists.newArrayList(selectedValues); + for (B value : values) { + int index = selectedValues.indexOf(value); + removeSelectionIntervalWithoutFire(index, index); + } + fireSelectionRemoved(values); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); + } + + protected void unSelectItem(B value) { + Collection<B> oldValue = Lists.newArrayList(selectedValues); + int index = selectedValues.indexOf(value); + removeSelectionIntervalWithoutFire(index, index); + + fireSelectionRemoved(Lists.newArrayList(value)); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); + } + + public void addSelectedItem(B toSelect) { + Collection<B> oldValue = Lists.newArrayList(selectedValues); + selectedValues.add(toSelect); + int index = selectedValues.indexOf(toSelect); + super.addSelectionInterval(index, index); + + fireSelectionAdded(Lists.newArrayList(toSelect)); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); + } + + public boolean hasSelectedIndex() { + return !selectedValues.isEmpty(); + } + + @Override + public void addSelectionInterval(int index0, int index1) { + Collection<B> oldValue = Lists.newArrayList(selectedValues); + + addSelectionIntervalWithFire(index0, index1); + super.addSelectionInterval(index0, index1); + + Collection<B> newValue = Lists.newArrayList(selectedValues); + newValue.removeAll(oldValue); + fireSelectionAdded(newValue); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); + } + + @Override + public void setSelectionInterval(int index0, int index1) { + Collection<B> oldValue = Lists.newArrayList(selectedValues); + selectedValues.clear(); + addSelectionIntervalWithFire(index0, index1); + super.setSelectionInterval(index0, index1); + + Collection<B> newValue = Lists.newArrayList(selectedValues); + newValue.removeAll(oldValue); + fireSelectionAdded(newValue); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); + } + + @Override + public void removeSelectionInterval(int index0, int index1) { + Collection<B> oldValue = Lists.newArrayList(selectedValues); + removeSelectionIntervalWithoutFire(index0, index1); + + Collection<B> newValue = Lists.newArrayList(selectedValues); + newValue.removeAll(oldValue); + fireSelectionRemoved(newValue); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); + } + + protected void removeSelectionIntervalWithoutFire(int index0, int index1) { + if (index0 > index1) { + int tmp = index1; + index1 = index0; + index0 = tmp; + } + for (int i=index0;i<=index1;i++) { + if (selectedValues.size() > i && i != -1) { + selectedValues.remove(i); + } + } + super.removeSelectionInterval(index0, index1); + } + + protected void addSelectionIntervalWithFire(int index0, int index1) { + if (index0 > index1) { + int tmp = index1; + index1 = index0; + index0 = tmp; + } + for (int i=index0;i<=index1;i++) { + + if (getSize() > i && i != -1) { + B value = getValueAt(i); + selectedValues.add(value); + } + } + } + + public abstract int getSize(); + + public abstract B getValueAt(int i); + + @Override + public void clearSelection() { + Collection<B> oldValue = Lists.newArrayList(selectedValues); + selectedValues.clear(); + super.clearSelection(); + + fireSelectionRemoved(oldValue); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); + } + + @Override + public int getSelectionMode() { + return MULTIPLE_INTERVAL_SELECTION; + } + + protected void fireValuesAdded(Collection<B> values) { + if (values.isEmpty()) { + return; + } + Object[] listeners = listenerList.getListenerList(); + GenericListEvent<B> e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == GenericListListener.class) { + if (e == null) { + e = new GenericListEvent<B>(this, values); + } + ((GenericListListener)listeners[i+1]).valuesAdded(e); + } + } + } + + protected void fireValuesRemoved(Collection<B> values) { + if (values.isEmpty()) { + return; + } + Object[] listeners = listenerList.getListenerList(); + GenericListEvent<B> e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == GenericListListener.class) { + if (e == null) { + e = new GenericListEvent<B>(this, values); + } + ((GenericListListener)listeners[i+1]).valuesRemoved(e); + } + } + } + + protected void fireSelectionAdded(Collection<B> selectedValues) { + if (selectedValues.isEmpty()) { + return; + } + Object[] listeners = listenerList.getListenerList(); + GenericListEvent<B> e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == GenericListListener.class) { + if (e == null) { + e = new GenericListEvent<B>(this, selectedValues); + } + ((GenericListListener)listeners[i+1]).selectionAdded(e); + } + } + } + + protected void fireSelectionRemoved(Collection<B> selectedValues) { + if (selectedValues.isEmpty()) { + return; + } + Object[] listeners = listenerList.getListenerList(); + GenericListEvent<B> e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == GenericListListener.class) { + if (e == null) { + e = new GenericListEvent<B>(this, selectedValues); + } + ((GenericListListener)listeners[i+1]).selectionAdded(e); + } + } + } + + public void addGenericListListener(GenericListListener l) { + listenerList.add(GenericListListener.class, l); + } + + public void removeGenericListListener(GenericListListener l) { + listenerList.remove(GenericListListener.class, l); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/AbstractSelectionListModel.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/AbstractSelectionListModel.java new file mode 100644 index 0000000..0e72d2a --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/AbstractSelectionListModel.java @@ -0,0 +1,32 @@ +package org.nuiton.jaxx.runtime.swing.model; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/** + * Created on 8/7/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since XXX + */ +public class AbstractSelectionListModel { +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/ComboBoxModel2.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/ComboBoxModel2.java new file mode 100644 index 0000000..895cf4b --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/ComboBoxModel2.java @@ -0,0 +1,50 @@ +package org.nuiton.jaxx.runtime.swing.model; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import javax.swing.ComboBoxModel; + +/** + * A new comboBox model that add supports for {@link WillChangeSelectedItemListener}. + * + * Created on 8/7/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.10 + */ +public interface ComboBoxModel2 extends ComboBoxModel { + + /** + * Adds a listener to the list that's notified each time the selected item should be changed. + * + * @param l the <code>ListDataListener</code> to be added + */ + void addWillChangeSelectedItemListener(WillChangeSelectedItemListener l); + + /** + * Adds a listener to the list that's notified each time the selected item should be changed. + * + * @param l the <code>ListDataListener</code> to be removed + */ + void removeWillChangeSelectedItemListener(WillChangeSelectedItemListener l); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/ComboBoxSelectionEvent.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/ComboBoxSelectionEvent.java new file mode 100644 index 0000000..9eaca5f --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/ComboBoxSelectionEvent.java @@ -0,0 +1,69 @@ +package org.nuiton.jaxx.runtime.swing.model; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import java.io.Serializable; +import java.util.EventObject; + +/** + * Created on 8/7/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.10 + */ +public class ComboBoxSelectionEvent extends EventObject { + + private static final long serialVersionUID = 1L; + + /** + * The current selected item in comboBox. + */ + protected final Serializable currentSelectedItem; + + /** + * The item to selected in comboBox. + */ + protected final Serializable nextSelectedItem; + + /** + * Constructs a ComboBoxSelectionEvent object. + * + * @param source the Object that originated the event + * (typically <code>this</code>) + * @param currentSelectedItem the current selected item in comboBox + * @param nextSelectedItem the item to selected in comboBox. + */ + public ComboBoxSelectionEvent(Object source, Serializable currentSelectedItem, Serializable nextSelectedItem) { + super(source); + this.currentSelectedItem = currentSelectedItem; + this.nextSelectedItem = nextSelectedItem; + } + + public Serializable getCurrentSelectedItem() { + return currentSelectedItem; + } + + public Serializable getNextSelectedItem() { + return nextSelectedItem; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/GenericListEvent.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/GenericListEvent.java new file mode 100644 index 0000000..c3f08f8 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/GenericListEvent.java @@ -0,0 +1,42 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.model; + +import java.util.Collection; +import java.util.EventObject; + +/** + * @author Sylvain Lletellier + */ +public class GenericListEvent<B> extends EventObject { + + protected Collection<B> values; + + public GenericListEvent(Object source, Collection<B> values) { + super(source); + this.values = values; + } + + public Collection<B> getValues() { + return values; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/GenericListListener.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/GenericListListener.java new file mode 100644 index 0000000..80211e0 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/GenericListListener.java @@ -0,0 +1,38 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.model; + +import java.util.EventListener; + +/** + * @author Sylvain Lletellier + */ +public interface GenericListListener extends EventListener { + + void valuesAdded(GenericListEvent event); + + void valuesRemoved(GenericListEvent event); + + void selectionAdded(GenericListEvent event); + + void selectionRemoved(GenericListEvent event); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/GenericListModel.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/GenericListModel.java new file mode 100644 index 0000000..231be4f --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/GenericListModel.java @@ -0,0 +1,162 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.model; + +import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.List; +import javax.swing.ComboBoxModel; +import javax.swing.DefaultListModel; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; + +/** + * @author Sylvain Lletellier + */ +public class GenericListModel<B> extends GenericListSelectionModel<B> implements ComboBoxModel { + + public GenericListModel() { + super(new DefaultListModel()); + } + + public GenericListModel(Collection<B> values) { + this(); + setElements(values); + } + + public void setElements(Collection<B> values) { + Collection<B> oldValues = getElements(); + Collection<B> oldSelectedValues = getSelectedValues(); + clearSelection(); + fireSelectionRemoved(oldSelectedValues); + + clearElements(); + fireValuesRemoved(oldValues); + + for (B value : values) { + getListModel().addElement(value); + } + + fireSelectionAdded(values); + } + + public void clearElements() { + Collection<B> elements = getElements(); + getListModel().clear(); + + fireValuesRemoved(elements); + } + + public Collection<B> getElements() { + int size = getListModel().getSize(); + Collection<B> result = Lists.newArrayList(); + for (int i=0;i<size;i++) { + result.add((B) getListModel().get(i)); + } + return result; + } + + public void addElement(int index, B valueToAdd) { + getListModel().add(index, valueToAdd); + + fireValuesAdded(Lists.newArrayList(valueToAdd)); + } + + public void addElement(B valueToAdd) { + getListModel().addElement(valueToAdd); + + fireValuesAdded(Lists.newArrayList(valueToAdd)); + } + + public void addElements(Collection<B> valuesToAdd) { + for (B value : valuesToAdd) { + getListModel().addElement(value); + } + + fireValuesAdded(valuesToAdd); + } + + public void removeElements(Collection<B> values) { + for (B value : values) { + getListModel().removeElement(value); + } + unSelectItems(values); + + fireValuesRemoved(values); + } + + @Override + public void setSelectedItem(Object anItem) { + List<B> oldValue = getSelectedValues(); + fireSelectionRemoved(oldValue); + + setSelectedValues(Lists.newArrayList((B) anItem)); + + List<B> newValues = getSelectedValues(); + fireSelectionAdded(newValues); + fireContentsChanged(this, -1, -1); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, newValues); + } + + @Override + public B getSelectedItem() { + List<B> selectedValues = getSelectedValues(); + if (selectedValues.isEmpty()) { + return null; + } + return selectedValues.get(0); + } + + @Override + public int getSize() { + return getListModel().size(); + } + + @Override + public Object getElementAt(int index) { + return getListModel().get(index); + } + + @Override + public void addListDataListener(ListDataListener l) { + getListModel().addListDataListener(l); + } + + @Override + public void removeListDataListener(ListDataListener l) { + getListModel().removeListDataListener(l); + } + + protected void fireContentsChanged(Object source, int index0, int index1) { + Object[] listeners = getListModel().getListDataListeners(); + ListDataEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ListDataListener.class) { + if (e == null) { + e = new ListDataEvent(source, ListDataEvent.CONTENTS_CHANGED, index0, index1); + } + ((ListDataListener)listeners[i+1]).contentsChanged(e); + } + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/GenericListSelectionModel.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/GenericListSelectionModel.java new file mode 100644 index 0000000..07714f8 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/GenericListSelectionModel.java @@ -0,0 +1,51 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.model; + +import javax.swing.DefaultListModel; + +/** + * @author Sylvain Lletellier + */ +public class GenericListSelectionModel<B> extends AbstractGenericListSelectionModel<B> { + + protected DefaultListModel listModel; + + public GenericListSelectionModel(DefaultListModel listModel) { + super(); + this.listModel = listModel; + } + + public DefaultListModel getListModel() { + return listModel; + } + + @Override + public int getSize() { + return listModel.size(); + } + + @Override + public B getValueAt(int i) { + return (B)listModel.getElementAt(i); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/JaxxDefaultComboBoxModel.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/JaxxDefaultComboBoxModel.java new file mode 100644 index 0000000..87aabbc --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/JaxxDefaultComboBoxModel.java @@ -0,0 +1,219 @@ +package org.nuiton.jaxx.runtime.swing.model; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.collections4.CollectionUtils; + +import javax.swing.AbstractListModel; +import javax.swing.DefaultComboBoxModel; +import javax.swing.MutableComboBoxModel; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Vector; + +/** + * To replace the {@link DefaultComboBoxModel} which used {@link Vector}. + * + * Add some new methods to {@link #addAllElements(Collection)} or + * {@link #setAllElements(Collection)}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.10 + */ +public class JaxxDefaultComboBoxModel<E> extends AbstractListModel implements MutableComboBoxModel, Serializable, ComboBoxModel2 { + + private static final long serialVersionUID = 1L; + + protected List<E> delegate; + + protected E selectedObject; + + public JaxxDefaultComboBoxModel() { + delegate = new ArrayList<E>(); + } + + public JaxxDefaultComboBoxModel(E... items) { + delegate = new ArrayList<E>(items.length); + + int i, c; + for (i = 0, c = items.length; i < c; i++) + delegate.add(items[i]); + + if (getSize() > 0) { + selectedObject = getElementAt(0); + } + } + + public JaxxDefaultComboBoxModel(Collection<E> v) { + delegate = new ArrayList<E>(v); + + if (getSize() > 0) { + selectedObject = getElementAt(0); + } + } + + @Override + public void setSelectedItem(Object anObject) { + if ((selectedObject != null && !selectedObject.equals(anObject)) || + selectedObject == null && anObject != null) { + + try { + fireSelectedItemWillChanged(selectedObject, anObject); + } catch (WillChangeSelectedItemVetoException e) { + // was not allowed to change selected item + return; + } + selectedObject = (E) anObject; + fireContentsChanged(this, -1, -1); + } + } + + public int getIndexOf(E anObject) { + return delegate.indexOf(anObject); + } + + + public void setAllElements(Collection<E> objects) { + removeAllElements(); + addAllElements(objects); + } + + public void addAllElements(Collection<E> objects) { + if (CollectionUtils.isNotEmpty(objects)) { + int firstIndex = delegate.size(); + this.delegate.addAll(objects); + int lastIndex = delegate.size() - 1; + if (lastIndex > -1) { + fireIntervalAdded(this, firstIndex, lastIndex); + } + } + } + + /** Empties the list. */ + public void removeAllElements() { + if (delegate.size() > 0) { + int firstIndex = 0; + int lastIndex = delegate.size() - 1; + delegate.clear(); + selectedObject = null; + fireIntervalRemoved(this, firstIndex, lastIndex); + } else { + selectedObject = null; + } + } + + @Override + public E getSelectedItem() { + return selectedObject; + } + + @Override + public int getSize() { + return delegate.size(); + } + + @Override + public E getElementAt(int index) { + E result; + + if (index >= 0 && index < delegate.size()) { + result = delegate.get(index); + } else { + result = null; + } + return result; + } + + @Override + public void addElement(Object anObject) { + delegate.add((E) anObject); + fireIntervalAdded(this, delegate.size() - 1, delegate.size() - 1); + if (delegate.size() == 1 && selectedObject == null && anObject != null) { + setSelectedItem(anObject); + } + } + + @Override + public void insertElementAt(Object anObject, int index) { + delegate.add(index, (E) anObject); + fireIntervalAdded(this, index, index); + } + + @Override + public void removeElementAt(int index) { + if (getElementAt(index) == selectedObject) { + if (index == 0) { + setSelectedItem(getSize() == 1 ? null : getElementAt(index + 1)); + } else { + setSelectedItem(getElementAt(index - 1)); + } + } + + delegate.remove(index); + + fireIntervalRemoved(this, index, index); + } + + @Override + public void removeElement(Object anObject) { + int index = delegate.indexOf(anObject); + if (index != -1) { + removeElementAt(index); + } + } + + @Override + public void addWillChangeSelectedItemListener(WillChangeSelectedItemListener l) { + listenerList.add(WillChangeSelectedItemListener.class, l); + } + + @Override + public void removeWillChangeSelectedItemListener(WillChangeSelectedItemListener l) { + listenerList.remove(WillChangeSelectedItemListener.class, l); + } + + /** + * Notifies all listeners that have registered interest for + * notification on this event type. The event instance + * is lazily created using the <code>currentSelectedItem</code> and <code>newSelectedItem</code> parameter. + */ + public void fireSelectedItemWillChanged(Object currentSelectedItem, + Object newSelectedItem) throws WillChangeSelectedItemVetoException { + // Guaranteed to return a non-null array + Object[] listeners = listenerList.getListenerList(); + ComboBoxSelectionEvent e = null; + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == WillChangeSelectedItemListener.class) { + // Lazily create the event: + if (e == null) + e = new ComboBoxSelectionEvent(this, (Serializable)currentSelectedItem, (Serializable) newSelectedItem); + ((WillChangeSelectedItemListener) listeners[i + 1]). + selectedItemWillChanged(e); + } + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/JaxxDefaultListModel.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/JaxxDefaultListModel.java new file mode 100644 index 0000000..6388423 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/JaxxDefaultListModel.java @@ -0,0 +1,618 @@ +package org.nuiton.jaxx.runtime.swing.model; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.Lists; +import org.apache.commons.collections4.CollectionUtils; + +import javax.swing.AbstractListModel; +import javax.swing.DefaultListModel; +import java.util.ArrayList; +import java.util.Collection; +import java.util.NoSuchElementException; +import java.util.Vector; + +/** + * To replace the {@link DefaultListModel} which used {@link Vector}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.10 + */ +public class JaxxDefaultListModel<E> extends AbstractListModel { + + private static final long serialVersionUID = 1L; + + protected ArrayList<E> delegate = new ArrayList<E>(); + + protected boolean valueIsAdjusting; + + public boolean isValueIsAdjusting() { + return valueIsAdjusting; + } + + public void setValueIsAdjusting(boolean valueIsAdjusting) { + this.valueIsAdjusting = valueIsAdjusting; + } + + public ArrayList<E> toList() { + return Lists.newArrayList(delegate); + } + + /** + * Returns the number of components in this list. + * + * This method is identical to <code>size</code>, which implements the + * <code>List</code> interface defined in the 1.2 Collections framework. + * This method exists in conjunction with <code>setSize</code> so that + * <code>size</code> is identifiable as a JavaBean property. + * + * @return the number of components in this list + * @see #size() + */ + @Override + public int getSize() { + return delegate.size(); + } + + /** + * Returns the component at the specified index. + * <blockquote> + * <b>Note:</b> Although this method is not deprecated, the preferred + * method to use is <code>get(int)</code>, which implements the + * <code>List</code> interface defined in the 1.2 Collections framework. + * </blockquote> + * + * @param index an index into this list + * @return the component at the specified index + * @throws ArrayIndexOutOfBoundsException if the <code>index</code> + * is negative or greater than the current size of this + * list + * @see #get(int) + */ + @Override + public E getElementAt(int index) { + return delegate.get(index); + } + +// /** +// * Copies the components of this list into the specified array. +// * The array must be big enough to hold all the objects in this list, +// * else an <code>IndexOutOfBoundsException</code> is thrown. +// * +// * @param anArray the array into which the components get copied +// * @see Vector#copyInto(Object[]) +// */ +// public void copyInto(Object anArray[]) { +// delegate.copyInto(anArray); +// } + + /** + * Trims the capacity of this list to be the list's current size. + * + * @see Vector#trimToSize() + */ + public void trimToSize() { + delegate.trimToSize(); + } + + /** + * Increases the capacity of this list, if necessary, to ensure + * that it can hold at least the number of components specified by + * the minimum capacity argument. + * + * @param minCapacity the desired minimum capacity + * @see Vector#ensureCapacity(int) + */ + public void ensureCapacity(int minCapacity) { + delegate.ensureCapacity(minCapacity); + } + + /** + * Sets the size of this list. + * + * @param newSize the new size of this list + * @see Vector#setSize(int) + */ + public void setSize(int newSize) { + int oldSize = delegate.size(); + delegate.ensureCapacity(newSize); + if (oldSize > newSize) { + fireIntervalRemoved(this, newSize, oldSize - 1); + } else if (oldSize < newSize) { + fireIntervalAdded(this, oldSize, newSize - 1); + } + } + + /** + * Returns the current capacity of this list. + * + * @return the current capacity + * @see Vector#capacity() + */ + public int capacity() { + return delegate.size(); + } + + /** + * Returns the number of components in this list. + * + * @return the number of components in this list + * @see Vector#size() + */ + public int size() { + return delegate.size(); + } + + /** + * Tests whether this list has any components. + * + * @return <code>true</code> if and only if this list has + * no components, that is, its size is zero; + * <code>false</code> otherwise + * @see Vector#isEmpty() + */ + public boolean isEmpty() { + return delegate.isEmpty(); + } + +// /** +// * Returns an enumeration of the components of this list. +// * +// * @return an enumeration of the components of this list +// * @see Vector#elements() +// */ +// public Enumeration<E> elements() { +// return delegate.iterator().elements(); +// } + + /** + * Tests whether the specified object is a component in this list. + * + * @param elem an object + * @return <code>true</code> if the specified object + * is the same as a component in this list + * @see Vector#contains(Object) + */ + public boolean contains(E elem) { + return delegate.contains(elem); + } + + /** + * Searches for the first occurrence of <code>elem</code>. + * + * @param elem an object + * @return the index of the first occurrence of the argument in this + * list; returns <code>-1</code> if the object is not found + * @see Vector#indexOf(Object) + */ + public int indexOf(E elem) { + return delegate.indexOf(elem); + } + + /** + * Searches for the first occurrence of <code>elem</code>, beginning + * the search at <code>index</code>. + * + * @param elem an desired component + * @param index the index from which to begin searching + * @return the index where the first occurrence of <code>elem</code> + * is found after <code>index</code>; returns <code>-1</code> + * if the <code>elem</code> is not found in the list + * @see Vector#indexOf(Object, int) + */ + public int indexOf(E elem, int index) { + return delegate.indexOf(elem); + } + + /** + * Returns the index of the last occurrence of <code>elem</code>. + * + * @param elem the desired component + * @return the index of the last occurrence of <code>elem</code> + * in the list; returns <code>-1</code> if the object is not found + * @see Vector#lastIndexOf(Object) + */ + public int lastIndexOf(E elem) { + return delegate.lastIndexOf(elem); + } + + /** + * Searches backwards for <code>elem</code>, starting from the + * specified index, and returns an index to it. + * + * @param elem the desired component + * @param index the index to start searching from + * @return the index of the last occurrence of the <code>elem</code> + * in this list at position less than <code>index</code>; + * returns <code>-1</code> if the object is not found + * @see Vector#lastIndexOf(Object, int) + */ + public int lastIndexOf(E elem, int index) { + return delegate.lastIndexOf(elem); + } + + /** + * Returns the component at the specified index. + * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index + * is negative or not less than the size of the list. + * <blockquote> + * <b>Note:</b> Although this method is not deprecated, the preferred + * method to use is <code>get(int)</code>, which implements the + * <code>List</code> interface defined in the 1.2 Collections framework. + * </blockquote> + * + * @param index an index into this list + * @return the component at the specified index + * @see #get(int) + * @see Vector#elementAt(int) + */ + public E elementAt(int index) { + return delegate.get(index); + } + + /** + * Returns the first component of this list. + * Throws a <code>NoSuchElementException</code> if this + * vector has no components. + * + * @return the first component of this list + * @see Vector#firstElement() + */ + public E firstElement() { + if (isEmpty()) { + throw new NoSuchElementException(); + } + return delegate.get(0); + } + + /** + * Returns the last component of the list. + * Throws a <code>NoSuchElementException</code> if this vector + * has no components. + * + * @return the last component of the list + * @see Vector#lastElement() + */ + public E lastElement() { + if (isEmpty()) { + throw new NoSuchElementException(); + } + return delegate.get(delegate.size() - 1); + } + + /** + * Sets the component at the specified <code>index</code> of this + * list to be the specified element. The previous component at that + * position is discarded. + * + * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index + * is invalid. + * <blockquote> + * <b>Note:</b> Although this method is not deprecated, the preferred + * method to use is <code>set(int,Object)</code>, which implements the + * <code>List</code> interface defined in the 1.2 Collections framework. + * </blockquote> + * + * @param element what the component is to be set to + * @param index the specified index + * @see #set(int, Object) + * @see Vector#setElementAt(Object, int) + */ + public void setElementAt(E element, int index) { + delegate.set(index, element); + if (!isValueIsAdjusting()) { + fireContentsChanged(this, index, index); + } + } + + /** + * Deletes the component at the specified index. + * + * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index + * is invalid. + * <blockquote> + * <b>Note:</b> Although this method is not deprecated, the preferred + * method to use is <code>remove(int)</code>, which implements the + * <code>List</code> interface defined in the 1.2 Collections framework. + * </blockquote> + * + * @param index the index of the object to remove + * @see #remove(int) + * @see Vector#removeElementAt(int) + */ + public void removeElementAt(int index) { + delegate.remove(index); + if (!isValueIsAdjusting()) { + fireIntervalRemoved(this, index, index); + } + } + + /** + * Inserts the specified element as a component in this list at the + * specified <code>index</code>. + * + * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index + * is invalid. + * <blockquote> + * <b>Note:</b> Although this method is not deprecated, the preferred + * method to use is <code>add(int,Object)</code>, which implements the + * <code>List</code> interface defined in the 1.2 Collections framework. + * </blockquote> + * + * @param element the component to insert + * @param index where to insert the new component + * @throws ArrayIndexOutOfBoundsException if the index was invalid + * @see #add(int, Object) + * @see Vector#insertElementAt(Object, int) + */ + public void insertElementAt(E element, int index) { + delegate.add(index, element); + if (!isValueIsAdjusting()) { + fireIntervalAdded(this, index, index); + } + } + + /** + * Adds the specified component to the end of this list. + * + * @param element the component to be added + * @see Vector#addElement(Object) + */ + public void addElement(E element) { + int index = delegate.size(); + delegate.add(element); + if (!isValueIsAdjusting()) { + fireIntervalAdded(this, index, index); + } + } + + /** + * Removes the first (lowest-indexed) occurrence of the argument + * from this list. + * + * @param obj the component to be removed + * @return <code>true</code> if the argument was a component of this + * list; <code>false</code> otherwise + * @see Vector#removeElement(Object) + */ + public boolean removeElement(E obj) { + int index = indexOf(obj); + boolean rv = delegate.remove(obj); + if (index >= 0) { + if (!isValueIsAdjusting()) { + fireIntervalRemoved(this, index, index); + } + } + return rv; + } + + + /** + * Removes all components from this list and sets its size to zero. + * <blockquote> + * <b>Note:</b> Although this method is not deprecated, the preferred + * method to use is <code>clear</code>, which implements the + * <code>List</code> interface defined in the 1.2 Collections framework. + * </blockquote> + * + * @see #clear() + * @see Vector#removeAllElements() + */ + public void removeAllElements() { + int index1 = delegate.size() - 1; + delegate.clear(); + if (index1 >= 0) { + if (!isValueIsAdjusting()) { + fireIntervalRemoved(this, 0, index1); + } + } + } + + @Override + public String toString() { + return delegate.toString(); + } + + + /* The remaining methods are included for compatibility with the + * Java 2 platform Vector class. + */ + + /** + * Returns an array containing all of the elements in this list in the + * correct order. + * + * @return an array containing the elements of the list + * @see Vector#toArray() + */ + public Object[] toArray() { + return delegate.toArray(); + } + + /** + * Returns the element at the specified position in this list. + * + * Throws an <code>ArrayIndexOutOfBoundsException</code> + * if the index is out of range + * (<code>index < 0 || index >= size()</code>). + * + * @param index index of element to return + */ + public E get(int index) { + return delegate.get(index); + } + + /** + * Replaces the element at the specified position in this list with the + * specified element. + * + * Throws an <code>ArrayIndexOutOfBoundsException</code> + * if the index is out of range + * (<code>index < 0 || index >= size()</code>). + * + * @param index index of element to replace + * @param element element to be stored at the specified position + * @return the element previously at the specified position + */ + public E set(int index, E element) { + E rv = delegate.set(index, element); + if (!isValueIsAdjusting()) { + fireContentsChanged(this, index, index); + } + return rv; + } + + /** + * Inserts the specified element at the specified position in this list. + * + * Throws an <code>ArrayIndexOutOfBoundsException</code> if the + * index is out of range + * (<code>index < 0 || index > size()</code>). + * + * @param index index at which the specified element is to be inserted + * @param element element to be inserted + */ + public void add(int index, E element) { + delegate.add(index, element); + if (!isValueIsAdjusting()) { + fireIntervalAdded(this, index, index); + } + } + + public void setAllElements(Collection<E> objects) { + removeAllElements(); + addAllElements(objects); + } + + public void addAllElements(Collection<E> elements) { + if (CollectionUtils.isNotEmpty(elements)) { + + int firstIndex = delegate.size(); + this.delegate.addAll(elements); + int lastIndex = delegate.size() - 1; + if (lastIndex > -1) { + if (!isValueIsAdjusting()) { + fireIntervalAdded(this, firstIndex, lastIndex); + } + } + } + } + + public void removeAllElements(Collection<E> elements) { + if (CollectionUtils.isNotEmpty(elements)) { + + int firstIndex = 0; + int lastIndex = delegate.size(); + this.delegate.removeAll(elements); + if (lastIndex > -1) { + if (!isValueIsAdjusting()) { + fireContentsChanged(this, firstIndex, lastIndex); + } + } + } + } + + /** + * Removes the element at the specified position in this list. + * Returns the element that was removed from the list. + * + * Throws an <code>ArrayIndexOutOfBoundsException</code> + * if the index is out of range + * (<code>index < 0 || index >= size()</code>). + * + * @param index the index of the element to removed + * @return the element previously at the specified position + */ + public E remove(int index) { + E rv = delegate.remove(index); + if (!isValueIsAdjusting()) { + fireIntervalRemoved(this, index, index); + } + return rv; + } + + /** + * Removes all of the elements from this list. The list will + * be empty after this call returns (unless it throws an exception). + */ + public void clear() { + int index1 = delegate.size() - 1; + delegate.clear(); + if (index1 >= 0) { + if (!isValueIsAdjusting()) { + fireIntervalRemoved(this, 0, index1); + } + } + } + + /** + * Deletes the components at the specified range of indexes. + * The removal is inclusive, so specifying a range of (1,5) + * removes the component at index 1 and the component at index 5, + * as well as all components in between. + * + * Throws an <code>ArrayIndexOutOfBoundsException</code> + * if the index was invalid. + * Throws an <code>IllegalArgumentException</code> if + * <code>fromIndex > toIndex</code>. + * + * @param fromIndex the index of the lower end of the range + * @param toIndex the index of the upper end of the range + * @see #remove(int) + */ + public void removeRange(int fromIndex, int toIndex) { + if (fromIndex > toIndex) { + throw new IllegalArgumentException("fromIndex must be <= toIndex"); + } + for (int i = toIndex; i >= fromIndex; i--) { + delegate.remove(i); + } + if (!isValueIsAdjusting()) { + fireIntervalRemoved(this, fromIndex, toIndex); + } + } + + public void refresh() { + if (!isEmpty()) { + + if (!isValueIsAdjusting()) { + fireContentsChanged(this, 0, getSize() - 1); + } + } + } + + public void refresh(int size) { + + if (!isValueIsAdjusting()) { + fireContentsChanged(this, 0, size); + } + + } + + /* + public void addAll(Collection c) { + } + + public void addAll(int index, Collection c) { + }*/ +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/JaxxFilterableComboBoxModel.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/JaxxFilterableComboBoxModel.java new file mode 100644 index 0000000..a58ebba --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/JaxxFilterableComboBoxModel.java @@ -0,0 +1,235 @@ +package org.nuiton.jaxx.runtime.swing.model; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Predicate; +import com.google.common.collect.Lists; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.decorator.JXPathDecorator; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.regex.Pattern; + +/** + * ComboBoxModel which can filter the elements displayed in the popup. + * + * @author Kevin Morin - morin@codelutin.com + * @since 2.5.12 + */ +public class JaxxFilterableComboBoxModel<E> extends JaxxDefaultComboBoxModel<E> { + + private static final long serialVersionUID = 1L; + + /** Logger. */ + private static final Log log = LogFactory.getLog(JaxxFilterableComboBoxModel.class); + + public static final Character DEFAULT_WILDCARD_CHARACTER = '*'; + + protected List<E> filteredItems = Lists.newArrayList(); + + protected String filterText; + + protected Character wildcardCharacter = DEFAULT_WILDCARD_CHARACTER; + + /** the decorator of data */ + protected JXPathDecorator<E> decorator; + + protected List<Predicate<E>> filters = Lists.newArrayList(); + + public JaxxFilterableComboBoxModel() { + super(); + } + + public JaxxFilterableComboBoxModel(E... items) { + delegate = new ArrayList<E>(items.length); + + int i, c; + for (i = 0, c = items.length; i < c; i++) + delegate.add(items[i]); + + } + + public JaxxFilterableComboBoxModel(Collection<E> v) { + delegate = new ArrayList<E>(v); + } + + @Override + public int getIndexOf(E anObject) { + return filteredItems.indexOf(anObject); + } + + @Override + public void addAllElements(Collection<E> objects) { + super.addAllElements(objects); + refilter(); + } + + /** Empties the list. */ + @Override + public void removeAllElements() { + super.removeAllElements(); + refilter(); + } + + @Override + public int getSize() { + return filteredItems.size(); + } + + @Override + public E getElementAt(int index) { + E result; + + synchronized (this) { + if (index >= 0 && index < filteredItems.size()) { + result = filteredItems.get(index); + } else { + result = null; + } + } + + return result; + } + + @Override + public void addElement(Object anObject) { + super.addElement(anObject); + refilter(); + } + + @Override + public void insertElementAt(Object anObject, int index) { + super.insertElementAt(anObject, index); + refilter(); + } + + @Override + public void removeElementAt(int index) { + super.removeElementAt(index); + refilter(); + } + + @Override + public void removeElement(Object anObject) { + super.removeElement(anObject); + refilter(); + } + + public String getFilterText() { + return filterText; + } + + public void setFilterText(String filterText) { + this.filterText = filterText; + refilter(); + } + + public Character getWildcardCharacter() { + return wildcardCharacter; + } + + public void setWildcardCharacter(Character wildcardCharacter) { + this.wildcardCharacter = wildcardCharacter; + refilter(); + + } + + public JXPathDecorator<E> getDecorator() { + return decorator; + } + + public void setDecorator(JXPathDecorator<E> decorator) { + this.decorator = decorator; + } + + public void addFilter(Predicate<E> filter) { + filters.add(filter); + refilter(); + } + + public void removeFilter(Predicate<E> filter) { + filters.remove(filter); + refilter(); + } + + public void clearFilters() { + filters.clear(); + refilter(); + } + + public void refreshFilteredElements() { + refilter(); + } + + protected void refilter() { + filteredItems.clear(); + + if ((StringUtils.isEmpty(filterText) + || wildcardCharacter != null && StringUtils.isEmpty(StringUtils.remove(filterText, wildcardCharacter))) + && filters.isEmpty()) { + filteredItems.addAll(delegate); + + } else { + Pattern pattern = null; + if (!StringUtils.isBlank(filterText)) { + String patternText= Pattern.quote(filterText); + + if (wildcardCharacter == null) { + patternText = ".*" + patternText; + + } else { + patternText = patternText.replace(wildcardCharacter.toString(), "\\E.*\\Q"); + } + pattern = Pattern.compile(patternText + ".*", Pattern.CASE_INSENSITIVE); + } + + for (E element : delegate) { + boolean addElement = true; + for (Predicate<E> filter : filters) { + addElement &= filter.apply(element); + } + String decoratedElement; + if (decorator != null) { + decoratedElement = decorator.toString(element); + } else { + decoratedElement = String.valueOf(element); + } + boolean matches = pattern == null + || pattern.matcher(decoratedElement).matches(); + if (matches && addElement) { + filteredItems.add(element); + } + } + } + + if (log.isInfoEnabled()) { + log.info("After refilter, nb items: " + getSize()); + } + + fireContentsChanged(this, 0, getSize()); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/JaxxFilterableListModel.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/JaxxFilterableListModel.java new file mode 100644 index 0000000..dfd40d4 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/JaxxFilterableListModel.java @@ -0,0 +1,259 @@ +package org.nuiton.jaxx.runtime.swing.model; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Predicate; +import com.google.common.collect.Lists; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.regex.Pattern; +import org.apache.commons.lang3.StringUtils; +import org.nuiton.decorator.JXPathDecorator; + +/** + * List model for filterable lists. + * + * @author Kevin Morin - morin@codelutin.com + * @since 2.5.11 + */ +public class JaxxFilterableListModel<E> extends JaxxDefaultListModel<E> { + + private static final long serialVersionUID = 1L; + + protected ArrayList<E> filteredItems = Lists.newArrayList(); + + protected String filterText; + + /** the decorator of data */ + protected JXPathDecorator<E> decorator; + + protected List<Predicate<E>> filters = Lists.newArrayList(); + + @Override + public E getElementAt(int index) { + E result; + + synchronized (this) { + if (index >= 0 && index < filteredItems.size()) { + result = filteredItems.get(index); + } else { + result = null; + } + } + return result; + } + + @Override + public E elementAt(int index) { + return getElementAt(index); + } + + @Override + public void addElement(E o) { + super.addElement(o); + refilter(); + } + + @Override + public boolean removeElement(E o) { + boolean result = super.removeElement(o); + refilter(); + return result; + } + + @Override + public int getSize() { + return filteredItems.size(); + } + + @Override + public int size() { + return filteredItems.size(); + } + + @Override + public void trimToSize() { + super.trimToSize(); + filteredItems.trimToSize(); + } + + @Override + public void ensureCapacity(int minCapacity) { + super.ensureCapacity(minCapacity); + filteredItems.ensureCapacity(minCapacity); + } + + @Override + public void setSize(int newSize) { + super.setSize(newSize); + filteredItems.ensureCapacity(newSize); + } + + @Override + public void setElementAt(E element, int index) { + super.setElementAt(element, index); + refilter(); + } + + @Override + public void removeElementAt(int index) { + super.removeElementAt(index); + refilter(); + } + + @Override + public void insertElementAt(E element, int index) { + super.insertElementAt(element, index); + refilter(); + } + + @Override + public void removeAllElements() { + super.removeAllElements(); + refilter(); + } + + @Override + public E set(int index, E element) { + E rv = super.set(index, element); + refilter(); + return rv; + } + + @Override + public void add(int index, E element) { + super.add(index, element); + refilter(); + } + + @Override + public void setAllElements(Collection<E> objects) { + super.setAllElements(objects); + refilter(); + } + + @Override + public void addAllElements(Collection<E> elements) { + super.addAllElements(elements); + refilter(); + } + + @Override + public void removeAllElements(Collection<E> elements) { + super.removeAllElements(elements); + refilter(); + } + + @Override + public E remove(int index) { + E rv = super.remove(index); + refilter(); + return rv; + } + + @Override + public void clear() { + super.clear(); + refilter(); + } + + @Override + public void removeRange(int fromIndex, int toIndex) { + super.removeRange(fromIndex, toIndex); + refilter(); + } + + public String getFilterText() { + return filterText; + } + + public void setFilterText(String filterText) { + this.filterText = filterText; + refilter(); + } + + public JXPathDecorator<E> getDecorator() { + return decorator; + } + + public void setDecorator(JXPathDecorator<E> decorator) { + this.decorator = decorator; + } + + public void addFilter(Predicate<E> filter) { + filters.add(filter); + refilter(); + } + + public void removeFilter(Predicate<E> filter) { + filters.remove(filter); + refilter(); + } + + public void clearFilters() { + filters.clear(); + refilter(); + } + + public void refreshFilteredElements() { + refilter(); + } + + protected void refilter() { + filteredItems.clear(); + + if (StringUtils.isEmpty(StringUtils.remove(filterText, '*')) + && filters.isEmpty()) { + filteredItems.addAll(delegate); + + } else { + int itemNumber = delegate.size(); + Pattern pattern = null; + if (!StringUtils.isBlank(filterText)) { + String patternText = Pattern.quote(filterText).replace("*", "\\E.*\\Q") + ".*"; + pattern = Pattern.compile(patternText, Pattern.CASE_INSENSITIVE); + } + for (int i = 0 ; i < itemNumber ; i++) { + E element = delegate.get(i); + boolean addElement = true; + for (Predicate<E> filter : filters) { + addElement &= filter.apply(element); + } + String decoratedElement; + if (decorator != null) { + decoratedElement = decorator.toString(element); + } else { + decoratedElement = String.valueOf(element); + } + boolean matches = pattern == null + || pattern.matcher(decoratedElement).matches(); + if (matches && addElement) { + filteredItems.add(element); + } + } + } + + fireContentsChanged(this, 0, getSize()); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/WillChangeSelectedItemListener.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/WillChangeSelectedItemListener.java new file mode 100644 index 0000000..ad304e3 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/WillChangeSelectedItemListener.java @@ -0,0 +1,41 @@ +package org.nuiton.jaxx.runtime.swing.model; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import java.util.EventListener; + +/** + * A listener to be able to stop the change of a selected item in a + * Created on 8/7/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.10 + */ +public interface WillChangeSelectedItemListener extends EventListener { + + /** + * Invoked whenever the selected item is about to change in the comboBox. + */ + void selectedItemWillChanged(ComboBoxSelectionEvent event) throws WillChangeSelectedItemVetoException; + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/WillChangeSelectedItemVetoException.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/WillChangeSelectedItemVetoException.java new file mode 100644 index 0000000..91eb858 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/model/WillChangeSelectedItemVetoException.java @@ -0,0 +1,58 @@ +package org.nuiton.jaxx.runtime.swing.model; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/** + * Created on 8/7/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.10 + */ +public class WillChangeSelectedItemVetoException extends Exception { + + private static final long serialVersionUID = 1L; + + /** The event that the exception was created for. */ + protected ComboBoxSelectionEvent event; + + /** + * Constructs an ExpandVetoException object with no message. + * + * @param event a ComboBoxSelectionEvent object + */ + + public WillChangeSelectedItemVetoException(ComboBoxSelectionEvent event) { + this(event, null); + } + + /** + * Constructs an ExpandVetoException object with the specified message. + * + * @param event a ComboBoxSelectionEvent object + * @param message a String containing the message + */ + public WillChangeSelectedItemVetoException(ComboBoxSelectionEvent event, String message) { + super(message); + this.event = event; + } +} \ No newline at end of file diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavBridge.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavBridge.java new file mode 100644 index 0000000..d21f56e --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavBridge.java @@ -0,0 +1,122 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav; + +import javax.swing.event.TreeModelListener; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import java.util.EventListener; + +/** + * Contract of the bridge used by {@link NavHelper} to hold model and ui. + * + * @param <M> Type of model to bridge + * @param <N> Type of nodes of the model + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public interface NavBridge<M, N extends NavNode<M, N>> { + + //-------------------------------------------------------------------------- + //-- Model Queries + //-------------------------------------------------------------------------- + + M getModel(); + + N getRoot(); + + boolean isLeaf(Object node); + + int getChildCount(Object parent); + + N getChild(Object parent, int index); + + int getIndexOfChild(Object parent, Object child); + + TreeNode[] getPathToRoot(TreeNode aNode); + + //-------------------------------------------------------------------------- + //-- Model modification + //-------------------------------------------------------------------------- + + void setModel(M delegate); + + void setRoot(N node); + + void insertNodeInto(N newChild, N parent, int index); + + void removeNodeFromParent(N node); + + void reload(N node); + + boolean canLoadChild(N node); + + //-------------------------------------------------------------------------- + //-- Listeners notifications + //-------------------------------------------------------------------------- + + void valueForPathChanged(TreePath path, Object newValue); + + void nodeStructureChanged(TreeNode node); + + void nodeChanged(TreeNode node); + + void nodesChanged(TreeNode node, int[] childIndices); + + void nodesWereInserted(N parent, int[] indices); + + void nodeWereInserted(N parentNode, int childIndice, N node); + + void nodesWereRemoved(TreeNode node, int[] childIndices, Object[] removedChildren); + + /** + * Notifies that the {@code node} was inserted. + * + * <b>Note:</b> The method recurses on childs (always notify parent before child) + * + * @param node node inserted + */ + void notifyNodeInserted(N node); + + /** + * Notifies that all childs nodes of {@code node} were + * inserted. + * + * <b>Note:</b> The method recurses on childs (always notify parent before child) + * + * @param node node where all childs where inserted + */ + void notifyChildNodesInserted(N node); + + //-------------------------------------------------------------------------- + //-- TreeModelListener provider + //-------------------------------------------------------------------------- + + void addTreeModelListener(TreeModelListener l); + + void removeTreeModelListener(TreeModelListener l); + + TreeModelListener[] getTreeModelListeners(); + + <T extends EventListener> T[] getListeners(Class<T> listenerType); + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavDataProvider.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavDataProvider.java new file mode 100644 index 0000000..055661a --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavDataProvider.java @@ -0,0 +1,43 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav; + +import org.nuiton.jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; + +/** + * Contract of provider of data. + * + * This object is used by {@link NavNodeChildLoador} to populate childs of node + * and by {@link AbstractNavTreeCellRenderer} to render nodes. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public interface NavDataProvider { + + /** + * @return {@code true} is provider is enabled and can provide datas, + * {@code false} otherwise. + */ + boolean isEnabled(); + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavHelper.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavHelper.java new file mode 100644 index 0000000..ae091ef --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavHelper.java @@ -0,0 +1,960 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav; + +import org.nuiton.jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.event.TreeWillExpandListener; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Tree helper to deal with the build of trees and other usefull operations. + * + * A helper acts as an handler for a {@code tree}. It owns the {@link #getModel()} of + * the {@code #tree}. + * + * <b>Note:</b> A helper can NOT be used to manage multi-trees. + * <h2>Internal states</h2> + * <h3>Internal model</h3> + * To create the model, use method {@link #createModel(NavNode, Object...)} given a + * root node. + * + * To obtain the model, use method {@link #getModel()}. + * + * <b>Note:</b> The helper internal model can be different from the tree model, + * but must be the <b>lowest</b> model, other models must listen nicely this + * model to obtain model modification and selection notifications. + * <h3>Internal tree</h3> + * As said before, a helper matches exactly one tree. + * + * To register the tree, use method {@link #setUI(Object, boolean, TreeSelectionListener)}. + * + * To obtain the tree, use method {@link #getUI()}. + * <h3>Internal data provider</h3> + * To populate childs nodes and render nodes, we use a {@link NavDataProvider}. + * + * To register the data provider, use method {@link #setDataProvider(NavDataProvider)}. + * + * To obtain the data provider, use method {@link #getDataProvider()}. + * <h2>Internal listeners</h2> + * Several listeners are used to manage the auto-loading of nodes in model : + * <h3>{@link #expandListener}</h3> + * This listener will load node's childs before node expands if the node is not loaded. + * + * See the {@link NavNode#isLoaded()} method. + * <h3>{@link #treeModelListener}</h3> + * To listen modification of the model, it will mainly repopulate nodes when + * required. + * + * See the method {@link #populateNode(NavNode, Object[], boolean)}. + * <h3>{@link #selectionListener}</h3> + * To listen modification of the selection, it will mainly expand paths if required. + * + * This is a requirement, since childs of a node should NOT be loaded, so when + * selects a node, always check the path from root to selected node are all fully + * loaded. + * <h2>Model methods</h2> + * The helper offers some methods to modify and query the internal tree model. + * <h3>Model modification</h3> + * <ul> + * <li>{@link #createModel(NavNode, Object...)}</li> + * <li>{@link #insertNode(NavNode, NavNode)}</li> + * <li>{@link #removeNode(NavNode)}</li> + * <li>{@link #moveNode(NavNode, NavNode, int)}</li> + * <li>{@link #refreshNode(NavNode, boolean)}</li> + * <li>{@link #loadAllNodes(NavNode, NavDataProvider)}</li> + * + * </ul> + * <h3>Model selection modification</h3> + * <ul> + * <li>{@link #selectNode(NavNode)}</li> + * <li>{@link #selectNode(String...)}</li> + * <li>{@link #selectParentNode()}</li> + * </ul> + * <h3>Model query</h3> + * <ul> + * <li>{@link #findNode(NavNode, String...)}</li> + * </ul> + * <h3>Child loadors factory</h3> + * The class offers a factory of {@link NavNodeChildLoador}, use the method + * {@link #getChildLoador(Class)} to obtain the correct child loador given his type. + * + * @param <U> Type of ui to bridge + * @author Tony Chemit - chemit@codelutin.com + * @see NavNode + * @see NavNodeChildLoador + * @see AbstractNavTreeCellRenderer + * @since 2.1 + */ +public abstract class NavHelper<M, U, B extends NavBridge<M, N>, N extends NavNode<M, N>> { + + /** Logger */ + static private final Log log = LogFactory.getLog(NavHelper.class); + + //-------------------------------------------------------------------------- + //-- Methods to implement in your helper (related only to ui) + //-------------------------------------------------------------------------- + + public abstract void scrollPathToVisible(TreePath path); + + public abstract void setSelectionPath(TreePath path); + + public abstract void addSelectionPath(TreePath path); + + public abstract void addSelectionPaths(TreePath[] paths); + + public abstract void removeSelectionPath(TreePath path); + + public abstract void removeSelectionPaths(TreePath[] paths); + + public abstract TreeSelectionModel getSelectionModel(); + + public abstract boolean isExpanded(TreePath pathToExpand); + + public abstract void expandPath(TreePath pathToExpand); + + /** + * Register a new root node. + * + * If internal {@link #getModel()} does not exists, creates a new one from + * his given root {@code node}, otherwise just set the new root on the + * existing model. + * + * <b>Note:</b> As a side-effect, the model will be keep in field {@link #getModel()} + * and the {@link #treeModelListener} will be registred on this model. + * + * @param node the root node of the new model + * @param extraArgs extra args to create initial model + * @return the new model + */ + protected abstract M createModel(N node, Object... extraArgs); + + /** + * Obtains the {@link AbstractNavTreeCellRenderer} renderer of the + * registred tree. + * + * @return the renderer of the registred tree or null if no tree was + * registred nor the renderer is a {@link AbstractNavTreeCellRenderer}. + */ + public abstract AbstractNavTreeCellRenderer<M, N> getTreeCellRenderer(); + + /** + * Obtains the selected node of the registred tree. + * + * @return the selected tree or {@code null} if no registred tree nor + * selection empty. + */ + public abstract N getSelectedNode(); + + /** + * Obtains the selected nodes of the registred tree. + * + * @return the selected tree or {@code null} if no registred tree nor + * selection empty. + */ + public abstract List<N> getSelectedNodes(); + + /** + * Registers the given {@code tree} for this helper. + * + * <b>Note:</b> as a side-effect, it will register (if required) the + * {@link #expandListener} listener and (if required) the + * {@link #selectionListener}. + * <b>Note :</b> as a second side-effect, it will register the given {@code willExpandListener} (if not null) + * for the ui and do it <b>BEFORE</b> the {@link #expandListener}. The main + * idea here is to be able to block any expand (or collapse). + * + * @param tree the tree to register + * @param addExpandTreeListener a flag to add expand listener + * @param addOneClickSelectionListener a flag to expend when selection + * @param listener the optional selection listener to add + * @param willExpandListener the optional will expand listener to add <b>BEFORE</b> the default expand tree listener (if he was required) + * @since 2.1.2 + */ + public abstract void setUI(U tree, + boolean addExpandTreeListener, + boolean addOneClickSelectionListener, + TreeSelectionListener listener, + TreeWillExpandListener willExpandListener); + + + /** + * The shared bridge. + * + * A helper deals with only ONE model (this one), becuase we add some + * listeners on it, we prefer always to keep ONE instance (any way this is + * a good thing). + * + * If you want to create a new model, just creates the good root node and + * push it in this model. + * + * For example, if you wrap the shared model with a filter model... Anyway, all + * listeners of this helper apply always of THIs model. + */ + private final B bridge; + + /** the associated ui component */ + private U ui; + + /** The shared data provider used to obtain datas to populate nodes and render them. */ + protected NavDataProvider dataProvider; + + /** + * A {@link TreeWillExpandListener} used to listen when tree should expand. + * + * If so, the listener will load selected node childs if required + * (says when the {@link NavNode#isLoaded()} is sets to {@code false}). + */ + protected TreeWillExpandListener expandListener; + + /** + * pour ouvrir les fils d'un noeud que l'on vient de sélectionner pour + * éviter d'avoir à faire des doubles clics. + */ + protected TreeSelectionListener selectionListener; + + /** + * pour recharger le rendu des noeuds (et charger les fils si nécessaires) + * lors d'une modification dans le modèle de l'arbre. + */ + protected TreeModelListener treeModelListener; + + /** Cache of child loadors. */ + protected static Set<? super NavNodeChildLoador<?, ?, ?, ?, ?>> childLoadors; + + protected static Set<? super NavNodeChildLoador<?, ?, ?, ?, ?>> getChildLoadors() { + if (childLoadors == null) { + childLoadors = new HashSet<NavNodeChildLoador<?, ?, ?, ?, ?>>(); + } + return childLoadors; + } + + /** + * Obtains the {@link NavNodeChildLoador} of the given {@code type} from + * internal cache. + * + * <b>Note:</b> The loador will be instanciated if not found, and push in cache. + * + * @param type the type of loador to get + * @param <L> the type of loador to get + * @return the loador from cache + */ + @SuppressWarnings({"unchecked"}) + public static <L extends NavNodeChildLoador<?, ?, ?, ?, ?>> L getChildLoador(Class<L> type) { + Set<? super NavNodeChildLoador<?, ?, ?, ?, ?>> cache = getChildLoadors(); + NavNodeChildLoador<?, ?, ?, ?, ?> result = null; + for (Object loador : cache) { + if (type.equals(loador.getClass())) { + result = (NavNodeChildLoador<?, ?, ?, ?, ?>) loador; + break; + } + } + if (result == null) { + // add it in cache + try { + result = type.newInstance(); + cache.add(result); + if (log.isDebugEnabled()) { + log.debug("Add " + result + " in loadors cache (new size:" + cache.size() + ")."); + } + } catch (Exception e) { + throw new IllegalArgumentException("Could not instanciate loador [" + type.getName() + "]", e); + } + } + return (L) result; + } + + public NavHelper(B bridge) { + this.bridge = bridge; + + selectionListener = new TreeSelectionListener() { + + @Override + public void valueChanged(TreeSelectionEvent e) { + + if (!checkModel()) { + return; + } + + // Hack, because event.getSource for TreeTable doesnt return selectionModel + TreeSelectionModel source = getSelectionModel(); + + if (source.isSelectionEmpty()) { + + // empty selection + if (log.isDebugEnabled()) { + log.debug("Selection is empty."); + } + return; + } + + boolean debugEnabled = log.isDebugEnabled(); + boolean traceEnabled = log.isTraceEnabled(); + for (TreePath path : e.getPaths()) { + + N node = getNode(path); + if (node == null) { + + // pas de noeud selectionne + if (debugEnabled) { + log.debug("Skip for null node."); + } + continue; + } + + boolean isAdded = e.isAddedPath(path); + + TreePath pathToExpand = new TreePath(NavHelper.this.bridge.getPathToRoot(node)); + boolean pathExpanded = isExpanded(pathToExpand); + + if (traceEnabled || isAdded && debugEnabled) { + log.debug("==== Node selection ===================================="); + log.debug("node ? " + node); + log.debug("is added ? " + isAdded); + log.debug("is path expanded ? " + pathExpanded); + log.debug("is node static ? " + node.isStaticNode()); + log.debug("is node loaded ? " + node.isLoaded()); + log.debug("is node leaf ? " + node.isLeaf()); + log.debug("node nb childs ? " + node.getChildCount()); + } + + if (isAdded && !pathExpanded) { + + // ask to expand path + if (log.isDebugEnabled()) { + log.debug("expand node [" + pathToExpand + "]"); + } + expandPath(pathToExpand); + } + } + } + }; + expandListener = new TreeWillExpandListener() { + @Override + public void treeWillExpand(TreeExpansionEvent event) { + + if (!checkModel()) { + // no model + return; + } + + N source = getNode(event.getPath()); + + if (source.isLoaded()) { + + // node is already loaded, nothing to do + return; + } + + if (log.isDebugEnabled()) { + log.debug("will load childs of node [" + source + "]"); + } + // populate childs of node + source.populateChilds(getBridge(), getDataProvider()); + } + + @Override + public void treeWillCollapse(TreeExpansionEvent event) { + } + }; + + treeModelListener = new TreeModelListener() { + @Override + public void treeNodesInserted(TreeModelEvent e) { + if (!checkModel()) { + // no model + return; + } + N source = getNode(e.getTreePath()); + Object[] children = e.getChildren(); + if (log.isDebugEnabled()) { + log.debug(getMessage("inserted ", source, children)); + } + + // ask to populate children nodes + populateNode(null, children, false); + } + + @SuppressWarnings({"unchecked"}) + @Override + public void treeNodesRemoved(TreeModelEvent e) { + if (!checkModel()) { + // no model + return; + } + N source = getNode(e.getTreePath()); + Object[] children = e.getChildren(); + if (log.isDebugEnabled()) { + log.debug(getMessage("removed ", source, children)); + } + + // Invalidates nodes in renderer cache (if any) + AbstractNavTreeCellRenderer<M, N> renderer = getTreeCellRenderer(); + if (children != null && renderer != null) { + for (Object child : children) { + renderer.invalidateCache((N) child); + } + } + } + + @Override + public void treeNodesChanged(TreeModelEvent e) { + if (!checkModel()) { + // no model + return; + } + + N source = getNode(e.getTreePath()); + Object[] children = e.getChildren(); + if (log.isDebugEnabled()) { + log.debug(getMessage("changed ", source, children)); + } + + // ask to populate modified child nodes + populateNode(null, children, false); + } + + @Override + public void treeStructureChanged(TreeModelEvent e) { + if (!checkModel()) { + // no model + return; + } + N source = getNode(e.getTreePath()); + Object[] children = e.getChildren(); + if (log.isDebugEnabled()) { + log.debug(getMessage("structure changed", source, children)); + } + + // ask to populate structure modified node and nodes recursively + populateNode(source, children, true); + } + + protected String getMessage(String action, N source, Object[] children) { + StringBuilder sb = new StringBuilder(); + sb.append("==== Nodes "); + sb.append(action); + sb.append(" ================="); + sb.append("\nsource : ").append(source); + sb.append("\nnb nodes : "); + sb.append(children == null ? 0 : children.length); + if (children != null) { + int i = 0; + for (Object child : children) { + sb.append("\n ["); + sb.append(i++); + sb.append("] - "); + sb.append(child); + } + } + return sb.toString(); + } + }; + } + + /** + * Obtains the attached data provider used to populate and render nodes. + * + * @return the attached data provider + */ + protected NavDataProvider getDataProvider() { + return dataProvider; + } + + /** + * Obtains the model. + * + * @return the internal tree model or {@code null} if none was created. + */ + public M getModel() { + return bridge.getModel(); + } + + /** + * Obtains the bridge . + * + * @return the internal bridge used by helper. + */ + protected B getBridge() { + return bridge; + } + + /** + * Obtains the ui associated with model in helper. + * + * @return the ui (or {@code null} if no ui attached) + */ + public U getUI() { + return ui; + } + + public N getRootNode() { + if (!checkModel()) { + return null; + } + return bridge.getRoot(); + } + + /** + * Obtains the path of ids fro the root node to the selected node on the + * registred tree. + * + * @return the array of ids from root node to selected node. + */ + public String[] getSelectedIds() { + List<String> result = new ArrayList<String>(); + N selectedNode = getSelectedNode(); + while (selectedNode != null && !selectedNode.isRoot()) { + + result.add(selectedNode.getId()); + selectedNode = selectedNode.getParent(); + } + Collections.reverse(result); + return result.toArray(new String[result.size()]); + } + + /** + * Registers the given {@code tree} for this helper. + * + * <b>Note:</b> as a side-effect, it will register (if required) the + * {@link #expandListener} listener and the {@link #selectionListener}. + * + * @param tree the tree to register + * @param addExpandTreeListener a flag to add expand listener + */ + public void setUI(U tree, + boolean addExpandTreeListener) { + setUI(tree, addExpandTreeListener, null); + } + + /** + * Registers the given {@code tree} for this helper. + * + * <b>Note:</b> as a side-effect, it will register (if required) the + * {@link #expandListener} listener and the {@link #selectionListener}. + * + * @param tree the tree to register + * @param addExpandTreeListener a flag to add expand listener + * @param listener the optional selection listener to add + */ + public void setUI(U tree, + boolean addExpandTreeListener, + TreeSelectionListener listener) { + + setUI(tree, addExpandTreeListener, true, listener); + } + + /** + * Registers the given {@code tree} for this helper. + * + * <b>Note:</b> as a side-effect, it will register (if required) the + * {@link #expandListener} listener and (if required) the + * {@link #selectionListener}. + * + * @param tree the tree to register + * @param addExpandTreeListener a flag to add expand listener + * @param addOneClickSelectionListener a flag to expend when selection + * @param listener the optional selection listener to add + */ + public void setUI(U tree, + boolean addExpandTreeListener, + boolean addOneClickSelectionListener, + TreeSelectionListener listener) { + setUI(tree, + addExpandTreeListener, + addOneClickSelectionListener, + listener, + null + ); + } + + /** + * Registers the {@code dataProvider} for the helper. + * + * <b>Node:</b> As a side-effect, the provider will be propagate to the + * renderer of the registred tree (if any). + * + * @param dataProvider the data provider to use + */ + public void setDataProvider(NavDataProvider dataProvider) { + this.dataProvider = dataProvider; + AbstractNavTreeCellRenderer<M, N> renderer = getTreeCellRenderer(); + if (renderer != null) { + + // dispatch provider to renderer + renderer.setDataProvider(dataProvider); + } + } + + /** + * Inserts the given node to the given {@code parentNode}. + * + * The node will be added to his parent, then creation listeners will be + * fired. + * + * @param parentNode the parent node where to insert the new node * + * @param newNode the node to insert + */ + public void insertNode(N parentNode, N newNode) { + parentNode.add(newNode); + bridge.notifyNodeInserted(newNode); + } + + /** + * Inserts the given node to the given {@code parentNode}. + * + * The node will be added to his parent, then creation listeners will be + * fired. + * + * @param parentNode the parent node where to insert the new node * + * @param newNode the node to insert + * @param position position of node is inserted + */ + public void insertNode(N parentNode, N newNode, int position) { + parentNode.insert(newNode, position); + bridge.notifyNodeInserted(newNode); + } + + /** + * Removes the given {@code node} from the registred tree model and returns + * his parent. + * + * @param node the node to remove + * @return the parent node of the removed node. + */ + public N removeNode(N node) { + N parentNode = node.getParent(); + bridge.removeNodeFromParent(node); + return parentNode; + } + + /** + * Moves the given {@code node} to the new {@code position}. + * + * @param parentNode the parent node + * @param node the node to move + * @param position the new position of the node + */ + public void moveNode(N parentNode, N node, int position) { + parentNode.remove(node); + parentNode.insert(node, position); + bridge.nodeStructureChanged(parentNode); + } + + /** + * Refreshs the given {@code node}. + * + * If flag {@code deep} is set to {@code true}, then it will refresh + * recursively children nodes. + * + * <b>Note:</b>As a side-effect, evvery node involved will become + * {@code dirty}. + * + * @param node the node to refresh + * @param deep un flag pour activer la repainte de la descendance du + * noeud + * @see NavNode#isDirty() + */ + @SuppressWarnings({"unchecked"}) + public void refreshNode(N node, boolean deep) { + if (log.isDebugEnabled()) { + log.debug("Will refresh (deep ? " + deep + ") node " + node); + } + bridge.nodeChanged(node); + if (deep) { + // repaint childs nodes + Enumeration<N> e = node.children(); + while (e.hasMoreElements()) { + N child = e.nextElement(); + refreshNode(child, true); + } + } + } + + /** + * To load all nodes of a model. + * + * @param node the root node to load + * @param dataProvider the data provider used to populate nodes + */ + @SuppressWarnings({"unchecked"}) + public void loadAllNodes(N node, NavDataProvider dataProvider) { + if (!checkModel()) { + return; + } + if (!node.isLoaded()) { + node.populateChilds(getBridge(), dataProvider); + Enumeration<? extends NavNode<?, ?>> enumeration = node.children(); + while (enumeration.hasMoreElements()) { + N jaxxNode = (N) enumeration.nextElement(); + loadAllNodes(jaxxNode, dataProvider); + } + } + } + + /** + * Selects the parent of the currently selected node. + * + * <b>Note:</b> If selection is empty, then throws a NPE. + * + * @throws NullPointerException if selection is empty + */ + public void selectParentNode() throws NullPointerException { + + N node = getSelectedNode(); + + if (node == null) { + // pas de noeud selectionne + throw new NullPointerException("no selected node in context"); + } + node = node.getParent(); + + selectNode(node); + } + + /** + * Selects the given {@code node} in the registred tree. + * + * @param node the node to select + */ + public void selectNode(N node) { + if (!checkModel()) { + + // no model + return; + } + if (log.isDebugEnabled()) { + log.debug("try to select node [" + node + "]"); + } + TreePath path = new TreePath(bridge.getPathToRoot(node)); + + addSelectionPath(path); + scrollPathToVisible(path); + } + + /** + * Selects the given {@code nodes} in the registred tree. + * + * @param nodes the nodes to select + */ + public void selectNodes(List<N> nodes) { + if (!checkModel()) { + + // no model + return; + } + List<TreePath> paths = new ArrayList<TreePath>(); + for (N node : nodes) { + paths.add(new TreePath(bridge.getPathToRoot(node))); + } + addSelectionPaths(paths.toArray(new TreePath[paths.size()])); + } + + /** + * Unselects the given {@code node} in the registred tree. + * + * @param node the node to select + */ + public void unSelectNode(N node) { + if (!checkModel()) { + + // no model + return; + } + if (log.isDebugEnabled()) { + log.debug("try to select node [" + node + "]"); + } + TreePath path = new TreePath(bridge.getPathToRoot(node)); + + removeSelectionPath(path); + } + + /** + * Selects the given {@code nodes} in the registred tree. + * + * @param nodes the nodes to select + */ + public void unSelectNodes(List<N> nodes) { + if (!checkModel()) { + + // no model + return; + } + for (N node : nodes) { + unSelectNode(node); + } + } + + /** + * Selects the node described by his given {@code path} of ids. + * + * @param path the absolute path of ids from root node to node to select. + */ + public void selectNode(String... path) { + if (!checkModel()) { + + // no model + return; + } + if (log.isDebugEnabled()) { + log.debug("try to select node from ids " + Arrays.toString(path)); + } + N root = bridge.getRoot(); + N node = findNode(root, path); + if (log.isDebugEnabled()) { + log.debug("selected node [" + node + "]"); + } + if (node != null) { + selectNode(node); + } + } + + /** + * Finds a node from the given root {@code node}, applying the path given + * by {@code ids}. + * + * @param node the starting node + * @param ids the path of ids to apply on the node. + * @return the find node or {@code null} if no node matchs. + */ + public N findNode(N node, String... ids) { + if (!checkModel()) { + + // no model + return null; + } + N result = null; + for (String id : ids) { + + result = node.findNodeById(id, getBridge(), getDataProvider()); + + if (result == null) { + + // un des noeud n'a pas ete trouve, on sort + break; + } + node = result; + } + return result; + } + + /** + * Finds a node from the given root {@code node}, and return child searched + * + * @param node the starting node + * @param id id of searched child + * @return the find node or {@code null} if no node matchs. + */ + public N getChild(N node, String id) { + if (!checkModel()) { + + // no model + return null; + } + + return node.getChild(id, getBridge(), getDataProvider()); + } + + /** + * Checks if internal model was created. + * + * @return {@code true} if model was created, {@code false} otherwise. + */ + protected boolean checkModel() { + if (getModel() == null) { + + // no model set, + if (log.isWarnEnabled()) { + log.warn("No model set in " + this); + } + return false; + } + // model is set + return true; + } + + /** + * Populates nodes. + * + * If {@code node} is not {@code null}, then populate it. + * + * If {@code children} is not {@code null}, then populate them, moreover + * if {@code recurse} is set to {@code true} then do a recurse refresh on + * children. + * + * @param node the parent node to populate (optional) + * @param children the child nodes to populate (optional) + * @param recurse flag sets to {@code true} if should do recurse refresh on + * given {@code children} nodes. + */ + @SuppressWarnings({"unchecked"}) + protected void populateNode(N node, + Object[] children, + boolean recurse) { + NavDataProvider dataProvider = getDataProvider(); + if (node != null) { + if (log.isDebugEnabled()) { + log.debug("Will populate node : " + node); + } + node.populateNode(getBridge(), dataProvider, false); + } + if (children != null) { + for (Object o : children) { + N child = (N) o; + if (log.isDebugEnabled()) { + log.debug("Will populate child node : " + child); + } + child.populateNode(getBridge(), dataProvider, recurse); + } + } + } + + /** + * Convinient method to objet the casted node of a {@link TreePath}. + * + * @param path the path contaning the node. + * @return the casted node from the path. + */ + @SuppressWarnings({"unchecked"}) + protected N getNode(TreePath path) { + return (N) path.getLastPathComponent(); + } + + protected void setUI(U ui) { + this.ui = ui; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavNode.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavNode.java new file mode 100644 index 0000000..523bb0e --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavNode.java @@ -0,0 +1,220 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav; + +import org.nuiton.jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; + +import javax.swing.tree.TreeNode; +import java.io.Serializable; + +/** + * Definition of a node with a optional {@code childLoador} to build childs of + * node. + * + * A node is identified by an {@link #getId} of an associated data of type + * {@link #getInternalClass}. + * + * <b>Note:</b> + * <p><i> While using a {@code childLoador}, we can not know before node + * was loaded the exact count of his childs. As a matter of facts, real leaf + * nodes appears at the beginning in ui as a not leaf (there is a root handler). + * When node was loaded, a leaf node will be then displayed as required. + * </i></p> + * + * <h2>Why NavNode is generic ?</h2> + * In a project, you should implements your own Node extending with one like this : + * <pre> + * class MyNode extends NavNode<MyNode> { ... } + * </pre> + * While in this class, you overrides every method with a node return type, + * co-variance you'll be able to use this code : + * <pre> + * MyNode parentNode = new MyNode(); + * MyNode node = parentNode.getFirstNode(); + * </pre> + * So for final application this generic type avoid any cast for your own node + * type, this is quite convinient. + * + * Even if in your project, you wants to have a heriarchy of nodes, this will + * still works (if you use a genercic type on your abstract nodes). + * <h2>Internal states</h2> + * <ul> + * <li><b>internalClass</b> : the type of data associated with the node</li> + * <li><b>context</b> : an optinal context to distinguish different types of + * node with same {@code internalclass}</li> + * <li><b>id</b> : id of the data associated with the node</li> + * <li><b>dirty</b> : flag sets to {@code true} when node render MUST be recomputed</li> + * <li><b>loaded</b> : flag sets to {@code true} when node was loaded</li> + * <li><b>childLoador</b> : optional loador of childs</li> + * </ul> + * <h2>Static nodes</h2> + * Some nodes do not need auto-loading, we call them {@code static nodes}. + * The method {@link #isStaticNode()} gives this state. + * + * <b>Note:</b> A static node has no {@code childLoador}. + * <h2>Node loading</h2> + * Initialy node has no data child nodes, ({@link #isLoaded()} equals + * {@code false}). + * when model requires node's childs, it can load them via method + * {@link #populateNode(NavBridge, NavDataProvider, boolean)} + * and {@link #populateChilds(NavBridge, NavDataProvider)} methods. + * <h2>Node rendering</h2> + * the {@link AbstractNavTreeCellRenderer} looks the {@link #isDirty} state to + * know when render should be (re-)compute and set back the state to {@code false}. + * + * Each time, a node is modified, the {@link #isDirty} should be set to {@code true}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public interface NavNode<M, N extends NavNode<M, N>> extends Cloneable, TreeNode, Serializable { + + String getId(); + + String getContext(); + + Class<?> getInternalClass(); + + boolean isLoaded(); + + boolean isDirty(); + + /** + * Convinient method to known if the node is a {@code String} typed. + * + * @return {@code true} if the type of node if + */ + boolean isStringNode(); + + /** + * To know if the node is static. + * + * A {@code static} node has no {@code childLoador}. + * + * @return {@code true} when the node is static : says, the node has + * no {@code childLoador}. + */ + boolean isStaticNode(); + + /** + * Gets the first node form this one to the root which has a none + * {@code String} type. + * + * @return the first concrete node type + */ + N getContainerNode(); + + /** + * Given an {@code id}, obtain the child with matching id. + * + * If node is NOT {@code loaded}, then first loads it (method + * {@link #populateChilds(NavBridge, NavDataProvider)}) then do search + * on direct childs of the node recursivly. + * + * @param id the id of the researched node + * @param bridge model owner of nodes + * @param provider data provider + * @return the found node or {@code null} if not found + */ + N findNodeById(String id, + NavBridge<M, N> bridge, + NavDataProvider provider); + + /** + * Given an {@code id}, obtain the child with matching id. + * + * If node is NOT {@code loaded}, then first loads it (method + * {@link #populateChilds(NavBridge, NavDataProvider)}) then return + * on direct childs of the node. + * + * @param id the id of the researched node + * @param bridge model owner of nodes + * @param provider data provider + * @return the found node or {@code null} if not found + */ + N getChild(String id, + NavBridge<M, N> bridge, + NavDataProvider provider); + + /** + * Changes the {@link #isDirty} state. + * + * As a side effect, when a renderer will use this node, it will force to + * reload the render from the {@link NavDataProvider}. + * + * @param dirty the new dirty value + */ + void setDirty(boolean dirty); + + @Override + boolean isLeaf(); + + Object getUserObject(); + + @Override + String toString(); + + //-------------------------------------------------------------------------- + //-- Populate methods + //-------------------------------------------------------------------------- + + /** + * To populate the node. A side-effect of this method is to set {@code dirty} + * the node (renderer will recompute the render of the node). + * + * If {@code populateChilds} is set to {@code true}, then also populate + * childs of the node using the given {@code dataProvider}. + * + * @param bridge le delegate modèles content le noeud + * @param provider le provider de données + * @param populateChilds un drapeau pour charger aussi les fils du noeud courant + */ + void populateNode(NavBridge<M, N> bridge, + NavDataProvider provider, + boolean populateChilds); + + /** + * To populate childs of the node (only when a none static node). + * A side-effect of this method is to set {@code loaded} of the node. + * + * For a static node, do nothing. + * + * @param bridge model owner of the node + * @param provider data provider + */ + void populateChilds(NavBridge<M, N> bridge, NavDataProvider provider); + + //-------------------------------------------------------------------------- + //-- Overrides to use generic type as return + //-------------------------------------------------------------------------- + + boolean isRoot(); + + @Override + N getParent(); + + void add(N node); + + void remove(N node); + + void insert(N node, int position); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavNodeChildLoador.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavNodeChildLoador.java new file mode 100644 index 0000000..09c56f1 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/NavNodeChildLoador.java @@ -0,0 +1,167 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.Serializable; +import java.util.List; + +/** + * Object to load childs of a node. + * + * It uses {@link NavDataProvider} in method + * {@link #loadChilds(NavBridge, NavNode, NavDataProvider)} to obtain datas + * then build childs nodes. + * + * A factory of such objects can be found in {@link NavHelper} to make + * them reusable in other places than inside a {@link NavNode} to auto-load + * childs. + * + * For example when you want to creat by hand a new node, always prefer to reuse + * a such object rathen than duplicate same code in helper... + * + * @param <T> type of data used to create nodes (can be just a String type to use only ids) + * @param <O> type of data associated with nodes + * @param <N> type of node to used (to make possible full co-variance and no cast in fal implementations). + * @author Tony Chemit - chemit@codelutin.com + * @see NavHelper + * @see NavNode + * @since 2.1 + */ +public abstract class NavNodeChildLoador<T, O, M, B extends NavBridge<M, N>, N extends NavNode<M, N>> implements Serializable { + + /** Logger. */ + static private final Log log = LogFactory.getLog(NavNodeChildLoador.class); + + private static final long serialVersionUID = 1L; + + /** Type of data of the node */ + protected final Class<O> beanType; + + protected NavNodeChildLoador(Class<O> beanType) { + this.beanType = beanType; + } + + /** + * Obtain the list of data used to create nodes. + * + * If type {@code T} is {@code O}, we directly use the data associated with nodes. + * + * @param parentClass type of parent + * @param parentId id of parent + * @param dataProvider the data provider + * @return the list of data + * @throws Exception if any problem + */ + public abstract List<T> getData(Class<?> parentClass, + String parentId, + NavDataProvider dataProvider) throws Exception; + + /** + * Hook to create a child node given his {@code data}. + * + * @param data the data of the node to create + * @param dataProvider the data provider + * @return the created node + */ + public abstract N createNode(T data, NavDataProvider dataProvider); + + /** + * Returns the type of data associated with nodes to create. + * + * @return the type of data associated with created nodes. + */ + public Class<O> getBeanType() { + return beanType; + } + + /** + * Load childs of the given {@code parentnode}. + * + * @param bridge the model owner of nodes + * @param parentNode the parent node where to insert nodes + * @param dataProvider data provider + * @throws Exception pour tout probleme de recuperation de donnees + */ + public void loadChilds(B bridge, + N parentNode, + NavDataProvider dataProvider) throws Exception { + + N containerNode = parentNode.getContainerNode(); + + List<T> datas; + if (containerNode == null) { + + // pas d'ancetre, il doit s'agir d'un premier noeud de données + // depuis le noeud root + + // recuperation des objets fils (sans connaitre de parent) + datas = getData(null, null, dataProvider); + + } else { + if (log.isDebugEnabled()) { + log.debug("search data for " + containerNode.getInternalClass() + + " : " + containerNode.getId()); + } + + // recuperation des objets fils + datas = getData(containerNode.getInternalClass(), + containerNode.getId(), + dataProvider); + } + + // on charge les fils + addChildNodes(parentNode, datas, dataProvider); + + // notifie le modele d'un ajout de noeuds + bridge.notifyChildNodesInserted(parentNode); + } + + /** + * Add childs to given {@code parentNode} using retrive {@code datas} from + * the data provider. + * + * This method is invoked by the {@link #loadChilds(NavBridge, NavNode, NavDataProvider)}. + * + * @param parentNode the node where to insert + * @param datas the data used to create node + * @param dataProvider the data provider + */ + protected void addChildNodes(N parentNode, + List<T> datas, + NavDataProvider dataProvider) { + + // creation des noeuds fils + if (datas != null) { + for (T o : datas) { + if (log.isDebugEnabled()) { + log.debug("[" + parentNode + "] Will add child node for " + o); + } + N node = createNode(o, dataProvider); + parentNode.add(node); + } + } + } + +} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/package.html b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/package.html similarity index 100% rename from jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/package.html rename to jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/package.html diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/AbstractNavTreeCellRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/AbstractNavTreeCellRenderer.java new file mode 100644 index 0000000..7b20f49 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/AbstractNavTreeCellRenderer.java @@ -0,0 +1,125 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav.tree; + +import org.nuiton.jaxx.runtime.swing.nav.NavDataProvider; +import org.nuiton.jaxx.runtime.swing.nav.NavNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.tree.DefaultTreeCellRenderer; +import java.util.HashMap; +import java.util.Map; + +import static org.nuiton.i18n.I18n.t; + +/** + * Le renderer abstrait (qui a toutes les methodes qui aident) pour implanter de + * vrai renderer pour les différents cas d'utilisation de l'abre de navigation. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.2 + */ +public abstract class AbstractNavTreeCellRenderer<M, N extends NavNode<M, N>> extends DefaultTreeCellRenderer { + + /** Logger */ + protected static final Log log = + LogFactory.getLog(AbstractNavTreeCellRenderer.class); + + /** source de donnée */ + protected NavDataProvider dataProvider; + + /** le cache de rendu */ + protected final Map<N, String> renderCache = new HashMap<N, String>(); + + /** + * Determines the text render of a node using the {@link #dataProvider}. + * + * @param node the node to render + * @return the text render of the node + */ + protected abstract String computeNodeText(N node); + + protected AbstractNavTreeCellRenderer() { + } + + public NavDataProvider getDataProvider() { + return dataProvider; + } + + public void setDataProvider(NavDataProvider dataProvider) { + this.dataProvider = dataProvider; + + // une nouvelle source utilisée, on vide le cache + clearCache(); + } + + public void clearCache() { + renderCache.clear(); + } + + public void invalidateCache(N node) { + renderCache.remove(node); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + clearCache(); + } + + public String getNodeText(N node) { + if (node == null) { + return null; + } + String text; + + if (node.isDirty() || !renderCache.containsKey(node)) { + + // calculer le rendu du noeud + if (node.isStringNode()) { + text = t(node.getId()); + + } else { + + text = computeNodeText(node); + } + + if (log.isDebugEnabled()) { + log.debug("text for node [" + node + "] = <" + text + ">"); + } + + // sauvegarde dans le cache + renderCache.put(node, text); + + // le noeud est de nouveau propre + node.setDirty(false); + + } else { + + // recupération directement du rendu dans le cache + text = renderCache.get(node); + } + + return text; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/NavTreeBridge.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/NavTreeBridge.java new file mode 100644 index 0000000..3727d56 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/NavTreeBridge.java @@ -0,0 +1,237 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav.tree; + +import org.nuiton.jaxx.runtime.swing.nav.NavBridge; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.event.TreeModelListener; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import java.util.Enumeration; +import java.util.EventListener; + +/** + * Delegate model used to switch between tree model and tree table model api + * + * @author Sylvain Lletellier + * @since 2.1 + */ +public class NavTreeBridge<N extends NavTreeNode<N>> implements NavBridge<DefaultTreeModel, N> { + + /** Logger */ + static private final Log log = LogFactory.getLog(NavTreeBridge.class); + + /** bridge model */ + protected DefaultTreeModel model; + + /** bridge ui */ +// protected JTree ui; +// public NavTreeBridge() { +// } + + //-------------------------------------------------------------------------- + //-- Model Queries + //-------------------------------------------------------------------------- + @Override + public DefaultTreeModel getModel() { + return model; + } + + @Override + @SuppressWarnings({"unchecked"}) + public N getRoot() { + return (N) model.getRoot(); + } + + @Override + public boolean isLeaf(Object node) { + return model.isLeaf(node); + } + + @Override + public int getChildCount(Object parent) { + return model.getChildCount(parent); + } + + @Override + @SuppressWarnings({"unchecked"}) + public N getChild(Object parent, int index) { + return (N) model.getChild(parent, index); + } + + @Override + public int getIndexOfChild(Object parent, Object child) { + return model.getIndexOfChild(parent, child); + } + + @Override + public TreeNode[] getPathToRoot(TreeNode aNode) { + return model.getPathToRoot(aNode); + } + + //-------------------------------------------------------------------------- + //-- Model modification + //-------------------------------------------------------------------------- + + @Override + public void setModel(DefaultTreeModel model) { + this.model = model; + } + + @Override + public void setRoot(N node) { + model.setRoot(node); + } + + @Override + public void insertNodeInto(N newChild, N parent, int index) { + model.insertNodeInto(newChild, parent, index); + } + + @Override + public void removeNodeFromParent(N node) { + model.removeNodeFromParent(node); + } + + @Override + public void reload(N node) { + model.reload(); + } + + @Override + public boolean canLoadChild(N node) { + return true; + } + + //-------------------------------------------------------------------------- + //-- Model Listeners notifications + //-------------------------------------------------------------------------- + + @Override + public void valueForPathChanged(TreePath path, Object newValue) { + model.valueForPathChanged(path, newValue); + } + + @Override + public void nodesWereInserted(N parent, int[] indices) { + model.nodesWereInserted(parent, indices); + } + + @Override + public void nodeWereInserted(N parentNode, int childIndice, N node) { + int[] indices = new int[1]; + indices[0] = childIndice; + model.nodesWereInserted(parentNode, indices); + } + + @Override + public void nodeChanged(TreeNode node) { + model.nodeChanged(node); + } + + @Override + public void nodeStructureChanged(TreeNode node) { + model.nodeStructureChanged(node); + } + + @Override + public void nodesWereRemoved(TreeNode node, int[] childIndices, + Object[] removedChildren) { + model.nodesWereRemoved(node, childIndices, removedChildren); + } + + @Override + public void nodesChanged(TreeNode node, int[] childIndices) { + model.nodesChanged(node, childIndices); + } + + @Override + @SuppressWarnings({"unchecked"}) + public void notifyChildNodesInserted(N node) { + int count = node.getChildCount(); + if (count < 1) { + if (log.isDebugEnabled()) { + log.debug("Skip for leaf node : " + node); + } + return; + } + if (log.isDebugEnabled()) { + log.debug("Notify for node : " + node + ", " + count + " child(s) inserted."); + } + int[] indices = new int[count]; + for (int i = 0; i < count; i++) { + indices[i] = i; + } + + nodesWereInserted(node, indices); + + // recurse notify on childs + for (Enumeration<? extends NavTreeNode<?>> childs = node.children(); + childs.hasMoreElements(); ) { + N child = (N) childs.nextElement(); + notifyChildNodesInserted(child); + } + } + + @Override + public void notifyNodeInserted(N node) { + + N parent = node.getParent(); + if (parent != null) { + int indice = parent.getIndex(node); + if (log.isDebugEnabled()) { + log.debug("Notify for node : " + node + ", for parent [" + parent + "] child " + indice + " inserted."); + } + nodesWereInserted(parent, new int[]{indice}); + notifyChildNodesInserted(node); + } + } + + //-------------------------------------------------------------------------- + //-- TreeModelListener provider + //-------------------------------------------------------------------------- + + @Override + public void addTreeModelListener(TreeModelListener l) { + model.addTreeModelListener(l); + } + + @Override + public void removeTreeModelListener(TreeModelListener l) { + model.removeTreeModelListener(l); + } + + @Override + public TreeModelListener[] getTreeModelListeners() { + return model.getTreeModelListeners(); + } + + @Override + @SuppressWarnings({"unchecked"}) + public <T extends EventListener> T[] getListeners(Class<T> listenerType) { + return model.getListeners(listenerType); + } + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/NavTreeHelper.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/NavTreeHelper.java new file mode 100644 index 0000000..cb38c9e --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/NavTreeHelper.java @@ -0,0 +1,182 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav.tree; + +import org.nuiton.jaxx.runtime.swing.nav.NavHelper; + +import javax.swing.JTree; +import javax.swing.event.TreeSelectionListener; +import javax.swing.event.TreeWillExpandListener; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.util.ArrayList; +import java.util.List; + +/** + * The implementation of {@link NavHelper} base on a {@link JTree} component. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public class NavTreeHelper<N extends NavTreeNode<N>> extends NavHelper<DefaultTreeModel, JTree, NavTreeBridge<N>, N> { + + public NavTreeHelper() { + this(new NavTreeBridge<N>()); + } + + public NavTreeHelper(NavTreeBridge<N> bridge) { + super(bridge); + } + + @Override + public void scrollPathToVisible(TreePath path) { + getUI().scrollPathToVisible(path); + } + + @Override + public void setSelectionPath(TreePath path) { + getUI().setSelectionPath(path); + } + + @Override + public void addSelectionPaths(TreePath[] paths) { + getUI().addSelectionPaths(paths); + } + + @Override + public void addSelectionPath(TreePath path) { + getUI().addSelectionPath(path); + } + + @Override + public void removeSelectionPaths(TreePath[] path) { + getUI().removeSelectionPaths(path); + } + + @Override + public void removeSelectionPath(TreePath path) { + getUI().removeSelectionPath(path); + } + + @Override + public TreeSelectionModel getSelectionModel() { + return getUI().getSelectionModel(); + } + + @Override + public boolean isExpanded(TreePath pathToExpand) { + return getUI().isExpanded(pathToExpand); + } + + @Override + public void expandPath(TreePath pathToExpand) { + getUI().expandPath(pathToExpand); + } + + @SuppressWarnings({"unchecked"}) + @Override + public AbstractNavTreeCellRenderer<DefaultTreeModel, N> getTreeCellRenderer() { + JTree t = getUI(); + if (t == null) { + return null; + } + TreeCellRenderer r = t.getCellRenderer(); + if (r instanceof AbstractNavTreeCellRenderer) { + return (AbstractNavTreeCellRenderer<DefaultTreeModel, N>) r; + } + return null; + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getSelectedNode() { + JTree tree = getUI(); + if (tree == null) { + return null; + } + TreePath path = tree.getSelectionPath(); + N node = null; + if (path != null) { + node = (N) path.getLastPathComponent(); + } + return node; + } + + @SuppressWarnings({"unchecked"}) + @Override + public List<N> getSelectedNodes() { + JTree tree = getUI(); + if (tree == null) { + return null; + } + TreePath[] paths = tree.getSelectionPaths(); + List<N> nodes = new ArrayList<N>(); + if (paths != null) { + for (TreePath path : paths) { + if (path != null) { + nodes.add((N) path.getLastPathComponent()); + } + } + } + return nodes; + } + + @Override + public void setUI(JTree tree, + boolean addExpandTreeListener, + boolean addOneClickSelectionListener, + TreeSelectionListener listener, + TreeWillExpandListener willExpandListener) { + setUI(tree); + if (willExpandListener != null) { + tree.addTreeWillExpandListener(willExpandListener); + } + if (addExpandTreeListener) { + tree.addTreeWillExpandListener(expandListener); + } + if (listener != null) { + tree.addTreeSelectionListener(listener); + } + if (addOneClickSelectionListener) { + tree.addTreeSelectionListener(selectionListener); + } + } + + @Override + protected DefaultTreeModel createModel(N node, Object... extraArgs) { + NavTreeBridge<N> bridge = getBridge(); + DefaultTreeModel model = bridge.getModel(); + if (model == null) { + model = new DefaultTreeModel(node); + bridge.setModel(model); + bridge.addTreeModelListener(treeModelListener); + } else { + bridge.setRoot(node); + } + + // notify structure has changed + bridge.nodeStructureChanged(getRootNode()); + return model; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/NavTreeNode.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/NavTreeNode.java new file mode 100644 index 0000000..7f1911f --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/NavTreeNode.java @@ -0,0 +1,425 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav.tree; + +import org.nuiton.jaxx.runtime.swing.nav.NavBridge; +import org.nuiton.jaxx.runtime.swing.nav.NavDataProvider; +import org.nuiton.jaxx.runtime.swing.nav.NavNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import java.util.Enumeration; + +/** + * Implementation of {@link NavNode} used to create in tree table + * This node extends {@link DefaultMutableTreeNode} + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.2 + */ +public class NavTreeNode<N extends NavTreeNode<N>> extends DefaultMutableTreeNode implements NavNode<DefaultTreeModel, N> { + + /** Logger */ + static private final Log log = LogFactory.getLog(NavNode.class); + + private static final long serialVersionUID = 1L; + + /** Type of data associated with the node */ + protected final Class<?> internalClass; + + /** + * Optinal context to distinguish different nodes with same + * {@link #internalClass}. + */ + protected final String context; + + /** Id of the data associated with the node. */ + protected final String id; + + /** Flag to know when renderer should (re-)compute render of the node. */ + protected boolean dirty = true; + + /** Flag to know when the none static node was loaded. */ + protected boolean loaded; + + /** Optional child loador to lazy create childs of the node. */ + protected final NavTreeNodeChildLoador<?, ?, N> childLoador; + + protected NavTreeNode(String id) { + this(String.class, id, null, null); + } + + public NavTreeNode(Class<?> internalClass, + String id, + String context, + NavTreeNodeChildLoador<?, ?, N> childLoador) { + this.internalClass = internalClass; + this.id = id; + this.context = context; + this.childLoador = childLoador; + if (isStaticNode()) { + + // A static node is always full loaded + loaded = true; + } + if (log.isDebugEnabled()) { + log.debug("new node : " + this); + } + } + + @Override + public String getId() { + return id; + } + + @Override + public String getContext() { + return context; + } + + @Override + public Class<?> getInternalClass() { + return internalClass; + } + + @Override + public boolean isLoaded() { + return loaded; + } + + @Override + public boolean isDirty() { + return dirty; + } + + @Override + public boolean isStringNode() { + return String.class.equals(internalClass); + } + + @Override + public boolean isStaticNode() { + return childLoador == null; + } + + @Override + @SuppressWarnings({"unchecked"}) + public N getContainerNode() { + if (isRoot()) { + // si on arrive sur le root, quelque chose ne va pas, + // on bloque par null, a defaut de declancher une exception + return null; + } + + if (isStringNode()) { + // on est sur un noeud de type String, donc on regarde sur le parent + return getParent().getContainerNode(); + } + + // cas final : sur un noeud de donnee + classe interne de donnee + return (N) this; + } + + @Override + @SuppressWarnings({"unchecked"}) + public N findNodeById(String id, + NavBridge<DefaultTreeModel, N> model, + NavDataProvider provider) { + if (id == null) { + + // id null ? donc rien a faire + return null; + } + if (id.equals(getId())) { + + // on a trouve le bon noeud + return (N) this; + } + + if (!isLoaded()) { + + // il faut charger les fils du noeud pour effectuer la recherche + populateChilds(model, provider); + } + + if (isLeaf()) { + + // au final le noeud est une feuille, donc ne convient pas + return null; + } + + // on recherche dans les fils + Enumeration<N> enumeration = children(); + while (enumeration.hasMoreElements()) { + N node = enumeration.nextElement(); + N nodeById = node.findNodeById(id, model, provider); + if (nodeById != null) { + return nodeById; + } + } + + // aucun des noeud fils ne convient + return null; + } + + @Override + public N getChild(String id, + NavBridge<DefaultTreeModel, N> bridge, + NavDataProvider provider) { + + if (id == null) { + + // id null ? donc rien a faire + return null; + } + + if (!isLoaded()) { + + // il faut charger les fils du noeud pour effectuer la recherche + populateChilds(bridge, provider); + } + + if (isLeaf()) { + + // au final le noeud est une feuille, donc ne convient pas + return null; + } + + // on recherche dans les fils + Enumeration<N> enumeration = children(); + while (enumeration.hasMoreElements()) { + N child = enumeration.nextElement(); + if (id.equals(child.getId())) { + return child; + } + } + + // aucun des noeud fils ne convient + return null; + } + + @Override + public void setDirty(boolean dirty) { + this.dirty = dirty; + } + + @Override + public boolean isLeaf() { + // there is two behaviours for the test : + // 1 - when the node is static, then can directly use his number of child + // to determine if node is a leaf (no child) + // 2 - when the node is dynamic, then ALWAYS says the node is NOT a leaf until + // it was loaded, otherwise the WillExpand listener will not load the childs... + // Once the node is loaded, use back the normal behaviour (count number of childs) + return isStaticNode() ? super.isLeaf() : isLoaded() && getChildCount() == 0; + } + + @Override + public Object getUserObject() { + return id; + } + + @Override + public String toString() { + return System.identityHashCode(this) + "-" + id; + } + + //-------------------------------------------------------------------------- + //-- Populate methods + //-------------------------------------------------------------------------- + + @Override + public void populateNode(NavBridge<DefaultTreeModel, N> model, + NavDataProvider provider, + boolean populateChilds) { + + // on indique que le noeud n'est plus propre + setDirty(true); + + if (populateChilds) { + + // chargement des fils + populateChilds(model, provider); + } + } + + @Override + @SuppressWarnings({"unchecked"}) + public void populateChilds(NavBridge<DefaultTreeModel, N> bridge, + NavDataProvider provider) { + if (isStaticNode()) { + + if (log.isDebugEnabled()) { + log.debug("is static node " + this); + } + + // noeud static, rien a faire + return; + } + + if (!bridge.canLoadChild((N) this)) { + + // can not load childs + if (log.isDebugEnabled()) { + log.debug("Will Skip populateChilds for node : " + this); + } + return; + } + + // chargement des noeuds fils du noeud courant + try { + if (log.isDebugEnabled()) { + log.debug("Will load childs for " + this); + } + childLoador.loadChilds((NavTreeBridge<N>) bridge, (N) this, provider); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } finally { + + // au final, on passe le noeud a l'état chargé + loaded = true; + } + } + + //-------------------------------------------------------------------------- + //-- Overrides to use generic type as return + //-------------------------------------------------------------------------- + + @SuppressWarnings({"unchecked"}) + @Override + public N getParent() { + return (N) super.getParent(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getRoot() { + return (N) super.getRoot(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getFirstChild() { + return (N) super.getFirstChild(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getLastChild() { + return (N) super.getLastChild(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getChildAfter(TreeNode aChild) { + return (N) super.getChildAfter(aChild); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getChildBefore(TreeNode aChild) { + return (N) super.getChildBefore(aChild); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getNextSibling() { + return (N) super.getNextSibling(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getPreviousSibling() { + return (N) super.getPreviousSibling(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getFirstLeaf() { + return (N) super.getFirstLeaf(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getLastLeaf() { + return (N) super.getLastLeaf(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getNextLeaf() { + return (N) super.getNextLeaf(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getPreviousLeaf() { + return (N) super.getPreviousLeaf(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getNextNode() { + return (N) super.getNextNode(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getPreviousNode() { + return (N) super.getPreviousNode(); + } + + @SuppressWarnings({"unchecked"}) + public N getSharedAncestor(N aNode) { + return (N) getSharedAncestor((DefaultMutableTreeNode) aNode); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getChildAt(int index) { + return (N) super.getChildAt(index); + } + + @SuppressWarnings({"unchecked"}) + @Override + public Enumeration<N> children() { + return (Enumeration<N>) super.children(); + } + + @Override + public void add(N node) { + super.add(node); + } + + @Override + public void remove(N node) { + super.remove(node); + } + + @Override + public void insert(N node, int position) { + super.insert(node, position); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/NavTreeNodeChildLoador.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/NavTreeNodeChildLoador.java new file mode 100644 index 0000000..8f62fb6 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/NavTreeNodeChildLoador.java @@ -0,0 +1,41 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav.tree; + +import org.nuiton.jaxx.runtime.swing.nav.NavNodeChildLoador; + +import javax.swing.tree.DefaultTreeModel; + +/** + * Implementation for tree of {@link NavNodeChildLoador} + * + * @author Sylvain Lletellier + * @since 2.2 + */ +public abstract class NavTreeNodeChildLoador<T, O, N extends NavTreeNode<N>> extends NavNodeChildLoador<T, O, DefaultTreeModel, NavTreeBridge<N>, N> { + + private static final long serialVersionUID = 1L; + + protected NavTreeNodeChildLoador(Class<O> beanType) { + super(beanType); + } +} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/package.html b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/package.html similarity index 100% rename from jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/package.html rename to jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/tree/package.html diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableBridge.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableBridge.java new file mode 100644 index 0000000..c7ba09b --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableBridge.java @@ -0,0 +1,294 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav.treetable; + +import org.nuiton.jaxx.runtime.swing.nav.NavBridge; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.treetable.TreeTableNode; + +import javax.swing.event.TreeModelListener; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.List; + +/** + * Delegate model used to switch between tree model and tree table model api + * + * @author Sylvain Lletellier + * @since 2.1 + */ +public class NavTreeTableBridge<N extends NavTreeTableNode<N>> implements NavBridge<NavTreeTableModel, N> { + + /** Logger */ + static private final Log log = LogFactory.getLog(NavTreeTableBridge.class); + + /** bridge model */ + protected NavTreeTableModel model; + + /** bridge ui */ +// protected JXTreeTable ui; + +// public NavTreeTableBridge() { +// if (log.isDebugEnabled()) { +// log.debug("New " + this); +// } +// } + + //-------------------------------------------------------------------------- + //-- Model Queries + //-------------------------------------------------------------------------- + @Override + public NavTreeTableModel getModel() { + return model; + } + + @Override + @SuppressWarnings({"unchecked"}) + public N getRoot() { + return (N) model.getRoot(); + } + + @Override + public boolean isLeaf(Object node) { + return model.isLeaf(node); + } + + @Override + public int getChildCount(Object parent) { + return model.getChildCount(parent); + } + + @Override + @SuppressWarnings({"unchecked"}) + public N getChild(Object parent, int index) { + return (N) model.getChild(parent, index); + } + + @Override + public int getIndexOfChild(Object parent, Object child) { + return model.getIndexOfChild(parent, child); + } + + @Override + public TreeNode[] getPathToRoot(TreeNode aNode) { + return model.getPathToRoot((TreeTableNode) aNode); + } + + //-------------------------------------------------------------------------- + //-- Model modification + //-------------------------------------------------------------------------- + + + @Override + public void setModel(NavTreeTableModel model) { + this.model = model; + } + + @Override + public void setRoot(N node) { + model.setRoot(node); + } + + @Override + public void insertNodeInto(N newChild, N parent, int index) { + parent.insert(newChild, index); + model.getModelSupport().fireChildAdded(getTreePath(parent), index, newChild); + } + + @Override + public void removeNodeFromParent(N node) { + N parent = node.getParent(); + int index = parent.getIndex(node); + if (index == -1) { + throw new IllegalArgumentException("Node " + node + " is not in tree"); + } + parent.remove(node); + +// It's not enougth to fire model support... +// model.getModelSupport().fireChildRemoved(path, index, node); + model.getModelSupport().fireTreeStructureChanged(getTreePath(parent)); + } + + @Override + public void reload(N node) { + model.getModelSupport().fireTreeStructureChanged(getTreePath(node)); + } + + @Override + public boolean canLoadChild(N node) { + return true; + } + + //-------------------------------------------------------------------------- + //-- Listeners notifications + //-------------------------------------------------------------------------- + + @Override + public void valueForPathChanged(TreePath path, Object newValue) { + model.valueForPathChanged(path, newValue); + } + + @Override + public void nodeStructureChanged(TreeNode node) { + model.nodeStructureChanged((NavTreeTableNode<?>) node); + } + + @Override + public void nodeChanged(TreeNode node) { + model.nodeChanged((NavTreeTableNode<?>) node); + } + + @Override + public void nodesChanged(TreeNode node, int[] childIndices) { + // changé par le node en lui meme + NavTreeTableNode<?> tableNode = (NavTreeTableNode<?>) node; + + // Extract children + Object[] children = getChildren(tableNode, childIndices); + + model.getModelSupport().fireChildrenChanged(getTreePath(tableNode), childIndices, children); + } + + @Override + public void nodesWereInserted(N parent, int[] indices) { + // Extract children + Object[] children = getChildren(parent, indices); + + model.getModelSupport().fireChildrenAdded(getTreePath(parent), indices, children); + } + + @Override + public void nodeWereInserted(N parentNode, int index, N node) { + + model.getModelSupport().fireChildAdded(getTreePath(parentNode), index, node); + } + + @Override + public void nodesWereRemoved(TreeNode node, int[] childIndices, + Object[] removedChildren) { + + model.getModelSupport().fireChildrenRemoved(getTreePath(node), + childIndices, + removedChildren); + } + + @Override + @SuppressWarnings({"unchecked"}) + public void notifyChildNodesInserted(N node) { + int count = node.getChildCount(); + if (count < 1) { + if (log.isDebugEnabled()) { + log.debug("Skip for leaf node : " + node); + } + return; + } + if (log.isDebugEnabled()) { + log.debug("Notify for node : " + node + ", " + count + " child(s) inserted."); + } + int[] indices = new int[count]; + for (int i = 0; i < count; i++) { + indices[i] = i; + } + + nodesWereInserted(node, indices); + + // recurse notify on childs + for (Enumeration<? extends NavTreeTableNode<?>> childs = node.children(); + childs.hasMoreElements(); ) { + N child = (N) childs.nextElement(); + notifyChildNodesInserted(child); + } + } + + @Override + public void notifyNodeInserted(N node) { + + N parent = node.getParent(); + if (parent != null) { + int index = parent.getIndex(node); + if (index == -1) { + throw new IllegalArgumentException("Node " + node + " is not in tree"); + } + if (log.isDebugEnabled()) { + log.debug("Notify for node : " + node + ", for parent [" + parent + "] child " + index + " inserted."); + } + nodesWereInserted(parent, new int[]{index}); + notifyChildNodesInserted(node); + } + } + + //-------------------------------------------------------------------------- + //-- TreeModelListener provider + //-------------------------------------------------------------------------- + + + @Override + public void addTreeModelListener(TreeModelListener l) { + model.addTreeModelListener(l); + } + + @Override + public void removeTreeModelListener(TreeModelListener l) { + model.removeTreeModelListener(l); + } + + @Override + public TreeModelListener[] getTreeModelListeners() { + return model.getModelSupport().getTreeModelListeners(); + } + + @Override + @SuppressWarnings({"unchecked"}) + public <T extends EventListener> T[] getListeners(Class<T> listenerType) { + TreeModelListener[] treeModelListeners = getTreeModelListeners(); + List<TreeModelListener> result = new ArrayList<TreeModelListener>(); + for (TreeModelListener listener : treeModelListeners) { + if (listener.getClass().isAssignableFrom(listenerType)) { + result.add(listener); + } + } + return (T[]) result.toArray(); + } + + // Extract children + protected Object[] getChildren(NavTreeTableNode<?> tableNode, int[] childIndices) { + + int size = childIndices.length; + Object[] children = new Object[size]; + for (int i = 0; i < size; i++) { + int index = childIndices[i]; + NavTreeTableNode<?> child = tableNode.getChildAt(index); + children[i] = child; + } + return children; + } + + // Create tree path for node in param + protected TreePath getTreePath(TreeNode node) { + return new TreePath(getPathToRoot(node)); + } + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableHelper.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableHelper.java new file mode 100644 index 0000000..adb8101 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableHelper.java @@ -0,0 +1,180 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav.treetable; + +import org.nuiton.jaxx.runtime.swing.nav.NavHelper; +import org.nuiton.jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTreeTable; + +import javax.swing.event.TreeSelectionListener; +import javax.swing.event.TreeWillExpandListener; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.util.ArrayList; +import java.util.List; + +/** + * The implementation of {@link NavHelper} based on a {@link JXTreeTable} component. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public class NavTreeTableHelper<N extends NavTreeTableNode<N>> extends NavHelper<NavTreeTableModel, JXTreeTable, NavTreeTableBridge<N>, N> { + + /** Logger */ + static private final Log log = LogFactory.getLog(NavTreeTableHelper.class); + + public NavTreeTableHelper() { + super(new NavTreeTableBridge<N>()); + } + + @Override + public void scrollPathToVisible(TreePath path) { + getUI().scrollPathToVisible(path); + } + + @Override + public void setSelectionPath(TreePath path) { + getUI().getTreeSelectionModel().setSelectionPath(path); + } + + @Override + public void addSelectionPath(TreePath path) { + getUI().getTreeSelectionModel().addSelectionPath(path); + } + + @Override + public void addSelectionPaths(TreePath[] paths) { + getUI().getTreeSelectionModel().addSelectionPaths(paths); + } + + @Override + public void removeSelectionPath(TreePath path) { + getUI().getTreeSelectionModel().removeSelectionPath(path); + } + + @Override + public void removeSelectionPaths(TreePath[] paths) { + getUI().getTreeSelectionModel().removeSelectionPaths(paths); + } + + @Override + public TreeSelectionModel getSelectionModel() { + return getUI().getTreeSelectionModel(); + } + + @Override + public boolean isExpanded(TreePath pathToExpand) { + return getUI().isExpanded(pathToExpand); + } + + @Override + public void expandPath(TreePath pathToExpand) { + getUI().expandPath(pathToExpand); + } + + @Override + public AbstractNavTreeCellRenderer<NavTreeTableModel, N> getTreeCellRenderer() { + //FIXME Implements it if possible + return null; + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getSelectedNode() { + TreePath path = getSelectionModel().getSelectionPath(); + N node = null; + if (path != null) { + node = (N) path.getLastPathComponent(); + } + return node; + } + + @SuppressWarnings({"unchecked"}) + @Override + public List<N> getSelectedNodes() { + JXTreeTable tree = getUI(); + if (tree == null) { + return null; + } + TreePath[] paths = tree.getTreeSelectionModel().getSelectionPaths(); + List<N> nodes = new ArrayList<N>(); + if (paths != null) { + for (TreePath path : paths) { + if (path != null) { + nodes.add((N) path.getLastPathComponent()); + } + } + } + return nodes; + } + + @Override + public void setUI(JXTreeTable tree, + boolean addExpandTreeListener, + boolean addOneClickSelectionListener, + TreeSelectionListener listener, + TreeWillExpandListener willExpandListener) { + setUI(tree); + if (willExpandListener != null) { + tree.addTreeWillExpandListener(willExpandListener); + } + if (addExpandTreeListener) { + tree.addTreeWillExpandListener(expandListener); + } + if (listener != null) { + tree.addTreeSelectionListener(listener); + } + if (addOneClickSelectionListener) { + tree.addTreeSelectionListener(selectionListener); + } + } + + @Override + protected NavTreeTableModel createModel(N node, Object... extraArgs) { + + // must have a single extra params with delegate model + if (extraArgs.length != 1) { + throw new IllegalArgumentException("Should have exactly one extra parameter (delegate model)"); + } + if (!(extraArgs[0] instanceof NavTreeTableModel.MyDefaultTreeTableModel)) { + throw new IllegalArgumentException("extra parameter is not instance of " + NavTreeTableModel.MyDefaultTreeTableModel.class.getName()); + } + NavTreeTableModel.MyDefaultTreeTableModel delegate = (NavTreeTableModel.MyDefaultTreeTableModel) extraArgs[0]; + NavTreeTableBridge<N> bridge = getBridge(); + NavTreeTableModel model = bridge.getModel(); + if (model == null) { + model = new NavTreeTableModel(delegate); + bridge.setModel(model); +// model = new NavTreeTableBridge(tableModel); + bridge.addTreeModelListener(treeModelListener); +// ((NavTreeTableModel) model).addTreeModelListener(treeModelListener); + } + bridge.setRoot(node); + + // notify structure has changed + bridge.nodeStructureChanged(getRootNode()); + return model; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableModel.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableModel.java new file mode 100644 index 0000000..8d1276e --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableModel.java @@ -0,0 +1,212 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav.treetable; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.tree.TreeModelSupport; +import org.jdesktop.swingx.treetable.DefaultTreeTableModel; +import org.jdesktop.swingx.treetable.TreeTableModel; +import org.jdesktop.swingx.treetable.TreeTableNode; + +import javax.swing.event.TreeModelListener; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +/** + * Model of the tree table used for a jaxx tree table api. + * + * @author Sylvain Lletellier + * @since 2.2 + */ +public class NavTreeTableModel implements TreeTableModel { + + /** Logger */ + static private final Log log = LogFactory.getLog(NavTreeTableModel.class); + + /** + * Hack to acces to the modelSupport + * + * @author sletellier + * @since 2.2 + */ + public static abstract class MyDefaultTreeTableModel extends DefaultTreeTableModel { + + public TreeModelSupport getModelSupport() { + return modelSupport; + } + + public abstract String[] getColumnsNames(); + + } + + /** the delegate model */ + protected MyDefaultTreeTableModel delegate; + + public NavTreeTableModel(MyDefaultTreeTableModel delegate) { + this.delegate = delegate; + } + + @SuppressWarnings({"SuspiciousSystemArraycopy"}) + public TreeTableNode[] getPathToRoot(TreeTableNode aNode) { + if (aNode == null) { + return null; + } + TreeNode[] treeNodes = getDelegate().getPathToRoot(aNode); + NavTreeTableNode<?>[] result = new NavTreeTableNode[treeNodes.length]; + System.arraycopy(treeNodes, 0, result, 0, treeNodes.length); + return result; + } + + public void nodeStructureChanged(NavTreeTableNode<?> node) { + if (node != null) { + NavTreeTableNode<?> parentNode = node.getParent(); + if (parentNode == null || parentNode.isRoot()) { + getModelSupport().fireNewRoot(); + } else { + TreeNode[] treeNodes = getPathToRoot(parentNode); + if (treeNodes != null) { + getModelSupport().fireTreeStructureChanged(new TreePath(treeNodes)); + } + // FIXME : it's append.... +// else { +// log.error("[Node structure changed] Path to root is null !"); +// } + } + } else { + log.error("Node is null !"); + } + } + + public void nodeChanged(NavTreeTableNode<?> node) { + if (node != null) { + NavTreeTableNode<?> parent = node.getParent(); + TreeNode[] treeNodes = getPathToRoot(parent); + if (treeNodes != null) { + getModelSupport().fireChildChanged( + new TreePath(treeNodes), parent.getIndex(node), node); + // FIXME : it's append.... +// else { +// log.error("[Node changed] Path to root is null !"); +// } + } + } else { + log.error("Node is null !"); + } + } + + public MyDefaultTreeTableModel getDelegate() { + return delegate; + } + + public TreeModelSupport getModelSupport() { + return delegate.getModelSupport(); + } + + public String[] getColomnsNames() { + return delegate.getColumnsNames(); + } + + public void setRoot(TreeTableNode root) { + delegate.setRoot(root); + } + + //-------------------------------------------------------------------------- + //-- Overrides delegate methode + //-------------------------------------------------------------------------- + + @Override + public TreeTableNode getRoot() { + return delegate.getRoot(); + } + + @Override + public Object getChild(Object parent, int index) { + return delegate.getChild(parent, index); + } + + @Override + public int getChildCount(Object parent) { + return delegate.getChildCount(parent); + } + + @Override + public boolean isLeaf(Object node) { + return delegate.isLeaf(node); + } + + @Override + public void valueForPathChanged(TreePath path, Object newValue) { + delegate.valueForPathChanged(path, newValue); + } + + @Override + public int getIndexOfChild(Object parent, Object child) { + return delegate.getIndexOfChild(parent, child); + } + + @Override + public void addTreeModelListener(TreeModelListener l) { + delegate.addTreeModelListener(l); + } + + @Override + public void removeTreeModelListener(TreeModelListener l) { + delegate.removeTreeModelListener(l); + } + + @Override + public Class<?> getColumnClass(int i) { + return getDelegate().getColumnClass(i); + } + + @Override + public int getColumnCount() { + return getColomnsNames().length; + } + + @Override + public String getColumnName(int column) { + return getColomnsNames()[column]; + } + + @Override + public int getHierarchicalColumn() { + return getDelegate().getHierarchicalColumn(); + } + + @Override + public Object getValueAt(Object o, int i) { + return getDelegate().getValueAt(o, i); + } + + @Override + public boolean isCellEditable(Object o, int i) { + return getDelegate().isCellEditable(o, i); + } + + @Override + public void setValueAt(Object o, Object o1, int i) { + getDelegate().setValueAt(o, o1, i); + } + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableNode.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableNode.java new file mode 100644 index 0000000..e3ccbe2 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableNode.java @@ -0,0 +1,376 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav.treetable; + +import org.nuiton.jaxx.runtime.swing.nav.NavBridge; +import org.nuiton.jaxx.runtime.swing.nav.NavDataProvider; +import org.nuiton.jaxx.runtime.swing.nav.NavNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTreeTable; +import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode; +import org.jdesktop.swingx.treetable.MutableTreeTableNode; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; + +/** + * Implementation of {@link NavNode} used to create in tree table + * This node extends {@link DefaultMutableTreeTableNode} used by + * {@link JXTreeTable} + * + * @author Sylvain Lletellier + * @since 2.2 + */ +public class NavTreeTableNode<N extends NavTreeTableNode<N>> extends DefaultMutableTreeTableNode implements NavNode<NavTreeTableModel, N> { + + /** Logger */ + static private final Log log = LogFactory.getLog(NavNode.class); + + private static final long serialVersionUID = 1L; + + /** Type of data associated with the node */ + protected final Class<?> internalClass; + + /** + * Optinal context to distinguish different nodes with same + * {@link #internalClass}. + */ + protected final String context; + + /** Id of the data associated with the node. */ + protected final String id; + + /** Flag to know when renderer should (re-)compute render of the node. */ + protected boolean dirty = true; + + /** Flag to know when the none static node was loaded. */ + protected boolean loaded; + + /** Optional child loador to lazy create childs of the node. */ + protected final NavTreeTableNodeChildLoador<?, ?, N> childLoador; + + protected NavTreeTableNode(String id) { + this(String.class, id, null, null); + } + + public NavTreeTableNode(Class<?> internalClass, + String id, + String context, + NavTreeTableNodeChildLoador<?, ?, N> childLoador) { + this.internalClass = internalClass; + this.id = id; + this.context = context; + this.childLoador = childLoador; + if (isStaticNode()) { + + // A static node is always full loaded + loaded = true; + } + if (log.isDebugEnabled()) { + log.debug("new node : " + this); + } + } + + @Override + public String getId() { + return id; + } + + @Override + public String getContext() { + return context; + } + + @Override + public Class<?> getInternalClass() { + return internalClass; + } + + @Override + public boolean isLoaded() { + return loaded; + } + + @Override + public boolean isDirty() { + return dirty; + } + + @Override + public boolean isStringNode() { + return String.class.equals(internalClass); + } + + @Override + public boolean isStaticNode() { + return childLoador == null; + } + + @Override + @SuppressWarnings({"unchecked"}) + public N getContainerNode() { + if (isRoot()) { + // si on arrive sur le root, quelque chose ne va pas, + // on bloque par null, a defaut de declancher une exception + return null; + } + + if (isStringNode()) { + // on est sur un noeud de type String, donc on regarde sur le parent + return getParent().getContainerNode(); + } + + // cas final : sur un noeud de donnee + classe interne de donnee + return (N) this; + } + + public boolean isRoot() { + return getParent() == null; + } + + @Override + @SuppressWarnings({"unchecked"}) + public N findNodeById(String id, + NavBridge<NavTreeTableModel, N> model, + NavDataProvider provider) { + if (id == null) { + + // id null ? donc rien a faire + return null; + } + if (id.equals(getId())) { + + // on a trouve le bon noeud + return (N) this; + } + + if (!isLoaded()) { + + // il faut charger les fils du noeud pour effectuer la recherche + populateChilds(model, provider); + } + + if (isLeaf()) { + + // au final le noeud est une feuille, donc ne convient pas + return null; + } + + // on recherche dans les fils + Enumeration<N> enumeration = children(); + while (enumeration.hasMoreElements()) { + N node = enumeration.nextElement(); + N nodeById = node.findNodeById(id, model, provider); + if (nodeById != null) { + return nodeById; + } + } + + // aucun des noeud fils ne convient + return null; + } + + @Override + public N getChild(String id, + NavBridge<NavTreeTableModel, N> bridge, + NavDataProvider provider) { + + if (id == null) { + + // id null ? donc rien a faire + return null; + } + + if (!isLoaded()) { + + // il faut charger les fils du noeud pour effectuer la recherche + populateChilds(bridge, provider); + } + + if (isLeaf()) { + + // au final le noeud est une feuille, donc ne convient pas + return null; + } + + // on recherche dans les fils + Enumeration<N> enumeration = children(); + while (enumeration.hasMoreElements()) { + N node = enumeration.nextElement(); + if (id.equals(node.getId())) { + return node; + } + } + + // aucun des noeud fils ne convient + return null; + } + + @Override + public void setDirty(boolean dirty) { + this.dirty = dirty; + } + + @Override + public boolean isLeaf() { + // there is two behaviours for the test : + // 1 - when the node is static, then can directly use his number of child + // to determine if node is a leaf (no child) + // 2 - when the node is dynamic, then ALWAYS says the node is NOT a leaf until + // it was loaded, otherwise the WillExpand listener will not load the childs... + // Once the node is loaded, use back the normal behaviour (count number of childs) + return isStaticNode() ? super.isLeaf() : isLoaded() && getChildCount() == 0; + } + + @Override + public Object getUserObject() { + return id; + } + + @Override + public String toString() { + return System.identityHashCode(this) + "-" + id; + } + + //-------------------------------------------------------------------------- + //-- Populate methods + //-------------------------------------------------------------------------- + + @Override + public void populateNode(NavBridge<NavTreeTableModel, N> model, + NavDataProvider provider, + boolean populateChilds) { + + // on indique que le noeud n'est plus propre + setDirty(true); + + if (populateChilds) { + + // chargement des fils + populateChilds(model, provider); + } + } + + @Override + @SuppressWarnings({"unchecked"}) + public void populateChilds(NavBridge<NavTreeTableModel, N> bridge, + NavDataProvider provider) { + if (isStaticNode()) { + + // noeud static, rien a faire + return; + } + + if (!bridge.canLoadChild((N) this)) { + + // can not load childs + if (log.isDebugEnabled()) { + log.debug("Will Skip populateChilds for node : " + this); + } + return; + } + + // chargement des noeuds fils du noeud courant + try { + if (log.isDebugEnabled()) { + log.debug("Will load childs for " + this); + } + childLoador.loadChilds((NavTreeTableBridge<N>) bridge, (N) this, provider); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } finally { + + // au final, on passe le noeud a l'état chargé + loaded = true; + } + } + + //-------------------------------------------------------------------------- + //-- Overrides to use generic type as return + //-------------------------------------------------------------------------- + + @SuppressWarnings({"unchecked"}) + @Override + public N getParent() { + return (N) super.getParent(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getChildAt(int index) { + return (N) super.getChildAt(index); + } + + // It's a hack to prevent concurent modification exception, caused by + // children() of AbstractMutableTreeTableNode return Collections.enumeration + @SuppressWarnings({"unchecked"}) + @Override + public Enumeration<N> children() { + List<? extends MutableTreeTableNode> newChildrenList = + new ArrayList<MutableTreeTableNode>(children); + + return (Enumeration<N>) Collections.enumeration(newChildrenList); + } + + public void removeAllChildren() { + children.clear(); + } + + @Override + public void add(N node) { + super.add(node); + } + + @SuppressWarnings({"unchecked"}) + public N[] getPathToRoot(NavTreeTableNode aNode, int depth) { + + NavTreeTableNode[] retNodes; + + /* Check for null, in case someone passed in a null node, or + they passed in an element that isn't rooted at root. */ + if (aNode == null) { + if (depth == 0) { + return null; + } else { + retNodes = new NavTreeTableNode[depth]; + } + } else { + depth++; + retNodes = getPathToRoot(aNode.getParent(), depth); + retNodes[retNodes.length - depth] = aNode; + } + return (N[]) retNodes; + } + + @Override + public void remove(N node) { + super.remove(node); + } + + @Override + public void insert(N node, int position) { + super.insert(node, position); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableNodeChildLoador.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableNodeChildLoador.java new file mode 100644 index 0000000..ab17bea --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/NavTreeTableNodeChildLoador.java @@ -0,0 +1,39 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.nav.treetable; + +import org.nuiton.jaxx.runtime.swing.nav.NavNodeChildLoador; + +/** + * Implementation for tree table of {@link NavNodeChildLoador} + * + * @author Sylvain Lletellier + * @since 2.2 + */ +public abstract class NavTreeTableNodeChildLoador<T, O, N extends NavTreeTableNode<N>> extends NavNodeChildLoador<T, O, NavTreeTableModel, NavTreeTableBridge<N>, N> { + + private static final long serialVersionUID = 1L; + + protected NavTreeTableNodeChildLoador(Class<O> beanType) { + super(beanType); + } +} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/package.html b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/package.html similarity index 100% rename from jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/package.html rename to jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/nav/treetable/package.html diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/BooleanCellRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/BooleanCellRenderer.java new file mode 100644 index 0000000..f1b992b --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/BooleanCellRenderer.java @@ -0,0 +1,108 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.renderer; + +import com.google.common.base.Predicate; + +import javax.swing.Icon; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import java.awt.Color; +import java.awt.Component; + +/** + * @author Tony Chemit - chemit@codelutin.com + * @since 1.5 + */ +public class BooleanCellRenderer extends JPanel implements TableCellRenderer { + + private static final long serialVersionUID = 1L; + + protected final TableCellRenderer defaultDelegate; + + protected final JCheckBox checkBox; + + private final Predicate predicate; + + private static final Predicate<Object> DEFAULT_PREDICATE = new Predicate<Object>() { + @Override + public boolean apply(Object input) { + return (input != null && (Boolean) input); + } + }; + + public BooleanCellRenderer(TableCellRenderer delegate, Predicate<?> predicate) { + this(delegate, new JCheckBox(), predicate); + } + + public BooleanCellRenderer(TableCellRenderer delegate) { + //super(new BorderLayout()); + this(delegate, DEFAULT_PREDICATE); + + } + + public BooleanCellRenderer(TableCellRenderer delegate, Icon icon, Predicate<?> predicate) { + this(delegate, new JCheckBox(icon), predicate); + } + + public BooleanCellRenderer(TableCellRenderer delegate, Icon icon) { + //super(new BorderLayout()); + this(delegate, icon, DEFAULT_PREDICATE); + checkBox.setVerticalTextPosition(JLabel.TOP); + + } + + public BooleanCellRenderer(TableCellRenderer delegate, JCheckBox checkBox, Predicate<?> predicate) { + this.defaultDelegate = delegate; + this.predicate = predicate; + this.checkBox = checkBox; + this.checkBox.setBorderPainted(true); + this.checkBox.setHorizontalAlignment(JLabel.CENTER); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + ((JComponent) defaultDelegate).setBackground(null); + JComponent render = (JComponent) defaultDelegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + if (isSelected) { + setForeground(table.getSelectionForeground()); + setBackground(table.getSelectionBackground()); + } else { + setForeground(render.getForeground()); + setBackground(render.getBackground()); + //fixme make this works... and remove the test + if (row % 2 == 1) { + setBackground(Color.WHITE); + } + } + + boolean selectCheckBox = predicate.apply(value); + checkBox.setSelected(selectCheckBox); + + setBorder(render.getBorder()); + return checkBox; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/ClassTableCellRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/ClassTableCellRenderer.java new file mode 100644 index 0000000..ff024b8 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/ClassTableCellRenderer.java @@ -0,0 +1,58 @@ +package org.nuiton.jaxx.runtime.swing.renderer; +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; + +/** + * Table cell renderer for a {@link Class} + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.4 + */ +public class ClassTableCellRenderer implements TableCellRenderer { + + protected final TableCellRenderer defaultDelegate; + + public ClassTableCellRenderer() { + this.defaultDelegate = new DefaultTableCellRenderer(); + } + + public ClassTableCellRenderer(TableCellRenderer defaultDelegate) { + this.defaultDelegate = defaultDelegate; + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + + return defaultDelegate.getTableCellRendererComponent( + table, + value == null ? null : ((Class<?>) value).getName(), + isSelected, + hasFocus, + row, + column); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/ColorCellRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/ColorCellRenderer.java new file mode 100644 index 0000000..563b359 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/ColorCellRenderer.java @@ -0,0 +1,50 @@ +package org.nuiton.jaxx.runtime.swing.renderer; +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import javax.swing.JButton; +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import java.awt.Color; +import java.awt.Component; + +/** + * Date: 31/07/12 + * + * @author Matthieu Allon + * @since 2.5.4 + */ +public class ColorCellRenderer implements TableCellRenderer { + + protected JButton button = new JButton(); + + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, + int column) { + button.setBackground((Color) value); + return button; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DecoratorListCellRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DecoratorListCellRenderer.java new file mode 100644 index 0000000..48f45b2 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DecoratorListCellRenderer.java @@ -0,0 +1,80 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.renderer; + +import org.nuiton.decorator.Decorator; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import java.awt.Component; + +/** + * A {@link ListCellRenderer} which compute text with the given {@link #decorator} + * and leave the hand to the {@link #delegate} to perform the visual renderer. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.7.2 + */ +public class DecoratorListCellRenderer implements ListCellRenderer { + + /** Delegate cell renderer */ + protected ListCellRenderer delegate; + + /** Decorator to produce text to render */ + protected Decorator<?> decorator; + + public DecoratorListCellRenderer(Decorator<?> decorator) { + this(new DefaultListCellRenderer(), decorator); + } + + public DecoratorListCellRenderer(ListCellRenderer delegate, + Decorator<?> decorator) { + this.delegate = delegate; + this.decorator = decorator; + } + + @Override + public Component getListCellRendererComponent(JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) { + value = decorateValue(value, index); + return delegate.getListCellRendererComponent(list, + value, + index, + isSelected, + cellHasFocus + ); + } + + protected Object decorateValue(Object value,int index) { + if (value == null) { + value = " "; + } + if (!(value instanceof String) && decorator != null) { + value = decorator.toString(value); + } + return value; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DecoratorProviderListCellRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DecoratorProviderListCellRenderer.java new file mode 100644 index 0000000..b98803d --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DecoratorProviderListCellRenderer.java @@ -0,0 +1,75 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.renderer; + +import org.nuiton.decorator.Decorator; +import org.nuiton.decorator.DecoratorProvider; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import java.awt.Component; + +/** + * A {@link ListCellRenderer} which use decorators from the {@link #provider} to obtain the text to display. + * + * The interest of this renderer is to define a unique renderer for your application (put it in JAXXContext) + * and then use it simply :) + * + * User: chemit + * Date: 29 oct. 2009 + * Time: 03:00:53 + * + * @see DecoratorProvider + * @since 2.0.0 + */ +public class DecoratorProviderListCellRenderer implements ListCellRenderer { + + /** Delegate cell renderer */ + protected ListCellRenderer delegate; + + /** provider of decorators */ + protected DecoratorProvider provider; + + public DecoratorProviderListCellRenderer(DecoratorProvider provider) { + this(new DefaultListCellRenderer(), provider); + } + + public DecoratorProviderListCellRenderer(ListCellRenderer delegate, DecoratorProvider provider) { + this.delegate = delegate; + this.provider = provider; + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + if (value != null) { + Decorator<?> decorator = provider.getDecorator(value); + + if (decorator != null) { + value = decorator.toString(value); + } + } else { + value = " "; + } + return delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DecoratorProviderTableCellRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DecoratorProviderTableCellRenderer.java new file mode 100644 index 0000000..66e08d7 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DecoratorProviderTableCellRenderer.java @@ -0,0 +1,73 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.renderer; + +import org.nuiton.decorator.Decorator; +import org.nuiton.decorator.DecoratorProvider; + +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; + +/** + * A {@link TableCellRenderer} which use decorators from the {@link #provider} to obtain the text to display. + * + * The interest of this renderer is to define a unique renderer for your application (put it in JAXXContext) + * and then use it simply :) + * + * User: chemit + * Date: 29 oct. 2009 + * Time: 03:00:53 + * + * @see DecoratorProvider + * @since 2.0.0 + */ +public class DecoratorProviderTableCellRenderer implements TableCellRenderer { + + /** Delegate cell renderer */ + protected TableCellRenderer delegate; + + /** provider of decorators */ + protected DecoratorProvider provider; + + public DecoratorProviderTableCellRenderer(DecoratorProvider provider) { + this(new DefaultTableCellRenderer(), provider); + } + + public DecoratorProviderTableCellRenderer(TableCellRenderer delegate, DecoratorProvider provider) { + this.delegate = delegate; + this.provider = provider; + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasfocus, int row, int column) { + if (value != null) { + Decorator<?> decorator = provider.getDecorator(value); + + if (decorator != null) { + value = decorator.toString(value); + } + } + return delegate.getTableCellRendererComponent(table, value, isSelected, hasfocus, row, column); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DecoratorTableCellRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DecoratorTableCellRenderer.java new file mode 100644 index 0000000..2c4df17 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DecoratorTableCellRenderer.java @@ -0,0 +1,87 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.renderer; + +import org.nuiton.decorator.Decorator; + +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; +import javax.swing.JComponent; + +/** + * A {@link TableCellRenderer} which compute text with the given {@link #decorator} + * and leave the hand to the {@link #delegate} to perform the visual renderer. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.7.2 (was previously {@code jaxx.runtime.swing.DecoratorTableCellRenderer}). + */ +public class DecoratorTableCellRenderer implements TableCellRenderer { + + /** Delegate cell renderer */ + protected TableCellRenderer delegate; + + /** Decorator to produce text to render */ + protected Decorator<?> decorator; + + protected boolean showToolTipText = false; + + public DecoratorTableCellRenderer(Decorator<?> decorator) { + this(new DefaultTableCellRenderer(), decorator, false); + } + + public DecoratorTableCellRenderer(Decorator<?> decorator, boolean showToolTipText) { + this(new DefaultTableCellRenderer(), decorator, showToolTipText); + } + + public DecoratorTableCellRenderer(TableCellRenderer delegate, Decorator<?> decorator) { + this(new DefaultTableCellRenderer(), decorator, false); + } + + public DecoratorTableCellRenderer(TableCellRenderer delegate, + Decorator<?> decorator, + boolean showToolTipText) { + this.delegate = delegate; + this.decorator = decorator; + this.showToolTipText = showToolTipText; + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasfocus, int row, int column) { + String text = null; + if (value != null) { + text = decorator.toString(value); + } + JComponent result = + (JComponent) delegate.getTableCellRendererComponent(table, + text, + isSelected, + hasfocus, + row, + column); + if (showToolTipText) { + result.setToolTipText(text); + } + return result; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/EmptyNumberTableCellRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/EmptyNumberTableCellRenderer.java new file mode 100644 index 0000000..0fc208c --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/EmptyNumberTableCellRenderer.java @@ -0,0 +1,61 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.renderer; + +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; + +/** + * A {@link TableCellRenderer} which does not display numbers when they are + * equals to 0. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.5 + */ +public class EmptyNumberTableCellRenderer implements TableCellRenderer { + + protected final Integer ZERO = 0; + + protected final Float ZEROF = 0F; + + protected final Double ZEROD = 0D; + + private TableCellRenderer delegate; + + public EmptyNumberTableCellRenderer() { + this(new DefaultTableCellRenderer()); + } + + public EmptyNumberTableCellRenderer(TableCellRenderer delegate) { + this.delegate = delegate; + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (value == null || ZERO.equals(value) || ZEROF.equals(value) || ZEROD.equals(value)) { + value = null; + } + return delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/EnumEditorRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/EnumEditorRenderer.java new file mode 100644 index 0000000..6ddc8ee --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/EnumEditorRenderer.java @@ -0,0 +1,53 @@ +package org.nuiton.jaxx.runtime.swing.renderer; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2016 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.ImmutableMap; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JList; +import java.awt.Component; + +/** + * Created on 08/03/16. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class EnumEditorRenderer<E extends Enum<E>> extends DefaultListCellRenderer { + private static final long serialVersionUID = 1L; + + private final ImmutableMap<E, String> labels; + + public EnumEditorRenderer(ImmutableMap<E, String> labels) { + this.labels = labels; + } + + @Override + public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + + if (value != null) { + value = labels.get((E) value); + } + return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/EnumTableCellRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/EnumTableCellRenderer.java new file mode 100644 index 0000000..c7ca030 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/EnumTableCellRenderer.java @@ -0,0 +1,66 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.renderer; + +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; +import java.util.EnumSet; + +/** + * A {@link TableCellRenderer} which displays enum values from their ordinal value. + * + * @param <E> le type de l'énumération. + * @author Tony Chemit - chemit@codelutin.com + * @since 1.5 + */ +public class EnumTableCellRenderer<E extends Enum<E>> implements TableCellRenderer { + + private TableCellRenderer delegate; + + private EnumSet<E> enumValues; + + public EnumTableCellRenderer(TableCellRenderer delegate, Class<E> enumClass) { + this.delegate = delegate; + this.enumValues = EnumSet.allOf(enumClass); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + + if (value != null) { + //FIXME : should be also able to read it by name ? + Integer ordinal = Integer.valueOf(value + ""); + if (ordinal == -1) { + value = null; + } else { + for (E enumValue : enumValues) { + if (ordinal == enumValue.ordinal()) { + value = enumValue; + break; + } + } + } + } + return delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/FilteredDecoratorListCellRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/FilteredDecoratorListCellRenderer.java new file mode 100644 index 0000000..60a10ff --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/FilteredDecoratorListCellRenderer.java @@ -0,0 +1,135 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.renderer; + +import java.awt.Component; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import org.apache.commons.lang3.StringUtils; +import org.nuiton.decorator.Decorator; + +/** + * A {@link ListCellRenderer} which compute text with the given {@link #decorator}, + * highlights a part of the rendered text, + * and leave the hand to the {@link #delegate} to perform the visual renderer. + * + * @author Kevin Morin - morin@codelutin.com + * @since 2.5.11 + */ +public class FilteredDecoratorListCellRenderer extends DecoratorListCellRenderer { + + /** text to highlight */ + protected String filterText; + + protected Pattern pattern; + + protected boolean highlightFilterText = false; + + public FilteredDecoratorListCellRenderer(Decorator<?> decorator) { + super(decorator); + } + + public FilteredDecoratorListCellRenderer(ListCellRenderer delegate, + Decorator<?> decorator) { + super(delegate, decorator); + } + + public FilteredDecoratorListCellRenderer(ListCellRenderer delegate, + Decorator<?> decorator, + boolean highlightFilterText) { + super(delegate, decorator); + this.highlightFilterText = highlightFilterText; + } + + public String getFilterText() { + return filterText; + } + + public void setFilterText(String filterText) { + this.filterText = filterText; + computePattern(); + } + + public boolean isHighlightFilterText() { + return highlightFilterText; + } + + public void setHighlightFilterText(boolean highlightFilterText) { + this.highlightFilterText = highlightFilterText; + computePattern(); + } + + @Override + public Component getListCellRendererComponent(JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) { + + if (!(value instanceof String) && decorator != null) { + value = decorator.toString(value); + } + + String stringValue = String.valueOf(value); + if (pattern != null) { + Matcher matcher = pattern.matcher(stringValue); + if (matcher.find()) { + // for each group caught, add the text between the previous group + // and the current group and surround the group with the highlighter + StringBuilder sb = new StringBuilder(); + int i = 0; + for (int g = 1 ; g <= matcher.groupCount() ; g++) { + String match = matcher.group(g); + int indexOfMatch = stringValue.indexOf(match, i); + sb.append(stringValue.substring(i, indexOfMatch)) + .append("<span style='background:#FFFF00'>") + .append(match) + .append("</span>"); + i = indexOfMatch + match.length(); + } + sb.append(stringValue.substring(i)); + stringValue = "<html>" + sb.toString() + "</html>"; + } + } + return delegate.getListCellRendererComponent(list, + stringValue, + index, + isSelected, + cellHasFocus + ); + } + + protected void computePattern() { + if (highlightFilterText + && !StringUtils.isEmpty(StringUtils.remove(filterText, '*'))) { + // add the groups in the pattern + String patternText = "(" + filterText.replace("*", ").*(") + ").*"; + patternText = StringUtils.remove(patternText, "()"); + pattern = Pattern.compile(patternText, Pattern.CASE_INSENSITIVE); + + } else { + pattern = null; + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/I18nTableCellRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/I18nTableCellRenderer.java new file mode 100644 index 0000000..5ca59ca --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/I18nTableCellRenderer.java @@ -0,0 +1,106 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.renderer; + +import javax.swing.JComponent; +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import java.awt.Component; + +import static org.nuiton.i18n.I18n.t; + +/** + * A simple TableCellRenderer using a delegate TableCellRenderer to render + * everything elese thant the text : the text is I18nalize. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class I18nTableCellRenderer implements TableCellRenderer { + + /** i18n keys of libelles to display */ + protected final String[] keys; + + /** i18n keys of toolTipTexts to display */ + protected final String[] tips; + + /** the delegate cell renderer */ + protected TableCellRenderer delegate; + + public I18nTableCellRenderer(TableCellRenderer delegate, + String... keysAndTips) { + this.delegate = delegate; + if (keysAndTips.length == 0) { + throw new IllegalArgumentException( + "can not have empty keysAndTips parameters (means no " + + "column ?)"); + } + if (keysAndTips.length % 2 == 1) { + throw new IllegalArgumentException( + "must have some couple (text,tooltTipText), but had an" + + " even number of data in keysAndTips parameter"); + } + int size = keysAndTips.length / 2; + keys = new String[size]; + tips = new String[size]; + for (int i = 0; i < size; i++) { + keys[i] = keysAndTips[2 * i]; + tips[i] = keysAndTips[2 * i + 1]; + } + } + + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasfocus, + int row, + int column) { + if (column > keys.length) { + throw new IndexOutOfBoundsException( + "colum can not be greater than " + keys.length); + } + TableColumn col = table.getColumn(table.getColumnName(column)); + int index = col.getModelIndex(); + value = t(keys[index]); + JComponent rendererComponent = (JComponent) + delegate.getTableCellRendererComponent( + table, + value, + isSelected, + hasfocus, + row, + column + ); + rendererComponent.setToolTipText(t(tips[index])); + return rendererComponent; + } + + public String[] getKeys() { + return keys; + } + + public String[] getTips() { + return tips; + } + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/LocaleListCellRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/LocaleListCellRenderer.java new file mode 100644 index 0000000..88cf004 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/LocaleListCellRenderer.java @@ -0,0 +1,146 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.renderer; + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.Icon; +import javax.swing.JLabel; +import javax.swing.JList; +import java.awt.Component; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/** @author Tony Chemit - chemit@codelutin.com */ +public class LocaleListCellRenderer extends DefaultListCellRenderer { + + public static final Log log = LogFactory.getLog(LocaleListCellRenderer.class); + + private static final long serialVersionUID = 1L; + + protected final Map<Locale, Icon> cache = new HashMap<Locale, Icon>(); + + protected boolean showIcon; + + protected boolean showText; + + public LocaleListCellRenderer() { + this(true, true); + } + + public LocaleListCellRenderer(boolean showIcon, boolean showText) { + this.showIcon = showIcon; + this.showText = showText; + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + JLabel comp = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + Locale locale = (Locale) value; + if (locale != null) { + Icon icon = getIcon(locale); + comp.setIcon(icon); + } + String text = getText(locale); + String tip = getToolTipText(locale); + comp.setText(text); + comp.setToolTipText(tip); + return comp; + } + + public String getText(Locale locale) { + String text = null; + if (showText) { + text = getSafeText(locale); + } + return text; + } + + public Icon getIcon(Locale locale) { + if (!showIcon) { + return null; + } + synchronized (cache) { + return getSafeIcon(locale); + } + } + + public String getToolTipText(Locale locale) { + return locale.getDisplayName(Locale.getDefault()); + } + + public boolean isShowText() { + return showText; + } + + public boolean isShowIcon() { + return showIcon; + } + + public void setShowIcon(boolean showIcon) { + boolean old = this.showIcon; + this.showIcon = showIcon; + firePropertyChange("showIcon", old, showIcon); + } + + public void setShowText(boolean showText) { + boolean old = this.showText; + this.showText = showText; + firePropertyChange("showText", old, showText); + } + + public String getSafeText(Locale locale) { + return locale.getDisplayName(Locale.getDefault()); + } + + public synchronized Icon getSafeIcon(Locale locale) { + Icon icon = cache.get(locale); + if (icon != null) { + return icon; + } + + icon = SwingUtil.getUIManagerActionIcon("i18n-" + locale.toString()); + + if (icon == null) { + log.warn("could not find icon action.i18n-" + locale.toString()); + if (locale.getCountry() != null) { + icon = SwingUtil.getUIManagerActionIcon("i18n-" + locale.getCountry().toLowerCase()); + if (icon == null) { + log.warn("could not find icon action.i18n-" + locale.getCountry().toLowerCase()); + + icon = SwingUtil.createActionIcon("i18n-" + locale.getCountry().toLowerCase()); + if (icon == null) { + log.warn("could not find icon action.i18n-" + locale.getCountry().toLowerCase()); + } + } + + } + } + + cache.put(locale, icon); + return icon; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/MultiDecoratorListCellRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/MultiDecoratorListCellRenderer.java new file mode 100644 index 0000000..a9405de --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/MultiDecoratorListCellRenderer.java @@ -0,0 +1,87 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.renderer; + +import org.nuiton.decorator.Decorator; +import org.nuiton.decorator.JXPathDecorator; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import java.awt.Component; +import java.util.ArrayList; +import java.util.List; + +/** + * A {@link ListCellRenderer} which compute text with the matching decorator + * from {@link #decorators} and leave the hand to the {@link #delegate} to + * perform the visual renderer. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.0 + */ +public class MultiDecoratorListCellRenderer implements ListCellRenderer { + + /** Delegate cell renderer */ + protected ListCellRenderer delegate; + + /** accepted types */ + protected List<Class<?>> types; + + /** decorators for accepted types */ + protected Decorator<?>[] decorators; + + public MultiDecoratorListCellRenderer(ListCellRenderer delegate, JXPathDecorator<?>... decorator) { + this.delegate = delegate; + this.types = new ArrayList<Class<?>>(); + List<Decorator<?>> tmp = new ArrayList<Decorator<?>>(); + for (JXPathDecorator<?> d : decorator) { + if (types.contains(d.getType())) { + throw new IllegalArgumentException("can not have twice a decorator of type " + d.getType()); + } + types.add(d.getType()); + tmp.add(d); + } + decorators = tmp.toArray(new Decorator<?>[tmp.size()]); + } + + public MultiDecoratorListCellRenderer(JXPathDecorator<?>... decorator) { + this(new DefaultListCellRenderer(), decorator); + } + + @Override + public Component getListCellRendererComponent(JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) { + if (value != null) { + int i = types.indexOf(value.getClass()); + if (i != -1) { + Decorator<?> d = decorators[i]; + value = d.toString(value); + } + } + return delegate.getListCellRendererComponent( + list, value, index, isSelected, cellHasFocus); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/MultiDecoratorTableCelleRenderer.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/MultiDecoratorTableCelleRenderer.java new file mode 100644 index 0000000..4235e6c --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/MultiDecoratorTableCelleRenderer.java @@ -0,0 +1,97 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.renderer; + +import org.nuiton.decorator.Decorator; +import org.nuiton.decorator.JXPathDecorator; + +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; +import java.util.ArrayList; +import java.util.List; + +/** + * A {@link TableCellRenderer} which compute text with the matching decorator + * from {@link #decorators} based on the type of value and leave the hand to + * the {@link #delegate} to perform the visual renderer. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.0 + */ +public class MultiDecoratorTableCelleRenderer implements TableCellRenderer { + + /** Delegate cell renderer */ + protected TableCellRenderer delegate; + + /** accepted types */ + protected List<Class<?>> types; + + /** decorators for accepted types */ + protected Decorator<?>[] decorators; + + public MultiDecoratorTableCelleRenderer(JXPathDecorator<?>... decorator) { + this(new DefaultTableCellRenderer(), decorator); + } + + public MultiDecoratorTableCelleRenderer(TableCellRenderer delegate, + JXPathDecorator<?>... decorator) { + this.delegate = delegate; + + types = new ArrayList<Class<?>>(); + List<Decorator<?>> tmp = new ArrayList<Decorator<?>>(); + for (JXPathDecorator<?> d : decorator) { + if (types.contains(d.getType())) { + throw new IllegalArgumentException( + "can not have twice a decorator of type " + + d.getType()); + } + types.add(d.getType()); + tmp.add(d); + } + decorators = tmp.toArray(new Decorator<?>[tmp.size()]); + } + + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasfocus, + int row, + int column) { + if (value != null) { + int i = types.indexOf(value.getClass()); + if (i != -1) { + Decorator<?> d = decorators[i]; + value = d.toString(value); + } + } + return delegate.getTableCellRendererComponent(table, + value, + isSelected, + hasfocus, + row, + column + ); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/JSplitPaneState.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/JSplitPaneState.java new file mode 100644 index 0000000..93d395f --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/JSplitPaneState.java @@ -0,0 +1,97 @@ +package org.nuiton.jaxx.runtime.swing.session; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import javax.swing.*; + +/** + * State for JSplit + * FIXME add listener for divider move action + * + * @author poussin + * @author Kevin Morin - morin@codelutin.com + * @since 2.5.16 + */ +public class JSplitPaneState implements State { + + protected int dividerLocation = -1; + + protected int orientation = JSplitPane.HORIZONTAL_SPLIT; + + public JSplitPaneState() { + } + + public int getDividerLocation() { + return dividerLocation; + } + + public void setDividerLocation(int dividerLocation) { + this.dividerLocation = dividerLocation; + } + + public int getOrientation() { + return orientation; + } + + public void setOrientation(int orientation) { + this.orientation = orientation; + } + + protected JSplitPane checkComponent(Object o) { + if (o == null) { + throw new IllegalArgumentException("null component"); + } + if (!(o instanceof JSplitPane)) { + throw new IllegalArgumentException("invalid component"); + } + return (JSplitPane) o; + } + + @Override + public State getState(Object o) { + JSplitPane p = checkComponent(o); + + JSplitPaneState result = new JSplitPaneState(); + result.setDividerLocation(p.getUI().getDividerLocation(p)); + result.setOrientation(p.getOrientation()); + + return result; + } + + @Override + public void setState(Object o, State state) { + if (state == null) { + return; + } + JSplitPane p = checkComponent(o); + if (state instanceof JSplitPaneState) { + JSplitPaneState sps = (JSplitPaneState) state; + if (sps.getDividerLocation() != -1 + && p.getOrientation() == sps.getOrientation()) { + p.setDividerLocation(sps.getDividerLocation()); + } + } else { + throw new IllegalArgumentException("invalid state"); + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/JTabbedPaneState.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/JTabbedPaneState.java new file mode 100644 index 0000000..5954c15 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/JTabbedPaneState.java @@ -0,0 +1,97 @@ +package org.nuiton.jaxx.runtime.swing.session; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import javax.swing.*; + +/** + * State for the JTabbedPane + * + * @author poussin + * @author Kevin Morin - morin@codelutin.com + * @since 2.5.16 + */ +public class JTabbedPaneState implements State { + + protected int selectedIndex = -1; + + protected int tabCount; + + public JTabbedPaneState() { + } + + public int getSelectedIndex() { + return selectedIndex; + } + + public void setSelectedIndex(int selectedIndex) { + this.selectedIndex = selectedIndex; + } + + public int getTabCount() { + return tabCount; + } + + public void setTabCount(int tabCount) { + this.tabCount = tabCount; + } + + + protected JTabbedPane checkComponent(Object o) { + if (o == null) { + throw new IllegalArgumentException("null component"); + } + if (!(o instanceof JTabbedPane)) { + throw new IllegalArgumentException("invalid component"); + } + return (JTabbedPane) o; + } + + @Override + public State getState(Object o) { + JTabbedPaneState result = new JTabbedPaneState(); + + JTabbedPane p = checkComponent(o); + result.setSelectedIndex(p.getSelectedIndex()); + result.setTabCount(p.getTabCount()); + + return result; + } + + @Override + public void setState(Object o, State state) { + if (state == null) { + return; + } + if (state instanceof JTabbedPaneState) { + JTabbedPane p = checkComponent(o); + JTabbedPaneState tps = (JTabbedPaneState) state; + if (tps.getSelectedIndex() != -1 + && p.getTabCount() == tps.getTabCount()) { + p.setSelectedIndex(tps.getSelectedIndex()); + } + } else { + throw new IllegalArgumentException("invalid state"); + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/JTableState.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/JTableState.java new file mode 100644 index 0000000..8d88ec3 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/JTableState.java @@ -0,0 +1,154 @@ +package org.nuiton.jaxx.runtime.swing.session; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.*; +import javax.swing.table.TableColumn; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * State for JTable. + * TODO add support for column order change + * + * @author poussin + * @author Kevin Morin - morin@codelutin.com + * @since 2.5.16 + * + */ +public class JTableState implements State { + + private static final Log log = LogFactory.getLog(JTableState.class); + + protected int[] columnWidths = new int[0]; + + protected Map<Integer, String> sortKeys; + + public JTableState() { + } + + public JTableState(int[] columnWidths, Map<Integer, String> sortKeys) { + this.columnWidths = columnWidths; + this.sortKeys = sortKeys; + } + + public int[] getColumnWidths() { + return columnWidths; + } + + public void setColumnWidths(int[] columnWidths) { + this.columnWidths = columnWidths; + } + + public Map<Integer, String> getSortKeys() { + return sortKeys; + } + + public void setSortKeys(Map<Integer, String> sortKeys) { + this.sortKeys = sortKeys; + } + + protected JTable checkComponent(Object o) { + if (o == null) { + throw new IllegalArgumentException("null component"); + } + if (!(o instanceof JTable)) { + throw new IllegalArgumentException("invalid component"); + } + return (JTable) o; + } + + @Override + public State getState(Object o) { + JTable table = checkComponent(o); + + JTableState result = new JTableState(); + + int[] columnWidths = new int[table.getColumnCount()]; + boolean resizableColumnExists = false; + + for (int i = 0; i < columnWidths.length; i++) { + TableColumn tc = table.getColumnModel().getColumn(i); + columnWidths[i] = (tc.getResizable()) ? tc.getWidth() : -1; + if (tc.getResizable()) { + resizableColumnExists = true; + } + } + + if (resizableColumnExists) { + result.setColumnWidths(columnWidths); + } + + if (table.getRowSorter() != null) { + List<? extends RowSorter.SortKey> sortKeys = table.getRowSorter().getSortKeys(); + Map<Integer, String> sortKeysMap = null; + if (sortKeys != null) { + sortKeysMap = new HashMap<Integer, String>(); + for (RowSorter.SortKey sortKey : sortKeys) { + sortKeysMap.put(sortKey.getColumn(), String.valueOf(sortKey.getSortOrder())); + } + } + result.setSortKeys(sortKeysMap); + } + + return result; + } + + @Override + public void setState(Object o, State state) { + if (!(state instanceof JTableState)) { + throw new IllegalArgumentException("invalid state"); + } + + JTable table = checkComponent(o); + JTableState jTableState = (JTableState) state; + + int[] columnWidths = jTableState.getColumnWidths(); + if (columnWidths != null + && table.getColumnCount() == columnWidths.length) { + for (int i = 0; i < columnWidths.length; i++) { + if (columnWidths[i] != -1) { + TableColumn tc = table.getColumnModel().getColumn(i); + if (tc.getResizable()) { + tc.setPreferredWidth(columnWidths[i]); + } + } + } + } + Map<Integer, String> sortKeysMap = jTableState.getSortKeys(); + if (sortKeysMap != null) { + List<RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>(); + for (Integer index : sortKeysMap.keySet()) { + SortOrder sortOrder = SortOrder.valueOf(sortKeysMap.get(index)); + RowSorter.SortKey sortKey = new RowSorter.SortKey(index, sortOrder); + sortKeys.add(sortKey); + } + table.getRowSorter().setSortKeys(sortKeys); + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/JXTableSwingSessionState.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/JXTableSwingSessionState.java new file mode 100644 index 0000000..f2f73f3 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/JXTableSwingSessionState.java @@ -0,0 +1,109 @@ +package org.nuiton.jaxx.runtime.swing.session; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.jdesktop.swingx.JXTable; +import org.jdesktop.swingx.table.DefaultTableColumnModelExt; +import org.jdesktop.swingx.table.TableColumnExt; + +import javax.swing.table.TableColumn; +import java.util.List; +import java.util.Map; + +/** + * @author Kevin Morin - kmorin@codelutin.com + * @since 2.5.16 + */ +public class JXTableSwingSessionState extends JTableState { + + protected boolean[] hiddenColumns; + + public JXTableSwingSessionState() { + super(); + } + + public JXTableSwingSessionState(int[] columnWidths, Map<Integer, String> sortKeys, boolean[] hiddenColumns) { + super(columnWidths, sortKeys); + this.hiddenColumns = hiddenColumns; + } + + public boolean[] getHiddenColumns() { + return hiddenColumns; + } + + public void setHiddenColumns(boolean[] hiddenColumns) { + this.hiddenColumns = hiddenColumns; + } + + protected JXTable checkComponent(Object o) { + if (o == null) { + throw new IllegalArgumentException("null component"); + } + if (!(o instanceof JXTable)) { + throw new IllegalArgumentException("invalid component"); + } + return (JXTable) o; + } + + @Override + public State getState(Object o) { + JXTable table = checkComponent(o); + JXTableSwingSessionState result = new JXTableSwingSessionState(); + JTableState state = (JTableState) super.getState(o); + if (state != null) { + result.setColumnWidths(state.getColumnWidths()); + result.setSortKeys(state.getSortKeys()); + } + DefaultTableColumnModelExt columnModel = + (DefaultTableColumnModelExt) table.getColumnModel(); + List<TableColumn> columns = columnModel.getColumns(true); + boolean[] hiddenColumns = new boolean[columns.size()]; + for (int i = 0; i < hiddenColumns.length; i++) { + TableColumnExt tc = (TableColumnExt) columns.get(i); + hiddenColumns[i] = !tc.isVisible(); + } + result.setHiddenColumns(hiddenColumns); + + return result; + } + + @Override + public void setState(Object o, State state) { + if (!(state instanceof JXTableSwingSessionState)) { + throw new IllegalArgumentException("invalid state"); + } + super.setState(o, state); + JXTable table = checkComponent(o); + boolean[] hiddenColumns = ((JXTableSwingSessionState) state).getHiddenColumns(); + DefaultTableColumnModelExt columnModel = + (DefaultTableColumnModelExt) table.getColumnModel(); + List<TableColumn> columns = columnModel.getColumns(true); + int columnNb = columns.size(); + if (hiddenColumns != null && hiddenColumns.length == columnNb) { + for (int i = 0; i < columnNb; i++) { + TableColumnExt tc = (TableColumnExt) columns.get(i); + tc.setVisible(!hiddenColumns[i]); + } + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/State.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/State.java new file mode 100644 index 0000000..e2cfc7d --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/State.java @@ -0,0 +1,38 @@ +package org.nuiton.jaxx.runtime.swing.session; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/** + * get(save) and set(restore) state of object passed in argument + * + * @author poussin + * @author Kevin Morin - morin@codelutin.com + * @since 2.5.16 + */ +public interface State { + + State getState(Object o); + + void setState(Object o, State state); + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/SwingSession.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/SwingSession.java new file mode 100644 index 0000000..fb9af50 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/SwingSession.java @@ -0,0 +1,478 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.session; + + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Predicate; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTable; + +import javax.swing.JFrame; +import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; +import javax.swing.JTable; +import java.awt.Component; +import java.awt.Container; +import java.awt.Rectangle; +import java.awt.Window; +import java.beans.DefaultPersistenceDelegate; +import java.beans.Encoder; +import java.beans.ExceptionListener; +import java.beans.Expression; +import java.beans.XMLDecoder; +import java.beans.XMLEncoder; +import java.io.ByteArrayOutputStream; +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.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +/** + * Use to store and restore position and size of application. Default supported widgets are: + * <ul> + * <li> java.awt.Window (and subclasses)</li> + * <li> javax.swing.JTabbedPane (and subclasses)</li> + * <li> javax.swing.JSplitPane (and subclasses)</li> + * <li> org.jdesktop.swingx.JXTable (and subclasses)</li> + * <li> javax.swing.JTable (and subclasses)</li> + * </ul> + * + * usage: + * <ul> + * <li> create SwingSession object</li> + * <li> add component that you want save</li> + * <li> explicite call to save</li> + * </ul> + * You can use same SwingSession for multiple window but in this case you must + * have setName for each window with different name, otherwize there are + * collision between window component and result is undetermisitic. + * + * This code is partialy inspired from http://kenai.com/projects/bsaf/pages/Home + * project. This project is under LGPL v2.1 license. We can't reuse directly this + * library because to many fields and methods are private and we can't implements + * it and modify some behavior. + * + * @author poussin + * @author kmorin + * @since 2.5.16 + */ +public class SwingSession { + + private static final Log log = LogFactory.getLog(SwingSession.class); + + protected File file; + + protected boolean autoSave; + + protected Set<Component> registeredComponent = Sets.newIdentityHashSet(); + + /** + * State object registered to get and set State. + * key: class of component managed by the state; value: the state + */ + protected Map<Class, State> stateManager = Maps.newHashMap(); + + /** + * state of all component added with add method. + * key: path of compoenent; value: State + */ + protected Map<String, State> states; + + /** + * Create a new swing session with the given parameters. + * + * If it fails to read the given file, then it will delete it from the fs and starts with a new empty file. + * + * @return the new swing session + * @since 2.8.6 + * @deprecated since 2.10, the default behaviour is now to safely load the incoming file + */ + @Deprecated + public static SwingSession newSession(File file, boolean autoSave) { + return newSession(file, autoSave, Maps.<Class, State>newHashMap()); + } + + /** + * Create a new swing session with the given parameters. + * + * If it fails to read the given file, then it will delete it from the fs and starts with a new empty file. + * + * @return the new swing session + * @since 2.8.6 + * @deprecated since 2.10, the default behaviour is now to safely load the incoming file + */ + @Deprecated + public static SwingSession newSession(File file, boolean autoSave, Map<Class, State> additionalStates) { + return new SwingSession(file, autoSave, additionalStates); + } + + public SwingSession(File file, boolean autoSave) { + this(file, autoSave, Maps.<Class, State>newHashMap()); + } + + public SwingSession(File file, boolean autoSave, Map<Class, State> additionalStates) { + this.file = file; + this.autoSave = autoSave; + stateManager.put(Window.class, new WindowState()); + stateManager.put(JTable.class, new JTableState()); + stateManager.put(JTabbedPane.class, new JTabbedPaneState()); + stateManager.put(JSplitPane.class, new JSplitPaneState()); + stateManager.put(JXTable.class, new JXTableSwingSessionState()); + stateManager.putAll(additionalStates); + + if (file != null && file.exists()) { + + loadSafeStates(); + + } else { + + states =Maps.newHashMap(); + + } + + } + + public File getFile() { + return new File(file.getAbsolutePath()); + } + + public void setFile(File file) { + this.file = file; + } + + /** + * Loads safely the states from the {@link #file}. + * + * If could not read the internal file, then will try to delete it. + * @since 2.10 + */ + public void loadSafeStates() { + + try { + states = loadStates(file); + } catch (IOException e) { + // reset file + if (log.isErrorEnabled()) { + log.error("Could not read swing session file: " + file, e); + } + if (file.exists()) { + + // try to delete it + try { + FileUtils.forceDelete(file); + } catch (IOException e1) { + throw new RuntimeException("Could not delete file: " + file, e1); + } + } + + states = Maps.newHashMap(); + } + + if (states == null) { + states = Maps.newHashMap(); + } + + } + + @Override + protected void finalize() throws Throwable { + save(); + super.finalize(); + } + + + /* If an exception occurs in the XMLEncoder/Decoder, we want + * to throw an IOException. The exceptionThrow listener method + * doesn't throw a checked exception so we just set a flag + * here and check it when the encode/decode operation finishes + */ + static private class AbortExceptionListener implements ExceptionListener { + + public Exception exception = null; + + @Override + public void exceptionThrown(Exception e) { + if (exception == null) { + exception = e; + } + } + } + + /* There are some (old) Java classes that aren't proper beans. Rectangle + * is one of these. When running within the secure sandbox, writing a + * Rectangle with XMLEncoder causes a security exception because + * DefaultPersistenceDelegate calls Field.setAccessible(true) to gain + * access to private fields. This is a workaround for that problem. + * A bug has been filed, see JDK bug ID 4741757 + */ + private static class RectanglePD extends DefaultPersistenceDelegate { + + public RectanglePD() { + super(new String[]{"x", "y", "width", "height"}); + } + + @Override + protected Expression instantiate(Object oldInstance, Encoder out) { + Rectangle oldR = (Rectangle) oldInstance; + Object[] constructorArgs = new Object[]{ + oldR.x, oldR.y, oldR.width, oldR.height + }; + return new Expression(oldInstance, oldInstance.getClass(), "new", constructorArgs); + } + } + + public void save() throws IOException { + updateState(); + AbortExceptionListener el = new AbortExceptionListener(); + ByteArrayOutputStream bst = new ByteArrayOutputStream(); + XMLEncoder e = null; + /* Buffer the XMLEncoder's output so that decoding errors don't + * cause us to trash the current version of the specified file. + */ + try { + e = new XMLEncoder(bst); + e.setPersistenceDelegate(Rectangle.class, new RectanglePD()); + e.setExceptionListener(el); + e.writeObject(states); + } finally { + if (e != null) { + e.close(); + } + } + if (el.exception != null) { + try { + throw el.exception; + } catch (Exception e1) { + if (e1 instanceof IOException) { + throw (IOException) e1; + } else { + throw new IOException(e1); + } + } +// log.warn("save failed \"" + file + "\"", el.exception); + } else { + OutputStream ost = null; + try { + ost = new FileOutputStream(file); + ost.write(bst.toByteArray()); + + ost.close(); + } finally { + IOUtils.closeQuietly(ost); + + } + } + } + + /** + * Loads the states from the file + */ + public Map<String, State> loadStates(File file) throws IOException { + Map<String, State> result = null; + if (file.exists()) { + XMLDecoder d = null; + try { + InputStream ist = new FileInputStream(file); + d = new XMLDecoder(ist); + AbortExceptionListener eee = new AbortExceptionListener(); + d.setExceptionListener(eee); + Object bean = d.readObject(); + if (eee.exception != null) { + log.warn("load failed \"" + file + "\"", eee.exception); + throw eee.exception; + } else { + result = (Map<String, State>) bean; + } + + } catch (Exception e) { + if (e instanceof IOException) { + throw (IOException) e; + } else { + throw new IOException(e); + } + } finally { + if (d != null) { + d.close(); + } + } + } + return result; + } + + public void updateState() { + walkThrowComponent("", registeredComponent, + new SaveStateAction()); + } + + public void add(Component c) { + add(c, false); + } + + public void add(final Component c, boolean replace) { + if (c == null) { + return; + } + final String cName = getComponentName(c); + Object existingComponent = CollectionUtils.find(registeredComponent, + new Predicate<Object>() { + @Override + public boolean evaluate(Object o) { + Component comp = (Component) o; + String compName = getComponentName(comp); + return c.getClass().equals(comp.getClass()) + && cName.equals(compName); + } + }); + + if (existingComponent != null) { + if (replace) { + if (log.isDebugEnabled()) { + log.debug("replacing the component fir path /" + cName); + } + remove((Component) existingComponent); + + } else { + log.warn(String.format( + "Component already added %s(%s)", c.getClass(), c.getName())); + return; + } + } + + registeredComponent.add(c); + walkThrowComponent("", + Collections.singleton(c), + new RestoreStateAction()); + } + + /** + * Remove component from component to save + * + * @param c + */ + public void remove(Component c) { + registeredComponent.remove(c); + } + + protected String getComponentName(Component c) { + String name = c.getName(); + if (name == null) { + int n = c.getParent().getComponentZOrder(c); + if (n >= 0) { + Class clazz = c.getClass(); + name = clazz.getSimpleName(); + if (name.length() == 0) { + name = "Anonymous" + clazz.getSuperclass().getSimpleName(); + } + name = name + n; + } else { + // Implies that the component tree is changing + // while we're computing the path. Punt. + log.warn("Couldn't compute pathname for " + c); + } + } + return name; + } + + public State getStateManager(Class clazz) { + State result = null; + while (result == null && clazz != null) { + result = stateManager.get(clazz); + clazz = clazz.getSuperclass(); + } + return result; + } + + public void addToStateManager(Class component, State state) { + stateManager.put(component, state); + } + + public State getStates(String path) { + return states.get(path); + } + + public void setStates(String path, State state) { + this.states.put(path, state); + } + + protected void walkThrowComponent( + String path, Collection<Component> roots, Action action) { + for (Component root : roots) { + if (root != null) { + String pathname = path + "/" + getComponentName(root); + State state = getStateManager(root.getClass()); + if (state != null) { + action.doAction(this, pathname, root); + } + if (root instanceof Container) { + Component[] children = ((Container) root).getComponents(); + if ((children != null) && (children.length > 0)) { + walkThrowComponent(pathname, Arrays.asList(children), action); + } + } + if (root instanceof JFrame) { + Component[] children = ((JFrame) root).getContentPane().getComponents(); + if ((children != null) && (children.length > 0)) { + walkThrowComponent(pathname, Arrays.asList(children), action); + } + } + } + } + } + + public static interface Action { + public void doAction(SwingSession session, String path, Component c); + } + + public static class SaveStateAction implements Action { + @Override + public void doAction(SwingSession session, String path, Component c) { + State manager = session.getStateManager(c.getClass()); + State state = manager.getState(c); + session.setStates(path, state); + } + } + + public static class RestoreStateAction implements Action { + @Override + public void doAction(SwingSession session, String path, Component c) { + State manager = session.getStateManager(c.getClass()); + State state = session.getStates(path); + if (state != null) { + manager.setState(c, state); + } + } + } + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/WindowState.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/WindowState.java new file mode 100644 index 0000000..71bee91 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/session/WindowState.java @@ -0,0 +1,202 @@ +package org.nuiton.jaxx.runtime.swing.session; + +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import javax.swing.*; +import java.awt.*; + +/** + * State for Window + * + * @author poussin + * @author Kevin Morin - morin@codelutin.com + * @since 2.5.16 + */ +public class WindowState implements State { + + private static final String WINDOW_STATE_NORMAL_BOUNDS = + "WindowState.normalBounds"; + + protected Rectangle bounds; + protected Rectangle gcBounds; + protected int frameState = Frame.NORMAL; + + public WindowState() { + } + + public WindowState(Rectangle bounds, Rectangle gcBounds, int frameState) { + this.bounds = new Rectangle(bounds); + this.gcBounds = new Rectangle(gcBounds); + this.frameState = frameState; + } + + public Rectangle getBounds() { + return bounds; + } + + public void setBounds(Rectangle bounds) { + this.bounds = bounds; + } + + public Rectangle getGcBounds() { + return gcBounds; + } + + public void setGcBounds(Rectangle gcBounds) { + this.gcBounds = gcBounds; + } + + public int getFrameState() { + return frameState; + } + + public void setFrameState(int frameState) { + this.frameState = frameState; + } + + protected Window checkComponent(Object o) { + if (o == null) { + throw new IllegalArgumentException("null component"); + } + if (!(o instanceof Window)) { + throw new IllegalArgumentException("invalid component"); + } + return (Window) o; + } + + /** + * Checks whether the window supports resizing + * @param window the {@code Window} to be checked + * @return true if the window supports resizing + */ + protected static boolean isResizable(Window window) { + boolean resizable = true; + if (window instanceof Frame) { + resizable = ((Frame) window).isResizable(); + } else if (window instanceof Dialog) { + resizable = ((Dialog) window).isResizable(); + } + return resizable; + } + + /** + * Gets {@code Window} bounds from the client property + * @param window the source {@code Window} + * @return bounds from the client property + */ + protected static Rectangle getWindowNormalBounds(Window window) { + Rectangle result = null; + if (window instanceof JFrame) { + Object res = ((JFrame) window).getRootPane().getClientProperty( + WINDOW_STATE_NORMAL_BOUNDS); + if (res instanceof Rectangle) { + result = (Rectangle) res; + } + } + return result; + } + + /** + * Calculates virtual graphic bounds. + * On multiscreen systems all screens are united into one virtual screen. + * @return the graphic bounds + */ + public static Rectangle computeVirtualGraphicsBounds() { + Rectangle virtualBounds = new Rectangle(); + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] gs = ge.getScreenDevices(); + for (GraphicsDevice gd : gs) { + GraphicsConfiguration gc = gd.getDefaultConfiguration(); + virtualBounds = virtualBounds.union(gc.getBounds()); + } + return virtualBounds; + } + + /** + * Puts {@code Window} bounds to client property. + * @param window the target {@code Window} + * @param bounds bounds + */ + public static void putWindowNormalBounds(Window window, Rectangle bounds) { + if (window instanceof JFrame) { + ((JFrame) window).getRootPane().putClientProperty( + WINDOW_STATE_NORMAL_BOUNDS, bounds); + } + } + + @Override + public State getState(Object o) { + Window c = checkComponent(o); + int frameState = Frame.NORMAL; + if (c instanceof Frame) { + frameState = ((Frame) c).getExtendedState(); + } + GraphicsConfiguration gc = c.getGraphicsConfiguration(); + Rectangle gcBounds = (gc == null) ? null : gc.getBounds(); + Rectangle frameBounds = c.getBounds(); + + /* If this is a JFrame created by FrameView and it's been maximized, + * retrieve the frame's normal (not maximized) bounds. More info: + * see FrameStateListener#windowStateChanged in FrameView. + */ + if ((c instanceof JFrame) && (0 != (frameState & Frame.MAXIMIZED_BOTH))) { + frameBounds = getWindowNormalBounds(c); + } + + WindowState result = null; + if (frameBounds != null && !frameBounds.isEmpty()) { + result = new WindowState(); + result.setBounds(frameBounds); + result.setGcBounds(gcBounds); + result.setFrameState(frameState); + } + + return result; + } + + @Override + public void setState(Object o, State state) { + Window w = checkComponent(o); + if ((state != null) && !(state instanceof WindowState)) { + throw new IllegalArgumentException("invalid state"); + } + WindowState windowState = (WindowState) state; + if (windowState.getBounds() != null) { + putWindowNormalBounds(w, windowState.getBounds()); + if (!w.isLocationByPlatform() && (state != null)) { + + Rectangle gcBounds0 = windowState.getGcBounds(); + if (gcBounds0 != null && isResizable(w)) { + if (computeVirtualGraphicsBounds().contains(gcBounds0.getLocation())) { + w.setBounds(windowState.getBounds()); + } else { + w.setSize(windowState.getBounds().getSize()); + } + } + } + if (w instanceof Frame) { + ((Frame) w).setExtendedState(windowState.getFrameState()); + } + } + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/BusyChangeListener.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/BusyChangeListener.java new file mode 100644 index 0000000..ce97a27 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/BusyChangeListener.java @@ -0,0 +1,113 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.wizard; + +import org.nuiton.jaxx.runtime.swing.BlockingLayerUI; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Component; +import java.awt.Cursor; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * To listen the busy state of a {@link WizardModel}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public class BusyChangeListener implements PropertyChangeListener { + + /** Logger */ + private static final Log log = LogFactory.getLog(BusyChangeListener.class); + + protected Cursor busyCursor; + + protected Cursor defaultCursor; + + protected final Component ui; + + protected BlockingLayerUI blockingUI; + + public BusyChangeListener(Component ui) { + this.ui = ui; + } + + public Component getUi() { + return ui; + } + + public BlockingLayerUI getBlockingUI() { + return blockingUI; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + Boolean value = (Boolean) evt.getNewValue(); + if (log.isDebugEnabled()) { + log.debug("busy state changed to " + value); + } + if (value != null && value) { + setBusy(ui); + + } else { + setUnBusy(ui); + } + } + + public void setBlockingUI(BlockingLayerUI blockingUI) { + this.blockingUI = blockingUI; + } + + protected void setBusy(Component ui) { + if (ui != null) { + ui.setCursor(getBusyCursor()); + } + if (blockingUI != null) { + blockingUI.setBlock(true); + } + } + + protected void setUnBusy(Component ui) { + if (ui != null) { + ui.setCursor(getDefaultCursor()); + } + if (blockingUI != null) { + blockingUI.setBlock(false); + } + } + + protected Cursor getBusyCursor() { + if (busyCursor == null) { + busyCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); + } + return busyCursor; + } + + protected Cursor getDefaultCursor() { + if (defaultCursor == null) { + defaultCursor = Cursor.getDefaultCursor(); + } + return defaultCursor; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardModel.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardModel.java new file mode 100644 index 0000000..9c2c9c2 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardModel.java @@ -0,0 +1,306 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.wizard; + +import org.nuiton.jaxx.runtime.JAXXUtil; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * Un modèle de wizard. + * + * + * <b>Note:</b> le type des étapes doit être uné énumération qui implante {@link + * WizardStep}. + * + * @param <E> le type des étapes. + * @author Tony Chemit - chemit@codelutin.com + * @see WizardStep + * @since 1.3 + */ +public abstract class WizardModel<E extends WizardStep> { + + public static final String STEPS_PROPERTY_NAME = "steps"; + + public static final String STEP_PROPERTY_NAME = "step"; + + public static final String PREVIOUS_STEP_PROPERTY_NAME = "previousStep"; + + public static final String NEXT_STEP_PROPERTY_NAME = "nextStep"; + + public static final String VALID_STEP_PROPERTY_NAME = "validStep"; + + public static final String BUSY_PROPERTY_NAME = "busy"; + + /** le type d'une etape du model (doit etre une enumeration) */ + protected final Class<E> stepClass; + + /** Toutes les étapes à passer */ + protected List<E> steps; + + /** les etapes a exclure */ + protected List<E> excludeSteps; + + /** L'étape courante */ + protected E step; + + /** drapeau pour valider l'état de l'étape courante */ + protected boolean validStep; + + /** un drapeau pour savoir si le modèle est occupé. */ + private boolean busy; + + /** + * drapeau lorsque le modele effectue des operations de transformation de + * modele mais que les écouteurs ne devraient pas tenir compte des + * modifications + */ + protected boolean valueAdjusting; + + /** pour propager les changements dans le modèle vers l'ui */ + protected PropertyChangeSupport pcs; + + public WizardModel(Class<E> stepClass, E... steps) { + if (!Enum.class.isAssignableFrom(stepClass)) { + throw new IllegalArgumentException("stepClass must be an" + + " Enumeration but was " + stepClass.getName()); + } + this.stepClass = stepClass; + pcs = new PropertyChangeSupport(this); + this.steps = new ArrayList<E>(); + if (steps.length > 0) { + setSteps(steps); + } + } + + public void start() { + if (steps.isEmpty()) { + throw new IllegalStateException("can not start, no step found"); + } + step = null; + E startStep = steps.get(0); + setStep(startStep); + } + + public void destroy() { + // suppression de tous les listeners + JAXXUtil.destroy(pcs); + } + + public void gotoNextStep() { + E nextStep = getNextStep(); + if (nextStep == null) { + throw new IllegalStateException("no next step to go"); + } + setStep(nextStep); + } + + public void gotoPreviousStep() { + E previousStep = getPreviousStep(); + if (previousStep == null) { + throw new IllegalStateException("no previous step to go"); + } + setStep(previousStep); + } + + public void gotoStep(E e) { + if (e == null) { + throw new NullPointerException("step can not be null"); + } + if (!steps.contains(e)) { + throw new IllegalStateException("step " + e.toString() + + " is not in universe of steps (" + steps + ')'); + } + setBusy(true); + try { + setStep(e); + } finally { + setBusy(false); + } + } + + public E getStep() { + return step; + } + + public int getStepIndex(E s) { + return steps.indexOf(s); + } + + public boolean isValidStep() { + return validStep; + } + + public E getPreviousStep() { + return getPreviousStep(step); + } + + public E getPreviousStep(E step) { + int index = getStepIndex(step); + if (index < 1) { + // si pas de step ou sur premier step + return null; + } + return steps.get(index - 1); + } + + public E getNextStep(E step) { + int index = getStepIndex(step); + if (index < 1) { + // si pas de step ou sur premier step + return null; + } + return steps.get(index - 1); + } + + public E getNextStep() { + int index = getStepIndex(step); + if (index == -1 || index == steps.size() - 1) { + // si pas de step positionne ou dernier etape + return null; + } + return steps.get(index + 1); + } + + public List<E> getSteps() { + return steps; + } + + public boolean containsStep(E step) { + return getSteps().contains(step); + } + + public boolean isValueAdjusting() { + return valueAdjusting; + } + + public boolean isBusy() { + return busy; + } + + public void setBusy(boolean busy) { + boolean oldValue = this.busy; + this.busy = busy; + firePropertyChange(BUSY_PROPERTY_NAME, oldValue, busy); + } + + /** + * Change l'univers des etapes. + * + * Note: on presume ici que l'étape courante est toujours la meme. + * + * @param steps le nouvel univers des etapes + */ + public void setSteps(E... steps) { + List<E> oldValue = this.steps; + this.steps = Collections.unmodifiableList(Arrays.asList(steps)); + firePropertyChange(STEPS_PROPERTY_NAME, oldValue, this.steps); + // la propriete nextStep peut avoir changee + firePropertyChange(NEXT_STEP_PROPERTY_NAME, null, getNextStep()); + } + + public void setValueAdjusting(boolean valueAdjusting) { + this.valueAdjusting = valueAdjusting; + } + + public void setExcludeSteps(List<E> excludeSteps) { + this.excludeSteps = excludeSteps; + } + + public boolean validate(E s) { + return step != null; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListeners() { + JAXXUtil.destroy(pcs); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + destroy(); + } + + public void validate() { + if (step == null) { + // pas de validation quand aucune etape n'est sélectionnée + return; + } + validStep = validate(step); + // toujours forcer la propagation + firePropertyChange(VALID_STEP_PROPERTY_NAME, null, validStep); + } + + public abstract void updateUniverse(); + + public Class<E> getStepClass() { + return stepClass; + } + + protected void setStep(E step) { + E oldValue = this.step; + this.step = step; + firePropertyChange(STEP_PROPERTY_NAME, oldValue, step); + // la propriete nextStep peut avoir changee + firePropertyChange(NEXT_STEP_PROPERTY_NAME, null, getNextStep()); + // la propriete previousStep peut avoir changee + firePropertyChange(PREVIOUS_STEP_PROPERTY_NAME, null, getPreviousStep()); + validate(); + } + + protected void firePropertyChange(String propertyName, Object oldValue, + Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + protected void firePropertyChange(String propertyName, Object newValue) { + pcs.firePropertyChange(propertyName, null, newValue); + } + + protected void fireIndexedPropertyChange(String propertyName, int index, + Object oldValue, Object newValue) { + pcs.fireIndexedPropertyChange(propertyName, index, oldValue, newValue); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardStep.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardStep.java new file mode 100644 index 0000000..8125fc1 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardStep.java @@ -0,0 +1,41 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.wizard; + +import java.io.Serializable; + +/** + * le contrat d'une étape d'un wizard. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.3 + */ +public interface WizardStep extends Serializable { + + String name(); + + int ordinal(); + + String getLabel(); + + String getDescription(); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardStepUI.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardStepUI.java new file mode 100644 index 0000000..8b7f2c9 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardStepUI.java @@ -0,0 +1,35 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.wizard; + +/** + * Le contrat d'une ui d'étape. + * + * @param <E> le type d'étape + * @param <M> le type de modèle + * @author Tony Chemit - chemit@codelutin.com + * @since 1.3 + */ +public interface WizardStepUI<E extends WizardStep, M extends WizardModel<E>> { + + E getStep(); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardUI.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardUI.java new file mode 100644 index 0000000..042037f --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardUI.java @@ -0,0 +1,82 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.wizard; + +import javax.swing.JTabbedPane; + +/** + * Contrat a respecter pour une ui de wizard. + * + * @param <E> le type d'etape + * @param <M> le type de model + * @author Tony Chemit - chemit@codelutin.com + * @since 1.3 + */ +public interface WizardUI<E extends WizardStep, M extends WizardModel<E>> { + + /** @return le modèle de wizard */ + M getModel(); + + /** @return l'étape courante */ + E getSelectedStep(); + + /** @return l'ui de l'étape courante */ + WizardStepUI<E, M> getSelectedStepUI(); + + /** + * @param step l'étape donnée + * @return l'ui de l'étape donnée + */ + WizardStepUI<E, M> getStepUI(E step); + + /** + * @param stepIndex la position de l'étape + * @return l'ui de l'étape donée + */ + WizardStepUI<E, M> getStepUI(int stepIndex); + + /** démarre le wizard */ + void start(); + + /** + * //TODO il faudrait supprimer cette méthode + * + * @return le conteneur d'ui d'étapes + */ + JTabbedPane getTabs(); + + /** + * Méthode invoquée lorsque l'univers des étapes a été modifié dans le + * modèle. + * + * @param steps les nouvelles étapes + */ + void onStepsChanged(E[] steps); + + /** + * Méthode invoquée lorsque l'étape courante a changé dans le modèle. + * + * @param oldStep l'ancienne étape + * @param newStep la nouvelle étape courante + */ + void onStepChanged(E oldStep, E newStep); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardUILancher.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardUILancher.java new file mode 100644 index 0000000..5e62905 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardUILancher.java @@ -0,0 +1,250 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.wizard; + +import org.nuiton.jaxx.runtime.JAXXContext; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.context.JAXXContextEntryDef; +import org.nuiton.jaxx.runtime.context.JAXXInitialContext; + +import javax.swing.ImageIcon; +import java.awt.Window; + +/** + * Une classe pour lancer une ui de wizard. + * + * @param <E> le type des etapes + * @param <M> le type de modele + * @param <UI> le type d'ui + * @author Tony Chemit - chemit@codelutin.com + * @since 1.3 + */ +public abstract class WizardUILancher<E extends WizardStep, M extends WizardModel<E>, UI extends WizardUI<E, M>> { + + /** the jaxx context entry to store the apply action */ + public static final JAXXContextEntryDef<Runnable> APPLY_DEF = + JAXXUtil.newContextEntryDef("apply", Runnable.class); + + /** the jaxx context entry to store the cancel action */ + public static final JAXXContextEntryDef<Runnable> CANCEL_DEF = + JAXXUtil.newContextEntryDef("cancel", Runnable.class); + + public static <M extends WizardModel<?>> JAXXContextEntryDef<M> newModelEntry(Class<M> modelType) { + return JAXXUtil.newContextEntryDef("incoming", modelType); + } + + protected UI ui; + + public WizardUILancher(JAXXContext context, + Class<UI> uiClass, + Class<M> modelClass, + String title, + String tip, + ImageIcon icon) { + this(context, uiClass, modelClass, null, title, tip, icon); + } + + public WizardUILancher(JAXXContext context, + Class<UI> uiClass, + Class<M> modelClass, + M model, + String title, + String tip, + ImageIcon icon) { + try { + ui = createUI(context, + uiClass, + modelClass, + model, + title, + tip, + icon + ); + } catch (Exception ex) { + throw new RuntimeException( + "could not instanciate launcher for reason " + + ex.getMessage(), ex); + } + } + + public WizardUILancher(JAXXContext context, + Window mainUI, + Class<UI> uiClass, + Class<M> modelClass, + M model) { + try { + ui = createUI(context, + mainUI, + uiClass, + modelClass, + model + ); + } catch (Exception ex) { + throw new RuntimeException( + "could not instanciate launcher for reason " + + ex.getMessage(), ex); + } + } + + public WizardUILancher(JAXXContext context, + Window mainUI, + Class<UI> uiClass, + Class<M> modelClass) { + this(context, mainUI, uiClass, modelClass, null); + } + + public void start() { + init(ui); + start(ui); + } + + protected void start(UI ui) { + ui.start(); + } + + public <T> T getContextValue(Class<T> clazz, String name) { + if (ui == null) { + throw new NullPointerException("ui can not be null"); + } + if (!(ui instanceof JAXXObject)) { + throw new ClassCastException("ui can not be casted to JAXXObject "); + } + + return ((JAXXObject) ui).getContextValue(clazz, name); + } + + public <T> T getContextValue(Class<T> clazz) { + return getContextValue(clazz, null); + } + + protected void init(UI ui) { + } + + protected void doAction(UI ui) { + } + + protected void doCancel(UI ui) { + } + + protected void doClose(UI ui, boolean wasCanceld) { + } + + protected UI createUI(JAXXContext context, + Window mainUI, + Class<UI> uiClass, + Class<M> modelClass, + M model) throws Exception { + JAXXInitialContext uiContext = new JAXXInitialContext(); + uiContext.add(mainUI == null ? context : mainUI); + // parent context model + uiContext.add(modelClass.newInstance()); + if (model != null) { + uiContext.add(newModelEntry(modelClass), model); + } + // apply action + uiContext.add(APPLY_DEF, new Runnable() { + + @Override + public void run() { + try { + doAction(ui); + } finally { + doClose(ui, false); + } + } + }); + // cancel action + uiContext.add(CANCEL_DEF, new Runnable() { + + @Override + public void run() { + try { + doCancel(ui); + } finally { + doClose(ui, true); + } + } + }); + + // instanciate ui + + return JAXXUtil.invokeConstructor( + uiClass, + new Class[]{Window.class, JAXXContext.class}, + mainUI, uiContext + ); + } + + protected UI createUI(JAXXContext context, + Class<UI> uiClass, + Class<M> modelClass, + M model, + String title, + String tip, + ImageIcon icon) throws Exception { + JAXXInitialContext uiContext = new JAXXInitialContext(); + uiContext.add(context); + // parent context model + uiContext.add(modelClass.newInstance()); + if (model != null) { + uiContext.add(newModelEntry(modelClass), model); + } + // apply action + uiContext.add(APPLY_DEF, new Runnable() { + + @Override + public void run() { + try { + doAction(ui); + } finally { + doClose(ui, false); + } + } + }); + + // cancel action + uiContext.add(CANCEL_DEF, new Runnable() { + + @Override + public void run() { + try { + doCancel(ui); + } finally { + doClose(ui, true); + } + } + }); + + // instanciate ui + return JAXXUtil.invokeConstructor( + uiClass, + new Class[]{ + JAXXContext.class, + String.class, + String.class, + ImageIcon.class + }, + uiContext, title, tip, icon + ); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardUtil.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardUtil.java new file mode 100644 index 0000000..a158fe6 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/WizardUtil.java @@ -0,0 +1,191 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.wizard; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JTabbedPane; +import java.awt.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Array; +import java.util.List; + +import static org.nuiton.i18n.I18n.t; + +/** + * Classe de méthodes utiles sur les wizard. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.3 + */ +public class WizardUtil { + + /** Logger */ + static private Log log = LogFactory.getLog(WizardUI.class); + + protected WizardUtil() { + } + +// public static boolean acceptStates(WizardState state, WizardState... accepted) { +// for (WizardState s : accepted) { +// if (s == state) { +// return true; +// } +// } +// return false; +// } +// +// public static boolean rejectStates(WizardState state, WizardState... rejected) { +// for (WizardState s : rejected) { +// if (s == state) { +// return false; +// } +// } +// return true; +// } + + public static void addDebugLogListener(final Log log, WizardModel<?> model) { + if (log.isDebugEnabled()) { + model.addPropertyChangeListener(new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + log.debug(evt.getPropertyName() + " <" + evt.getOldValue() + " - " + evt.getNewValue() + ">"); + } + }); + } + } + + public static void addTraceLogListener(final Log log, WizardModel<?> model) { + if (log.isTraceEnabled()) { + model.addPropertyChangeListener(new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + log.trace(evt.getPropertyName() + " <" + evt.getOldValue() + " - " + evt.getNewValue() + ">"); + } + }); + } + } + + public static <E extends WizardStep, M extends WizardModel<E>> void installWizardUIListeners(final WizardUI<E, M> ui) { + ui.getModel().addPropertyChangeListener(new PropertyChangeListener() { + + @Override + @SuppressWarnings("unchecked") + public void propertyChange(PropertyChangeEvent evt) { + String propertyName = evt.getPropertyName(); +// if (WizardExtModel.WAS_STARTED_PROPERTY_NAME.equals(propertyName)) { +// ui.onWasStarted(); +// return; +// } + if (WizardModel.STEPS_PROPERTY_NAME.equals(propertyName)) { + List<E> steps = (List<E>) evt.getNewValue(); + ui.onStepsChanged( + steps.toArray((E[]) Array.newInstance( + ui.getModel().stepClass, steps.size())) + ); + return; + } + if (WizardModel.STEP_PROPERTY_NAME.equals(propertyName)) { + ui.onStepChanged((E) evt.getOldValue(), (E) evt.getNewValue()); +// return; + } + /*if (WizardModel.VALID_STEP_PROPERTY_NAME.equals(propertyName)) { + Boolean value = (Boolean) evt.getNewValue(); + if (value == null || !value) { + ui.onModelStateChanged(WizardState.NEED_FIX); + } else { + ui.onModelStateChanged(WizardState.PENDING); + } + return; + } + if (WizardExtModel.MODEL_STATE_PROPERTY_NAME.equals(propertyName)) { + //TODO should be unicast : only for good stepUI ? + ui.onModelStateChanged((WizardState) evt.getNewValue()); + return; + } + if (WizardExtModel.STEP_STATE_PROPERTY_NAME.equals(propertyName)) { + IndexedPropertyChangeEvent e = (IndexedPropertyChangeEvent) evt; + int stepIndex = e.getIndex(); + E step = ui.getModel().getSteps().get(stepIndex); + ui.onOperationStateChanged(step, (WizardState) evt.getNewValue()); + return; + }*/ + } + }); + } + + /** + * Ajoute un listener sur le modele pour gere la politique d'affichage des + * onglets. + * + * Dans cette implantation, les onglets sont ouverts jusqu'a l'etape + * courante. Lorsque l'on revient en arrière, les onglets d'etapes + * superieurs sont fermes. + * + * @param <E> le type d'un etape de l'assistant + * @param <M> le type du modele de l'assistant + * @param ui l'ui de l'assitant + * @since 1.7.1 + */ + public static <E extends WizardStep, M extends WizardModel<E>> void addTabsDisplayUntilStepListener(final WizardUI<E, M> ui) { + // on écoute les changements d'étapes + ui.getModel().addPropertyChangeListener(WizardModel.STEP_PROPERTY_NAME, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + M model = (M) evt.getSource(); + E oldStep = (E) evt.getOldValue(); + E newStep = (E) evt.getNewValue(); + log.debug("step has changed <old:" + oldStep + ", new:" + newStep + ">"); + int oldStepIndex = oldStep == null ? -1 : model.getStepIndex(oldStep); + int newStepIndex = model.getStepIndex(newStep); + JTabbedPane tabs = ui.getTabs(); + if (oldStepIndex + 1 == newStepIndex) { + // creation d'un nouvel onglet + WizardStepUI<E, M> c = ui.getStepUI(newStep); + String title = t(newStep.getLabel()); + String tip = t(newStep.getDescription()); + tabs.addTab(title, null, (Component) c, tip); + // selection du nouvel onglet + int index = tabs.indexOfComponent((Component) c); + if (index > -1) { + tabs.setSelectedIndex(index); + } + } else if (oldStepIndex > newStepIndex) { + // il s'agit d'un retour en arrière + // on supprime tous les onglets obsoletes + int index = newStepIndex + 1; + while (tabs.getTabCount() > index) { + log.trace("remove tab : " + index); + tabs.remove(index); + } + } else { + throw new IllegalStateException("can not go from " + oldStep + " to " + newStep); + } + } + }); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtModel.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtModel.java new file mode 100644 index 0000000..433eb01 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtModel.java @@ -0,0 +1,435 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.wizard.ext; + +import org.nuiton.jaxx.runtime.swing.wizard.WizardModel; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Un modèle de wizard avec des opérations. + * + * @param <E> le type des étapes. + * @author Tony Chemit - chemit@codelutin.com + * @since 1.3 + */ +public abstract class WizardExtModel<E extends WizardExtStep> extends WizardModel<E> { + + /** Logger */ + private static final Log log = LogFactory.getLog(WizardExtModel.class); + + public static final String OPERATIONS_PROPERTY_NAME = "operations"; + + public static final String STEP_STATE_PROPERTY_NAME = "stepState"; + + public static final String MODEL_STATE_PROPERTY_NAME = "modelState"; + + public static final String WAS_STARTED_PROPERTY_NAME = "wasStarted"; + + /** La liste des opérations à effectuer */ + protected Set<E> operations; + + /** le dictionnaire des modèles d'opération */ + protected final Map<E, WizardExtStepModel<E>> models; + + /** Pour conserver les états des opérations */ + protected Map<E, WizardState> stepStates; + + /** L'état générale du modèle */ + protected WizardState modelState; + + /** un drapeau pour savoir siune opération a été lancée */ + protected boolean wasStarted; + + @SuppressWarnings("unchecked") + public <T extends Enum<T>> WizardExtModel(Class<E> stepClass, E... steps) { + super(stepClass, steps); + Class<T> k = (Class<T>) stepClass; + stepStates = new EnumMap(k); + operations = (Set<E>) EnumSet.noneOf(k); + models = (Map<E, WizardExtStepModel<E>>) new EnumMap(k); + } + + public Set<E> getOperations() { + return operations; + } + + public WizardState getModelState() { + return modelState; + } + + public boolean isWasStarted() { + return wasStarted; + } + + public boolean containsOperation(E step) { + return getOperations().contains(step); + } + + @SuppressWarnings("unchecked") + public E getOperation() { + return getStep() != null && getStep().isOperation() ? getStep() : null; + } + + public WizardState getStepState() { + E operation = getOperation(); + return getStepState(operation); + } + + public WizardState getStepState(E step) { + return stepStates.get(step); + } + + public void setStepState(WizardState newState) { + E operation = getOperation(); + setStepState(operation, newState); + } + + public void setStepState(E step, WizardState newState) { + WizardState oldValue = getStepState(step); + stepStates.put(step, newState); + if (valueAdjusting) { + return; + } + fireIndexedPropertyChange(STEP_STATE_PROPERTY_NAME, getSteps().indexOf(step), oldValue, newState); + updateModelState(step, newState); + validate(); + } + + public boolean[] getAccessibleSteps() { + if (log.isDebugEnabled()) { + log.debug("compute with steps " + getSteps()); + } + boolean[] result = new boolean[getSteps().size()]; + int index = getSteps().indexOf(getStep()); + if (index != -1) { + + for (int i = 0, j = steps.size(); i < j; i++) { + if (i <= index) { + // tous les onglets inferieur ou egal au courant sont accessibles + result[i] = true; + continue; + } + // les onglets au dela de l'onglet sélectionné sont accessibles + // uniquement si l'onglet precedent est accessible, valide et son etat est a SUCCESSED + E previousStep = steps.get(i - 1); + result[i] = modelState == WizardState.SUCCESSED || + result[i - 1] && + validate(previousStep) && + (!previousStep.isOperation() || getStepState(previousStep) == WizardState.SUCCESSED); + } + } + if (log.isDebugEnabled()) { + log.debug("accessibles steps -------- " + Arrays.toString(result)); + } + return result; + } + + @Override + public void start() { +// super.start(); + + if (steps.isEmpty()) { + throw new IllegalStateException("can not start, no step found"); + } + + // update universe of steps and actions + updateUniverse(); + + // set first step + step = null; + E startStep = steps.get(0); + setStep(startStep); + + // model is ready + setModelState(WizardState.PENDING); + + validate(); + } + + public void cancel() { + + for (E op : operations) { + if (getStepState(op) == WizardState.PENDING) { + // on annule l'opération à venir + setStepState(op, WizardState.CANCELED); + } + } + setModelState(WizardState.CANCELED); + } + + public WizardExtModel<E> addOperation(E operation) { + if (operations.contains(operation)) { + + // skip add + return this; + } + + log.info("Add operation " + operation); + operations.add(operation); + // mis a jour de l'univers des etapes et operations + updateUniverse(); + // validation + validate(); + return this; + } + + public void removeOperation(E operation) { + if (!operations.contains(operation)) { + + // skip remove + return; + } + operations.remove(operation); + + // mis a jour de l'univers des etapes et operations + updateUniverse(); + // validation + validate(); + } + + @Override + public void setSteps(E... steps) { + super.setSteps(steps); + if (valueAdjusting) { + return; + } + // on force la propagation de la nouvelle liste + firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations); + } + + public WizardExtStepModel<E> getStepModel(E operation) { + if (operation == null) { + return null; + } + if (!operation.isOperation()) { + throw new IllegalStateException("step [" + operation + "] is not an operation."); + } + return models.get(operation); + } + + public void updateStepStates(List<E> steps) { + int index = 0; + for (E e : steps) { + fireIndexedPropertyChange(STEP_STATE_PROPERTY_NAME, index++, null, getStepState(e)); + } + firePropertyChange(MODEL_STATE_PROPERTY_NAME, null, modelState); + } + + protected void setModelState(WizardState modelState) { + WizardState oldValue = this.modelState; + this.modelState = modelState; + firePropertyChange(MODEL_STATE_PROPERTY_NAME, oldValue, modelState); + if (!wasStarted) { + if ((oldValue == null || oldValue == WizardState.PENDING) && modelState == WizardState.RUNNING) { + wasStarted = true; + firePropertyChange(WAS_STARTED_PROPERTY_NAME, false, true); + } + } + } + + protected void updateModelState(E step, WizardState newState) { + + switch (newState) { + case RUNNING: + //le modele est occupé + setModelState(WizardState.RUNNING); + break; + case FAILED: + //le modele est en erreur + setModelState(WizardState.FAILED); + break; + case CANCELED: + //le modele devient annulé + setModelState(WizardState.CANCELED); + return; + case PENDING: + //le modele est en attente + setModelState(WizardState.PENDING); + break; + case NEED_FIX: + //le modele est en attente + setModelState(WizardState.PENDING); + break; + case SUCCESSED: + // on regarde si on peut passer le model a l'état success + boolean valid = true; + for (E o : operations) { + if (getStepState(o) != WizardState.SUCCESSED) { + valid = false; + break; + } + } + if (valid) { + setModelState(WizardState.SUCCESSED); + } else { + setModelState(WizardState.PENDING); + } + break; + } + updateStepStates(steps); + } + + @Override + public void updateUniverse() { +// setValueAdjusting(true); + + List<E> oldSteps = new ArrayList<E>(getSteps()); + log.info("Start updateUniverse (oldSteps = " + oldSteps + ")"); + E[] newSteps = updateStepUniverse(); + log.info("newSteps = " + Arrays.toString(newSteps)); + + // do nothing if steps has not changed + boolean skip = true; + for (E newStep : newSteps) { + if (!oldSteps.contains(newStep)) { + skip = false; + } + } + + if (skip && oldSteps.size() == newSteps.length) { + + // same steps, so nothing to do + log.info("Steps are same, do not modify anything"); + return; + } + + for (WizardExtStepModel<E> model : models.values()) { + log.info("Destroy previous model : " + model); + model.destroy(); + } + models.clear(); + + List<E> toAdd = new ArrayList<E>(Arrays.asList(newSteps)); + + log.info("Will add models for " + toAdd); + + Iterator<E> itr = toAdd.iterator(); + while (itr.hasNext()) { + + E step = itr.next(); + + if (step.getModelClass() == null) { + + // no model attach to the step + itr.remove(); + continue; + } + + if (step.isOperation()) { + + // step is operation, model must be instanciate + WizardExtStepModel<E> model = (WizardExtStepModel<E>) step.newModel(); + if (log.isInfoEnabled()) { + log.info("[" + step + "] Add primary model " + model); + } + models.put(step, model); + + itr.remove(); + } + + // step has a model + } + + if (!toAdd.isEmpty()) { + + // there is some steps with model to attach + itr = toAdd.iterator(); + while (itr.hasNext()) { + + E step = itr.next(); + Class<? extends WizardExtStepModel<?>> modelClass = step.getModelClass(); + WizardExtStepModel<E> selectedModel = null; + // find out in models a + for (WizardExtStepModel<E> model : models.values()) { + if (modelClass.isAssignableFrom(model.getClass())) { + // find one + selectedModel = model; + break; + } + } + + if (selectedModel == null) { + throw new IllegalStateException("Could not find a primary model " + modelClass + " for step [" + step + "]"); + } + + log.info("[" + step + "] Attach model " + selectedModel); + models.put(step, selectedModel); + itr.remove(); + } + + if (!toAdd.isEmpty()) { + throw new IllegalStateException("There is some step no model : " + toAdd); + } + } + + setSteps(newSteps); + + // on met a jour les états des étapes + stepStates.clear(); + for (E step : newSteps) { + if (!stepStates.containsKey(step)) { + setStepState(step, WizardState.PENDING); + } + } + + // finally set the steps (this will refire a lot) + + log.info("Ending updateUniverse"); + +// setValueAdjusting(false); + } + + protected abstract E[] updateStepUniverse(); + + @Override + public void destroy() { + super.destroy(); + + for (WizardExtStepModel<E> model : models.values()) { + if (log.isDebugEnabled()) { + log.debug("destroy model " + model); + } + model.destroy(); + } + } + + protected int getOperationIndex(E operation) { + int index = 0; + for (E o : operations) { + if (o.equals(operation)) { + return index; + } + index++; + } + return -1; + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtStep.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtStep.java new file mode 100644 index 0000000..5c9f963 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtStep.java @@ -0,0 +1,75 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.wizard.ext; + +import org.nuiton.jaxx.runtime.swing.wizard.WizardStep; +import org.nuiton.jaxx.runtime.swing.wizard.WizardStepUI; + + +/** + * Extension de {@link WizardStep} avec des états supplémentaires. + * + * Chaque étape possède un modèle de type {@link #getModelClass()}. + * Ce modèle peut être partagé par plusieurs étapes. + * + * De plus, on a deux drapeaux {@link #isConfig()} pour savoir si l'étape est une phase de configuration. + * + * Le drapeau {@link #isOperation()} quand à lui permet de savoir si l'étape est une opération. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public interface WizardExtStep extends WizardStep { + + /** @return le label de l'opération */ + String getOperationLabel(); + + /** @return la description de l'opération */ + String getOperationDescription(); + + /** @return le type du modèle de l'action */ + Class<? extends WizardExtStepModel<?>> getModelClass(); + + /** @return le type de l'ui de l'opération */ + Class<? extends WizardStepUI<?, ?>> getUiClass(); + + /** @return {@code true} si l'étape a une opération associée, {@code false} sinon. */ + boolean isOperation(); + + /** @return {@code true} si l'étape est une phase de configuration, {@code false} sinon. */ + boolean isConfig(); + + /** + * Instancie le modèle associée à l'étape. + * + * @return le nouveau modèle associé à l'étape + */ + WizardExtStepModel<?> newModel(); + + /** + * Construit l'ui associée à l'étape. + * + * @param ui l'ui principale du wiard + * @return la noveau ui associé à l'étape + */ + WizardStepUI<?, ?> newUI(WizardExtUI<?, ?> ui); +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtStepModel.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtStepModel.java new file mode 100644 index 0000000..d33e23c --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtStepModel.java @@ -0,0 +1,108 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.wizard.ext; + +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +/** + * Abstract model of {@link WizardExtStep}. + * + * @author Tony Chemit - chemit@codelutin.com + * @see WizardExtStep + * @since 2.1 + */ +public abstract class WizardExtStepModel<E extends WizardExtStep> { + + /** Logger */ + private static final Log log = LogFactory.getLog(WizardExtStepModel.class); + + /** for properties change support */ + private final PropertyChangeSupport pcs; + + /** step of the model */ + protected final E step; + + /** to store if an error occurs while running */ + protected Exception error; + + protected WizardExtStepModel(E step) { + this.step = step; + pcs = new PropertyChangeSupport(this); + } + + public final E getStep() { + return step; + } + + public final Exception getError() { + return error; + } + + public void setError(Exception error) { + this.error = error; + } + + public final void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public final void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + + public final void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public final void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + public void destroy() { + if (log.isDebugEnabled()) { + log.debug("will destroy " + this); + } + + // remove all listeners + JAXXUtil.destroy(pcs); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + destroy(); + } + + protected final void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + protected final void firePropertyChange(String propertyName, Object newValue) { + pcs.firePropertyChange(propertyName, null, newValue); + } +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtUI.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtUI.java new file mode 100644 index 0000000..5ea8ef0 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtUI.java @@ -0,0 +1,57 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.wizard.ext; + +import org.nuiton.jaxx.runtime.swing.wizard.WizardUI; + +/** + * Contrat a respecter pour une ui de wizard. + * + * @param <E> le type d'etape + * @param <M> le type de model + * @author Tony Chemit - chemit@codelutin.com + * @since 1.3 + */ +public interface WizardExtUI<E extends WizardExtStep, M extends WizardExtModel<E>> extends WizardUI<E, M> { + + /** Méthode invoqué lorsque le modèle a été initialisé. */ + void onWasInit(); + + /** Méthode invoqué lorsque la première opération du modèlé a été démarrée. */ + void onWasStarted(); + + /** + * Méthode invoquée lorsque l'état interne du modèle a changé. + * + * @param newState le nouvelle état du modèle de wizard + */ + void onModelStateChanged(WizardState newState); + + /** + * Méthode invoqué lorsque l'état d'une opération a changé. + * + * @param step l'étape dont l'état a changé + * @param newState le nouvel état pour l'étape donné + */ + void onOperationStateChanged(E step, WizardState newState); + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtUtil.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtUtil.java new file mode 100644 index 0000000..2a13d49 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardExtUtil.java @@ -0,0 +1,121 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.wizard.ext; + +import org.nuiton.jaxx.runtime.swing.wizard.WizardModel; +import org.nuiton.jaxx.runtime.swing.wizard.WizardUI; +import org.nuiton.jaxx.runtime.swing.wizard.WizardUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.IndexedPropertyChangeEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Array; +import java.util.List; + +/** + * Classe de méthodes utiles sur les wizard. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.3 + */ +public class WizardExtUtil extends WizardUtil { + + /** Logger */ + static private Log log = LogFactory.getLog(WizardUI.class); + + protected WizardExtUtil() { + } + + public static boolean acceptStates(WizardState state, WizardState... accepted) { + for (WizardState s : accepted) { + if (s == state) { + return true; + } + } + return false; + } + + public static boolean rejectStates(WizardState state, WizardState... rejected) { + for (WizardState s : rejected) { + if (s == state) { + return false; + } + } + return true; + } + + public static <E extends WizardExtStep, M extends WizardExtModel<E>> void installWizardUIListeners(final WizardExtUI<E, M> ui) { + + + PropertyChangeListener dispatcher = new PropertyChangeListener() { + + @Override + @SuppressWarnings("unchecked") + public void propertyChange(PropertyChangeEvent evt) { + String propertyName = evt.getPropertyName(); + if (WizardExtModel.WAS_STARTED_PROPERTY_NAME.equals(propertyName)) { + ui.onWasStarted(); + return; + } + WizardExtModel<E> model = (WizardExtModel<E>) evt.getSource(); + if (WizardModel.STEPS_PROPERTY_NAME.equals(propertyName)) { + List<E> steps = (List<E>) evt.getNewValue(); + ui.onStepsChanged( + steps.toArray((E[]) Array.newInstance( + model.getStepClass(), steps.size())) + ); + return; + } + if (WizardModel.STEP_PROPERTY_NAME.equals(propertyName)) { + ui.onStepChanged((E) evt.getOldValue(), (E) evt.getNewValue()); + return; + } + if (WizardModel.VALID_STEP_PROPERTY_NAME.equals(propertyName)) { + Boolean value = (Boolean) evt.getNewValue(); + if (value == null || !value) { + ui.onModelStateChanged(WizardState.NEED_FIX); + } else { + ui.onModelStateChanged(WizardState.PENDING); + } + return; + } + if (WizardExtModel.MODEL_STATE_PROPERTY_NAME.equals(propertyName)) { + //TODO should be unicast : only for good stepUI ? + ui.onModelStateChanged((WizardState) evt.getNewValue()); + return; + } + if (WizardExtModel.STEP_STATE_PROPERTY_NAME.equals(propertyName)) { + IndexedPropertyChangeEvent e = (IndexedPropertyChangeEvent) evt; + int stepIndex = e.getIndex(); + E step = model.getSteps().get(stepIndex); + ui.onOperationStateChanged(step, (WizardState) evt.getNewValue()); + } + } + }; + M model = ui.getModel(); + log.info("Adding dispatcher " + dispatcher + " to model " + model); + model.addPropertyChangeListener(dispatcher); + } + +} diff --git a/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardState.java b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardState.java new file mode 100644 index 0000000..06f4336 --- /dev/null +++ b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/WizardState.java @@ -0,0 +1,48 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.wizard.ext; + +/** + * Pour caractériser l'état d'une opération. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public enum WizardState { + + /** quand l'opération n'a pas encore été réalisée */ + PENDING, + + /** quand l'opération est en cours */ + RUNNING, + + /** quand l'opération est annulé en cours d'exécution */ + CANCELED, + + /** quand une erreur s'est produite pendant l'exécution */ + FAILED, + + /** quand l'exécution s'est terminée mais requière des corrections */ + NEED_FIX, + + /** quand l'exécution s'est terminée et ne requière pas de correction */ + SUCCESSED +} diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/package.html b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/package.html similarity index 100% rename from jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/package.html rename to jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/ext/package.html diff --git a/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/package.html b/jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/package.html similarity index 100% rename from jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/package.html rename to jaxx-runtime/src/main/java/org/nuiton/jaxx/runtime/swing/wizard/package.html diff --git a/jaxx-runtime/src/test/java/jaxx/runtime/UtilTest.java b/jaxx-runtime/src/test/java/jaxx/runtime/UtilTest.java deleted file mode 100644 index dd207cc..0000000 --- a/jaxx-runtime/src/test/java/jaxx/runtime/UtilTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime; - -import org.junit.Assert; -import org.junit.Test; - -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; - -public class UtilTest { - - int count; - - @Test - public void testGetEventListener() { - count = 0; - DocumentListener listener = JAXXUtil.getEventListener(DocumentListener.class, this, "incCount"); - listener.insertUpdate(null); - Assert.assertEquals(count, 1); - DocumentListener listener2 = JAXXUtil.getEventListener(DocumentListener.class, this, "incCount"); - listener2.removeUpdate(null); - Assert.assertEquals(count, 2); - //assertTrue("Received two different event listeners despite using identical parameters", listener == listener2); - } - - - public void incCount(DocumentEvent e) { - count++; - } -} diff --git a/jaxx-runtime/src/test/java/jaxx/runtime/context/DataContextEntryIteratorTest.java b/jaxx-runtime/src/test/java/jaxx/runtime/context/DataContextEntryIteratorTest.java deleted file mode 100644 index 81ab569..0000000 --- a/jaxx-runtime/src/test/java/jaxx/runtime/context/DataContextEntryIteratorTest.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.context; - -import jaxx.runtime.context.DataContext.DataContextEntry; -import jaxx.runtime.context.DataContext.DataContextEntryIterator; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.util.regex.Pattern; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Tests {@link DataContext}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0.1 - */ -public class DataContextEntryIteratorTest { - - static DataContextEntry<?>[] entries; - - static class DataContextEntry2 extends DataContextEntry<Object> { - - public DataContextEntry2() { - super(Object.class); - } - - public DataContextEntry2(DataContextEntry<?> previous) { - super(Object.class, previous); - } - - @Override - public Pattern getPattern() { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public String getContextPath(Object... args) { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public boolean acceptType(Class<?> type) { - throw new UnsupportedOperationException("Not supported yet."); - } - } - - @BeforeClass - public static void setUpClass() throws Exception { - entries = new DataContextEntry<?>[3]; - entries[0] = new DataContextEntry2(); - entries[1] = new DataContextEntry2(entries[0]); - entries[2] = new DataContextEntry2(entries[1]); - } - - DataContextEntryIterator instance; - - @Test - public void testEmptyIterator() { - - instance = new DataContextEntryIterator( - DataContext.EMPTY_DATA_CONTEXT_ENTRY_ARRAY); - - boolean result = instance.hasNext(); - assertEquals(false, result); - } - - @Test - public void testEmptyReverseIterator() { - - instance = new DataContextEntryIterator( - DataContext.EMPTY_DATA_CONTEXT_ENTRY_ARRAY, true); - - boolean result = instance.hasNext(); - assertEquals(false, result); - } - - @Test - public void testEmptyLevelIterator() { - - instance = new DataContextEntryIterator( - DataContext.EMPTY_DATA_CONTEXT_ENTRY_ARRAY, 0); - - boolean result = instance.hasNext(); - assertEquals(false, result); - - instance = new DataContextEntryIterator( - new DataContextEntry<?>[]{entries[1]}, 0); - - result = instance.hasNext(); - assertEquals(false, result); - } - - @Test - public void testSingletonIterator() { - - instance = new DataContextEntryIterator( - new DataContextEntry<?>[]{entries[0]}); - - boolean result = instance.hasNext(); - assertEquals(true, result); - DataContextEntry<?> data = instance.next(); - assertNotNull(data); - assertEquals(entries[0], data); - assertEquals(0, data.getLevel()); - - result = instance.hasNext(); - assertEquals(false, result); - } - - @Test - public void testSingletonReverseIterator() { - - instance = new DataContextEntryIterator( - new DataContextEntry<?>[]{entries[0]}, true); - - boolean result = instance.hasNext(); - assertEquals(true, result); - DataContextEntry<?> data = instance.next(); - assertNotNull(data); - assertEquals(entries[0], data); - assertEquals(0, data.getLevel()); - - result = instance.hasNext(); - assertEquals(false, result); - } - - @Test - public void testSingletonLevelIterator() { - - instance = new DataContextEntryIterator( - new DataContextEntry<?>[]{entries[0]}, 0); - - boolean result = instance.hasNext(); - assertEquals(true, result); - DataContextEntry<?> data = instance.next(); - assertNotNull(data); - assertEquals(entries[0], data); - assertEquals(0, data.getLevel()); - - result = instance.hasNext(); - assertEquals(false, result); - - instance = new DataContextEntryIterator( - new DataContextEntry<?>[]{entries[0]}, 1); - - result = instance.hasNext(); - assertEquals(true, result); - data = instance.next(); - assertNotNull(data); - assertEquals(entries[0], data); - assertEquals(0, data.getLevel()); - - result = instance.hasNext(); - assertEquals(false, result); - - instance = new DataContextEntryIterator(entries, 0); - - result = instance.hasNext(); - assertEquals(true, result); - data = instance.next(); - assertNotNull(data); - assertEquals(entries[0], data); - assertEquals(0, data.getLevel()); - - result = instance.hasNext(); - assertEquals(false, result); - - } - - @Test - public void testIterator() { - - instance = new DataContextEntryIterator(entries); - - boolean result = instance.hasNext(); - assertEquals(true, result); - DataContextEntry<?> data = instance.next(); - assertNotNull(data); - assertEquals(entries[0], data); - assertEquals(0, data.getLevel()); - - result = instance.hasNext(); - assertEquals(true, result); - data = instance.next(); - assertNotNull(data); - assertEquals(entries[1], data); - assertEquals(1, data.getLevel()); - - result = instance.hasNext(); - assertEquals(true, result); - data = instance.next(); - assertNotNull(data); - assertEquals(entries[2], data); - assertEquals(2, data.getLevel()); - - result = instance.hasNext(); - assertEquals(false, result); - - - } - - @Test - public void testReverseIterator() { - - instance = new DataContextEntryIterator(entries, true); - - boolean result = instance.hasNext(); - assertEquals(true, result); - Object data = instance.next(); - assertNotNull(data); - assertEquals(entries[2], data); - - result = instance.hasNext(); - assertEquals(true, result); - data = instance.next(); - assertNotNull(data); - assertEquals(entries[1], data); - - result = instance.hasNext(); - assertEquals(true, result); - data = instance.next(); - assertNotNull(data); - assertEquals(entries[0], data); - - result = instance.hasNext(); - assertEquals(false, result); - - - } - - @Test - public void testLevelIterator() { - - instance = new DataContextEntryIterator(entries, 2); - - boolean result = instance.hasNext(); - assertEquals(true, result); - DataContextEntry<?> data = instance.next(); - assertNotNull(data); - assertEquals(entries[0], data); - assertEquals(0, data.getLevel()); - - result = instance.hasNext(); - assertEquals(true, result); - data = instance.next(); - assertNotNull(data); - assertEquals(entries[1], data); - assertEquals(1, data.getLevel()); - - result = instance.hasNext(); - assertEquals(true, result); - data = instance.next(); - assertNotNull(data); - assertEquals(entries[2], data); - assertEquals(2, data.getLevel()); - - result = instance.hasNext(); - assertEquals(false, result); - - - } -} diff --git a/jaxx-runtime/src/test/java/jaxx/runtime/context/DefaultApplicationContextTest.java b/jaxx-runtime/src/test/java/jaxx/runtime/context/DefaultApplicationContextTest.java deleted file mode 100644 index 378447e..0000000 --- a/jaxx-runtime/src/test/java/jaxx/runtime/context/DefaultApplicationContextTest.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.context; - -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.context.DefaultApplicationContext.AutoLoad; -import jaxx.runtime.context.DefaultApplicationContext.MethodAccess; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.Arrays; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -/** @author Tony Chemit - chemit@codelutin.com */ -public class DefaultApplicationContextTest { - - /** Logger */ - private static final Log log = - LogFactory.getLog(DefaultApplicationContextTest.class); - - static int helloCount; - - static int helloGetCount; - - static final JAXXContextEntryDef<String> STRING_ENTRY = - JAXXUtil.newContextEntryDef("myStringEntryKey", String.class); - - static final JAXXContextEntryDef<List<String>> LIST_STRING_ENTRY = - JAXXUtil.newListContextEntryDef("myListEntryKey"); - - @AutoLoad - @MethodAccess(methodName = "hello", target = String.class) - public static class Hello { - - public Hello() { - helloCount++; - } - - public String hello(String name) { - helloGetCount++; - return "hello " + name; - } - } - - DefaultApplicationContext context; - - @BeforeClass - public static void setUpClass() throws Exception { - helloCount = 0; - helloGetCount = 0; - } - - @AfterClass - public static void tearDownClass() throws Exception { - } - - @Before - public void setUp() { - context = new DefaultApplicationContext(); - assertEquals(0, helloCount); - assertEquals(0, helloGetCount); - } - - @After - public void tearDown() { - context = null; - helloCount = helloGetCount = 0; - } - - @Test(expected = IllegalArgumentException.class) - public void testAutoLoadNamed() { - context.getContextValue(Hello.class, "fakeName"); - } - - @Test - public void testAutoLoad() { - Hello hello = context.getContextValue(Hello.class); - assertNotNull(hello); - assertEquals(1, helloCount); - - Hello hello2 = context.getContextValue(Hello.class); - assertNotNull(hello2); - assertEquals(1, helloCount); - assertEquals(hello, hello2); - } - - @Test - public void testForward() { - context.getContextValue(Hello.class); - assertEquals(1, helloCount); - String response = context.getContextValue(String.class, "John"); - assertNotNull(response); - assertEquals(1, helloGetCount); - assertEquals(new Hello().hello("John"), response); - } - - @Test - public void testRemove() { - String response; - - context.getContextValue(Hello.class); - assertEquals(1, helloCount); - assertEquals(1, context.forwards.size()); - response = context.getContextValue(String.class, "John"); - assertNotNull(response); - - context.removeContextValue(Hello.class); - assertEquals(0, context.forwards.size()); - response = context.getContextValue(String.class, "John"); - assertEquals(1, helloCount); - assertNull(response); - - // reinstanciate the service - context.getContextValue(Hello.class); - assertEquals(2, helloCount); - assertEquals(1, context.forwards.size()); - - // no effect with a name - context.removeContextValue(Hello.class, "fake"); - assertEquals(1, context.forwards.size()); - context.getContextValue(Hello.class); - assertEquals(2, helloCount); - } - - static int yoCount; - - @Test - public void testEntryListener() { - - PropertyChangeListener listener = new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (log.isInfoEnabled()) { - log.info("changed detected on " + evt.getSource()); - } - yoCount++; - } - }; - context.addPropertyChangeListener(STRING_ENTRY, "myKey", listener); - - STRING_ENTRY.setContextValue(context, "myValue"); - - Assert.assertEquals(1, yoCount); - - STRING_ENTRY.removeContextValue(context); - - Assert.assertEquals(2, yoCount); - - context.removePropertyChangeListener(STRING_ENTRY, "myKey", listener); - - // test that nothing changed now - - STRING_ENTRY.setContextValue(context, "myValue"); - - Assert.assertEquals(2, yoCount); - - STRING_ENTRY.removeContextValue(context); - - Assert.assertEquals(2, yoCount); - - // test with a list entry - - context.addPropertyChangeListener(LIST_STRING_ENTRY, "myKey2", listener); - - LIST_STRING_ENTRY.setContextValue(context, Arrays.asList("myValue")); - - Assert.assertEquals(3, yoCount); - - LIST_STRING_ENTRY.removeContextValue(context); - - Assert.assertEquals(4, yoCount); - - - // test that nothing changed now - - context.removePropertyChangeListener(LIST_STRING_ENTRY, "myKey2", listener); - - LIST_STRING_ENTRY.setContextValue(context, Arrays.asList("myValue2")); - - Assert.assertEquals(4, yoCount); - - LIST_STRING_ENTRY.removeContextValue(context); - - Assert.assertEquals(4, yoCount); - - - } - - -} diff --git a/jaxx-runtime/src/test/java/jaxx/runtime/context/DefaultJAXXContextTest.java b/jaxx-runtime/src/test/java/jaxx/runtime/context/DefaultJAXXContextTest.java deleted file mode 100644 index 006abdf..0000000 --- a/jaxx-runtime/src/test/java/jaxx/runtime/context/DefaultJAXXContextTest.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * #%L - * JAXX :: Runtime - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.context; - -import jaxx.runtime.JAXXContext; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** @author Tony Chemit - chemit@codelutin.com */ -public class DefaultJAXXContextTest { - - DefaultJAXXContext ctxt; - - @Before - public void initContext() throws Exception { - - // instanciate a new empty context - ctxt = new DefaultJAXXContext(); - } - - @Test - public void testGetParentContext() throws Exception { - JAXXContext expected, result; - expected = null; - result = ctxt.getContextValue(JAXXContext.class); - Assert.assertEquals(expected, result); - - DefaultJAXXContext parentContext = new DefaultJAXXContext(); - - ctxt.setContextValue(parentContext); - - expected = parentContext; - result = ctxt.getContextValue(JAXXContext.class); - Assert.assertEquals(expected, result); - } - - @Test - public void testSetGetContextValue() throws Exception { - String expected; - String result; - - result = ctxt.getContextValue(String.class); - Assert.assertNull(result); - - expected = "yo"; - ctxt.setContextValue(expected); - result = ctxt.getContextValue(String.class); - Assert.assertEquals(expected, result); - - expected = "ya"; - ctxt.setContextValue(expected, "second"); - result = ctxt.getContextValue(String.class, "second"); - Assert.assertEquals(expected, result); - - expected = "yi"; - ctxt.setContextValue(expected, "second"); - result = ctxt.getContextValue(String.class, "second"); - Assert.assertEquals(expected, result); - } - - @Test - public void testSetGetContextValueInParentContext() throws Exception { - - // attach parent context - JAXXContext parentContext = new DefaultJAXXContext(); - ctxt.setContextValue(parentContext); - - String expected; - String result; - - result = ctxt.getContextValue(String.class); - Assert.assertNull(result); - - expected = "yo"; - result = ctxt.getContextValue(String.class); - Assert.assertNull(result); - parentContext.setContextValue(expected); - result = ctxt.getContextValue(String.class); - Assert.assertEquals(expected, result); - - expected = "ya"; - result = ctxt.getContextValue(String.class, "second"); - Assert.assertNull(result); - parentContext.setContextValue(expected, "second"); - result = ctxt.getContextValue(String.class, "second"); - Assert.assertEquals(expected, result); - - expected = "yi"; - result = ctxt.getContextValue(String.class, "second"); - parentContext.setContextValue(expected, "second"); - Assert.assertEquals("ya", result); - result = ctxt.getContextValue(String.class, "second"); - Assert.assertEquals(expected, result); - } - - @Test - public void testSetGetContextValue2() throws Exception { - - // attach parent context - JAXXContext parentContext = new DefaultJAXXContext(); - ctxt.setContextValue(parentContext); - - String expected; - String result; - - result = ctxt.getContextValue(String.class); - Assert.assertNull(result); - result = ctxt.getContextValue(String.class, "yo"); - Assert.assertNull(result); - - expected = "yo"; - ctxt.setContextValue(expected, "yo"); - - result = ctxt.getContextValue(String.class); - Assert.assertNull(result); - result = ctxt.getContextValue(String.class, "yo"); - Assert.assertEquals(expected, result); - } - - @Test - public void testSetGetContextValueInParentParentContext() throws Exception { - - // attach parent parent context - JAXXContext parentParentContext = new DefaultJAXXContext(); - JAXXContext parentContext = new DefaultJAXXContext(); - parentContext.setContextValue(parentParentContext); - ctxt.setContextValue(parentContext); - - String expected; - String result; - - result = ctxt.getContextValue(String.class); - Assert.assertNull(result); - - expected = "yo"; - result = ctxt.getContextValue(String.class); - Assert.assertNull(result); - parentParentContext.setContextValue(expected); - result = ctxt.getContextValue(String.class); - Assert.assertEquals(expected, result); - - expected = "ya"; - result = ctxt.getContextValue(String.class, "second"); - Assert.assertNull(result); - parentParentContext.setContextValue(expected, "second"); - result = ctxt.getContextValue(String.class, "second"); - Assert.assertEquals(expected, result); - - expected = "yi"; - result = ctxt.getContextValue(String.class, "second"); - parentParentContext.setContextValue(expected, "second"); - Assert.assertEquals("ya", result); - result = ctxt.getContextValue(String.class, "second"); - Assert.assertEquals(expected, result); - } - - @Test - public void testEntrySet() throws Exception { - Object o = new Object(); - - ctxt.setContextValue(o); - - Assert.assertEquals(1, ctxt.data.size()); - Assert.assertEquals(o, ctxt.getContextValue(Object.class)); - Assert.assertEquals(null, ctxt.getContextValue(Object.class, "named")); - - ctxt.setContextValue(o, "named"); - - Assert.assertEquals(2, ctxt.data.size()); - Assert.assertEquals(o, ctxt.getContextValue(Object.class)); - Assert.assertEquals(o, ctxt.getContextValue(Object.class, "named")); - - ctxt.removeContextValue(Object.class); - Assert.assertEquals(1, ctxt.data.size()); - Assert.assertEquals(null, ctxt.getContextValue(Object.class)); - Assert.assertEquals(o, ctxt.getContextValue(Object.class, "named")); - - ctxt.removeContextValue(Object.class); - Assert.assertEquals(1, ctxt.data.size()); - Assert.assertEquals(null, ctxt.getContextValue(Object.class)); - Assert.assertEquals(o, ctxt.getContextValue(Object.class, "named")); - - ctxt.removeContextValue(Object.class, "named"); - Assert.assertEquals(0, ctxt.data.size()); - Assert.assertEquals(null, ctxt.getContextValue(Object.class)); - Assert.assertEquals(null, ctxt.getContextValue(Object.class, "named")); - - } - - @Test - public void testEntrySetWithParent() throws Exception { - - DefaultJAXXContext parentContext = new DefaultJAXXContext(); - - ctxt.setContextValue(parentContext); - - class Object2 { - - } - Object o = new Object2(); - - parentContext.setContextValue(o); - - Assert.assertEquals(0, ctxt.data.size()); - Assert.assertEquals(1, parentContext.data.size()); - Assert.assertEquals(o, ctxt.getContextValue(Object2.class)); - Assert.assertEquals(null, ctxt.getContextValue(Object2.class, "named")); - - parentContext.setContextValue(o, "named"); - - Assert.assertEquals(0, ctxt.data.size()); - Assert.assertEquals(2, parentContext.data.size()); - Assert.assertEquals(o, ctxt.getContextValue(Object2.class)); - Assert.assertEquals(o, ctxt.getContextValue(Object2.class, "named")); - - parentContext.removeContextValue(Object2.class); - Assert.assertEquals(0, ctxt.data.size()); - Assert.assertEquals(1, parentContext.data.size()); - Assert.assertEquals(null, ctxt.getContextValue(Object2.class)); - Assert.assertEquals(o, ctxt.getContextValue(Object2.class, "named")); - - parentContext.removeContextValue(Object2.class); - Assert.assertEquals(0, ctxt.data.size()); - Assert.assertEquals(1, parentContext.data.size()); - Assert.assertEquals(null, ctxt.getContextValue(Object2.class)); - Assert.assertEquals(o, ctxt.getContextValue(Object2.class, "named")); - - ctxt.removeContextValue(Object2.class, "named"); - Assert.assertEquals(0, ctxt.data.size()); - Assert.assertEquals(0, parentContext.data.size()); - Assert.assertEquals(null, ctxt.getContextValue(Object2.class)); - Assert.assertEquals(null, ctxt.getContextValue(Object2.class, "named")); - - } - -} diff --git a/jaxx-runtime/src/test/java/org/nuiton/jaxx/runtime/UtilTest.java b/jaxx-runtime/src/test/java/org/nuiton/jaxx/runtime/UtilTest.java new file mode 100644 index 0000000..c062bef --- /dev/null +++ b/jaxx-runtime/src/test/java/org/nuiton/jaxx/runtime/UtilTest.java @@ -0,0 +1,51 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime; + +import org.junit.Assert; +import org.junit.Test; +import org.nuiton.jaxx.runtime.JAXXUtil; + +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +public class UtilTest { + + int count; + + @Test + public void testGetEventListener() { + count = 0; + DocumentListener listener = JAXXUtil.getEventListener(DocumentListener.class, this, "incCount"); + listener.insertUpdate(null); + Assert.assertEquals(count, 1); + DocumentListener listener2 = JAXXUtil.getEventListener(DocumentListener.class, this, "incCount"); + listener2.removeUpdate(null); + Assert.assertEquals(count, 2); + //assertTrue("Received two different event listeners despite using identical parameters", listener == listener2); + } + + + public void incCount(DocumentEvent e) { + count++; + } +} diff --git a/jaxx-runtime/src/test/java/org/nuiton/jaxx/runtime/context/DataContextEntryIteratorTest.java b/jaxx-runtime/src/test/java/org/nuiton/jaxx/runtime/context/DataContextEntryIteratorTest.java new file mode 100644 index 0000000..ae28906 --- /dev/null +++ b/jaxx-runtime/src/test/java/org/nuiton/jaxx/runtime/context/DataContextEntryIteratorTest.java @@ -0,0 +1,285 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.context; + +import org.nuiton.jaxx.runtime.context.DataContext.DataContextEntry; +import org.nuiton.jaxx.runtime.context.DataContext.DataContextEntryIterator; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.regex.Pattern; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Tests {@link DataContext}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0.1 + */ +public class DataContextEntryIteratorTest { + + static DataContextEntry<?>[] entries; + + static class DataContextEntry2 extends DataContextEntry<Object> { + + public DataContextEntry2() { + super(Object.class); + } + + public DataContextEntry2(DataContextEntry<?> previous) { + super(Object.class, previous); + } + + @Override + public Pattern getPattern() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String getContextPath(Object... args) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean acceptType(Class<?> type) { + throw new UnsupportedOperationException("Not supported yet."); + } + } + + @BeforeClass + public static void setUpClass() throws Exception { + entries = new DataContextEntry<?>[3]; + entries[0] = new DataContextEntry2(); + entries[1] = new DataContextEntry2(entries[0]); + entries[2] = new DataContextEntry2(entries[1]); + } + + DataContextEntryIterator instance; + + @Test + public void testEmptyIterator() { + + instance = new DataContextEntryIterator( + DataContext.EMPTY_DATA_CONTEXT_ENTRY_ARRAY); + + boolean result = instance.hasNext(); + assertEquals(false, result); + } + + @Test + public void testEmptyReverseIterator() { + + instance = new DataContextEntryIterator( + DataContext.EMPTY_DATA_CONTEXT_ENTRY_ARRAY, true); + + boolean result = instance.hasNext(); + assertEquals(false, result); + } + + @Test + public void testEmptyLevelIterator() { + + instance = new DataContextEntryIterator( + DataContext.EMPTY_DATA_CONTEXT_ENTRY_ARRAY, 0); + + boolean result = instance.hasNext(); + assertEquals(false, result); + + instance = new DataContextEntryIterator( + new DataContextEntry<?>[]{entries[1]}, 0); + + result = instance.hasNext(); + assertEquals(false, result); + } + + @Test + public void testSingletonIterator() { + + instance = new DataContextEntryIterator( + new DataContextEntry<?>[]{entries[0]}); + + boolean result = instance.hasNext(); + assertEquals(true, result); + DataContextEntry<?> data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + assertEquals(0, data.getLevel()); + + result = instance.hasNext(); + assertEquals(false, result); + } + + @Test + public void testSingletonReverseIterator() { + + instance = new DataContextEntryIterator( + new DataContextEntry<?>[]{entries[0]}, true); + + boolean result = instance.hasNext(); + assertEquals(true, result); + DataContextEntry<?> data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + assertEquals(0, data.getLevel()); + + result = instance.hasNext(); + assertEquals(false, result); + } + + @Test + public void testSingletonLevelIterator() { + + instance = new DataContextEntryIterator( + new DataContextEntry<?>[]{entries[0]}, 0); + + boolean result = instance.hasNext(); + assertEquals(true, result); + DataContextEntry<?> data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + assertEquals(0, data.getLevel()); + + result = instance.hasNext(); + assertEquals(false, result); + + instance = new DataContextEntryIterator( + new DataContextEntry<?>[]{entries[0]}, 1); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + assertEquals(0, data.getLevel()); + + result = instance.hasNext(); + assertEquals(false, result); + + instance = new DataContextEntryIterator(entries, 0); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + assertEquals(0, data.getLevel()); + + result = instance.hasNext(); + assertEquals(false, result); + + } + + @Test + public void testIterator() { + + instance = new DataContextEntryIterator(entries); + + boolean result = instance.hasNext(); + assertEquals(true, result); + DataContextEntry<?> data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + assertEquals(0, data.getLevel()); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[1], data); + assertEquals(1, data.getLevel()); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[2], data); + assertEquals(2, data.getLevel()); + + result = instance.hasNext(); + assertEquals(false, result); + + + } + + @Test + public void testReverseIterator() { + + instance = new DataContextEntryIterator(entries, true); + + boolean result = instance.hasNext(); + assertEquals(true, result); + Object data = instance.next(); + assertNotNull(data); + assertEquals(entries[2], data); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[1], data); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + + result = instance.hasNext(); + assertEquals(false, result); + + + } + + @Test + public void testLevelIterator() { + + instance = new DataContextEntryIterator(entries, 2); + + boolean result = instance.hasNext(); + assertEquals(true, result); + DataContextEntry<?> data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + assertEquals(0, data.getLevel()); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[1], data); + assertEquals(1, data.getLevel()); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[2], data); + assertEquals(2, data.getLevel()); + + result = instance.hasNext(); + assertEquals(false, result); + + + } +} diff --git a/jaxx-runtime/src/test/java/org/nuiton/jaxx/runtime/context/DefaultApplicationContextTest.java b/jaxx-runtime/src/test/java/org/nuiton/jaxx/runtime/context/DefaultApplicationContextTest.java new file mode 100644 index 0000000..76736eb --- /dev/null +++ b/jaxx-runtime/src/test/java/org/nuiton/jaxx/runtime/context/DefaultApplicationContextTest.java @@ -0,0 +1,221 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.context; + +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.context.DefaultApplicationContext.AutoLoad; +import org.nuiton.jaxx.runtime.context.DefaultApplicationContext.MethodAccess; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +/** @author Tony Chemit - chemit@codelutin.com */ +public class DefaultApplicationContextTest { + + /** Logger */ + private static final Log log = + LogFactory.getLog(DefaultApplicationContextTest.class); + + static int helloCount; + + static int helloGetCount; + + static final JAXXContextEntryDef<String> STRING_ENTRY = + JAXXUtil.newContextEntryDef("myStringEntryKey", String.class); + + static final JAXXContextEntryDef<List<String>> LIST_STRING_ENTRY = + JAXXUtil.newListContextEntryDef("myListEntryKey"); + + @AutoLoad + @MethodAccess(methodName = "hello", target = String.class) + public static class Hello { + + public Hello() { + helloCount++; + } + + public String hello(String name) { + helloGetCount++; + return "hello " + name; + } + } + + DefaultApplicationContext context; + + @BeforeClass + public static void setUpClass() throws Exception { + helloCount = 0; + helloGetCount = 0; + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() { + context = new DefaultApplicationContext(); + assertEquals(0, helloCount); + assertEquals(0, helloGetCount); + } + + @After + public void tearDown() { + context = null; + helloCount = helloGetCount = 0; + } + + @Test(expected = IllegalArgumentException.class) + public void testAutoLoadNamed() { + context.getContextValue(Hello.class, "fakeName"); + } + + @Test + public void testAutoLoad() { + Hello hello = context.getContextValue(Hello.class); + assertNotNull(hello); + assertEquals(1, helloCount); + + Hello hello2 = context.getContextValue(Hello.class); + assertNotNull(hello2); + assertEquals(1, helloCount); + assertEquals(hello, hello2); + } + + @Test + public void testForward() { + context.getContextValue(Hello.class); + assertEquals(1, helloCount); + String response = context.getContextValue(String.class, "John"); + assertNotNull(response); + assertEquals(1, helloGetCount); + assertEquals(new Hello().hello("John"), response); + } + + @Test + public void testRemove() { + String response; + + context.getContextValue(Hello.class); + assertEquals(1, helloCount); + assertEquals(1, context.forwards.size()); + response = context.getContextValue(String.class, "John"); + assertNotNull(response); + + context.removeContextValue(Hello.class); + assertEquals(0, context.forwards.size()); + response = context.getContextValue(String.class, "John"); + assertEquals(1, helloCount); + assertNull(response); + + // reinstanciate the service + context.getContextValue(Hello.class); + assertEquals(2, helloCount); + assertEquals(1, context.forwards.size()); + + // no effect with a name + context.removeContextValue(Hello.class, "fake"); + assertEquals(1, context.forwards.size()); + context.getContextValue(Hello.class); + assertEquals(2, helloCount); + } + + static int yoCount; + + @Test + public void testEntryListener() { + + PropertyChangeListener listener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (log.isInfoEnabled()) { + log.info("changed detected on " + evt.getSource()); + } + yoCount++; + } + }; + context.addPropertyChangeListener(STRING_ENTRY, "myKey", listener); + + STRING_ENTRY.setContextValue(context, "myValue"); + + Assert.assertEquals(1, yoCount); + + STRING_ENTRY.removeContextValue(context); + + Assert.assertEquals(2, yoCount); + + context.removePropertyChangeListener(STRING_ENTRY, "myKey", listener); + + // test that nothing changed now + + STRING_ENTRY.setContextValue(context, "myValue"); + + Assert.assertEquals(2, yoCount); + + STRING_ENTRY.removeContextValue(context); + + Assert.assertEquals(2, yoCount); + + // test with a list entry + + context.addPropertyChangeListener(LIST_STRING_ENTRY, "myKey2", listener); + + LIST_STRING_ENTRY.setContextValue(context, Arrays.asList("myValue")); + + Assert.assertEquals(3, yoCount); + + LIST_STRING_ENTRY.removeContextValue(context); + + Assert.assertEquals(4, yoCount); + + + // test that nothing changed now + + context.removePropertyChangeListener(LIST_STRING_ENTRY, "myKey2", listener); + + LIST_STRING_ENTRY.setContextValue(context, Arrays.asList("myValue2")); + + Assert.assertEquals(4, yoCount); + + LIST_STRING_ENTRY.removeContextValue(context); + + Assert.assertEquals(4, yoCount); + + + } + + +} diff --git a/jaxx-runtime/src/test/java/org/nuiton/jaxx/runtime/context/DefaultJAXXContextTest.java b/jaxx-runtime/src/test/java/org/nuiton/jaxx/runtime/context/DefaultJAXXContextTest.java new file mode 100644 index 0000000..ffbe55d --- /dev/null +++ b/jaxx-runtime/src/test/java/org/nuiton/jaxx/runtime/context/DefaultJAXXContextTest.java @@ -0,0 +1,256 @@ +/* + * #%L + * JAXX :: Runtime + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.context; + +import org.nuiton.jaxx.runtime.JAXXContext; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** @author Tony Chemit - chemit@codelutin.com */ +public class DefaultJAXXContextTest { + + DefaultJAXXContext ctxt; + + @Before + public void initContext() throws Exception { + + // instanciate a new empty context + ctxt = new DefaultJAXXContext(); + } + + @Test + public void testGetParentContext() throws Exception { + JAXXContext expected, result; + expected = null; + result = ctxt.getContextValue(JAXXContext.class); + Assert.assertEquals(expected, result); + + DefaultJAXXContext parentContext = new DefaultJAXXContext(); + + ctxt.setContextValue(parentContext); + + expected = parentContext; + result = ctxt.getContextValue(JAXXContext.class); + Assert.assertEquals(expected, result); + } + + @Test + public void testSetGetContextValue() throws Exception { + String expected; + String result; + + result = ctxt.getContextValue(String.class); + Assert.assertNull(result); + + expected = "yo"; + ctxt.setContextValue(expected); + result = ctxt.getContextValue(String.class); + Assert.assertEquals(expected, result); + + expected = "ya"; + ctxt.setContextValue(expected, "second"); + result = ctxt.getContextValue(String.class, "second"); + Assert.assertEquals(expected, result); + + expected = "yi"; + ctxt.setContextValue(expected, "second"); + result = ctxt.getContextValue(String.class, "second"); + Assert.assertEquals(expected, result); + } + + @Test + public void testSetGetContextValueInParentContext() throws Exception { + + // attach parent context + JAXXContext parentContext = new DefaultJAXXContext(); + ctxt.setContextValue(parentContext); + + String expected; + String result; + + result = ctxt.getContextValue(String.class); + Assert.assertNull(result); + + expected = "yo"; + result = ctxt.getContextValue(String.class); + Assert.assertNull(result); + parentContext.setContextValue(expected); + result = ctxt.getContextValue(String.class); + Assert.assertEquals(expected, result); + + expected = "ya"; + result = ctxt.getContextValue(String.class, "second"); + Assert.assertNull(result); + parentContext.setContextValue(expected, "second"); + result = ctxt.getContextValue(String.class, "second"); + Assert.assertEquals(expected, result); + + expected = "yi"; + result = ctxt.getContextValue(String.class, "second"); + parentContext.setContextValue(expected, "second"); + Assert.assertEquals("ya", result); + result = ctxt.getContextValue(String.class, "second"); + Assert.assertEquals(expected, result); + } + + @Test + public void testSetGetContextValue2() throws Exception { + + // attach parent context + JAXXContext parentContext = new DefaultJAXXContext(); + ctxt.setContextValue(parentContext); + + String expected; + String result; + + result = ctxt.getContextValue(String.class); + Assert.assertNull(result); + result = ctxt.getContextValue(String.class, "yo"); + Assert.assertNull(result); + + expected = "yo"; + ctxt.setContextValue(expected, "yo"); + + result = ctxt.getContextValue(String.class); + Assert.assertNull(result); + result = ctxt.getContextValue(String.class, "yo"); + Assert.assertEquals(expected, result); + } + + @Test + public void testSetGetContextValueInParentParentContext() throws Exception { + + // attach parent parent context + JAXXContext parentParentContext = new DefaultJAXXContext(); + JAXXContext parentContext = new DefaultJAXXContext(); + parentContext.setContextValue(parentParentContext); + ctxt.setContextValue(parentContext); + + String expected; + String result; + + result = ctxt.getContextValue(String.class); + Assert.assertNull(result); + + expected = "yo"; + result = ctxt.getContextValue(String.class); + Assert.assertNull(result); + parentParentContext.setContextValue(expected); + result = ctxt.getContextValue(String.class); + Assert.assertEquals(expected, result); + + expected = "ya"; + result = ctxt.getContextValue(String.class, "second"); + Assert.assertNull(result); + parentParentContext.setContextValue(expected, "second"); + result = ctxt.getContextValue(String.class, "second"); + Assert.assertEquals(expected, result); + + expected = "yi"; + result = ctxt.getContextValue(String.class, "second"); + parentParentContext.setContextValue(expected, "second"); + Assert.assertEquals("ya", result); + result = ctxt.getContextValue(String.class, "second"); + Assert.assertEquals(expected, result); + } + + @Test + public void testEntrySet() throws Exception { + Object o = new Object(); + + ctxt.setContextValue(o); + + Assert.assertEquals(1, ctxt.data.size()); + Assert.assertEquals(o, ctxt.getContextValue(Object.class)); + Assert.assertEquals(null, ctxt.getContextValue(Object.class, "named")); + + ctxt.setContextValue(o, "named"); + + Assert.assertEquals(2, ctxt.data.size()); + Assert.assertEquals(o, ctxt.getContextValue(Object.class)); + Assert.assertEquals(o, ctxt.getContextValue(Object.class, "named")); + + ctxt.removeContextValue(Object.class); + Assert.assertEquals(1, ctxt.data.size()); + Assert.assertEquals(null, ctxt.getContextValue(Object.class)); + Assert.assertEquals(o, ctxt.getContextValue(Object.class, "named")); + + ctxt.removeContextValue(Object.class); + Assert.assertEquals(1, ctxt.data.size()); + Assert.assertEquals(null, ctxt.getContextValue(Object.class)); + Assert.assertEquals(o, ctxt.getContextValue(Object.class, "named")); + + ctxt.removeContextValue(Object.class, "named"); + Assert.assertEquals(0, ctxt.data.size()); + Assert.assertEquals(null, ctxt.getContextValue(Object.class)); + Assert.assertEquals(null, ctxt.getContextValue(Object.class, "named")); + + } + + @Test + public void testEntrySetWithParent() throws Exception { + + DefaultJAXXContext parentContext = new DefaultJAXXContext(); + + ctxt.setContextValue(parentContext); + + class Object2 { + + } + Object o = new Object2(); + + parentContext.setContextValue(o); + + Assert.assertEquals(0, ctxt.data.size()); + Assert.assertEquals(1, parentContext.data.size()); + Assert.assertEquals(o, ctxt.getContextValue(Object2.class)); + Assert.assertEquals(null, ctxt.getContextValue(Object2.class, "named")); + + parentContext.setContextValue(o, "named"); + + Assert.assertEquals(0, ctxt.data.size()); + Assert.assertEquals(2, parentContext.data.size()); + Assert.assertEquals(o, ctxt.getContextValue(Object2.class)); + Assert.assertEquals(o, ctxt.getContextValue(Object2.class, "named")); + + parentContext.removeContextValue(Object2.class); + Assert.assertEquals(0, ctxt.data.size()); + Assert.assertEquals(1, parentContext.data.size()); + Assert.assertEquals(null, ctxt.getContextValue(Object2.class)); + Assert.assertEquals(o, ctxt.getContextValue(Object2.class, "named")); + + parentContext.removeContextValue(Object2.class); + Assert.assertEquals(0, ctxt.data.size()); + Assert.assertEquals(1, parentContext.data.size()); + Assert.assertEquals(null, ctxt.getContextValue(Object2.class)); + Assert.assertEquals(o, ctxt.getContextValue(Object2.class, "named")); + + ctxt.removeContextValue(Object2.class, "named"); + Assert.assertEquals(0, ctxt.data.size()); + Assert.assertEquals(0, parentContext.data.size()); + Assert.assertEquals(null, ctxt.getContextValue(Object2.class)); + Assert.assertEquals(null, ctxt.getContextValue(Object2.class, "named")); + + } + +} diff --git a/jaxx-runtime/src/test/resources/log4j.properties b/jaxx-runtime/src/test/resources/log4j.properties index 6c08bb0..1149532 100644 --- a/jaxx-runtime/src/test/resources/log4j.properties +++ b/jaxx-runtime/src/test/resources/log4j.properties @@ -26,4 +26,4 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) %M - %m%n -log4j.logger.jaxx=INFO +log4j.logger.org.nuiton.jaxx=INFO diff --git a/jaxx-validator/pom.xml b/jaxx-validator/pom.xml index 7abf9bb..4c47e50 100644 --- a/jaxx-validator/pom.xml +++ b/jaxx-validator/pom.xml @@ -123,7 +123,7 @@ <treateDefaultEntry>false</treateDefaultEntry> <entries> <entry> - <basedir>src/main/java/jaxx/runtime/validator</basedir> + <basedir>src/main/java/org/nuiton/jaxx/validator</basedir> </entry> </entries> </configuration> diff --git a/jaxx-validator/src/main/java/jaxx/runtime/JAXXValidator.java b/jaxx-validator/src/main/java/jaxx/runtime/JAXXValidator.java deleted file mode 100644 index ab64c1a..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/JAXXValidator.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime; - - -import jaxx.runtime.validator.swing.SwingValidator; - -import javax.swing.JComponent; -import java.util.List; - -/** - * The contract of a validator-able object. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public interface JAXXValidator { - - /** - * Obtain a validator from his id - * - * @param validatorId validator id - * @return the associated validator, or <code>null</code> if not find - */ - SwingValidator<?> getValidator(String validatorId); - - /** @return the list of ids of all registred validator */ - List<String> getValidatorIds(); - - /** - * Init the fields representation. - * - * This method is generated and should be called each time the context name - * of a validator has changed, since when using method - * {@link SwingValidator#setFieldRepresentation(String, JComponent)} - * is invoked at init, if a field is not watched for the selected context, - * then after when changing context name, the field will not be notified of any changed... - * - * @since 2.2.1 - */ - void registerValidatorFields(); - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SimpleBeanValidatorMessageTableModel.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SimpleBeanValidatorMessageTableModel.java deleted file mode 100644 index 225eb36..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SimpleBeanValidatorMessageTableModel.java +++ /dev/null @@ -1,269 +0,0 @@ -package jaxx.runtime.validator.swing; - -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.SwingUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.simple.SimpleBeanValidator; -import org.nuiton.validator.bean.simple.SimpleBeanValidatorEvent; -import org.nuiton.validator.bean.simple.SimpleBeanValidatorListener; -import org.nuiton.validator.bean.simple.SimpleBeanValidatorMessage; - -import javax.swing.table.AbstractTableModel; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * A model of the table of errors based on {@link SimpleBeanValidatorMessage}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6.23 - */ -public class SimpleBeanValidatorMessageTableModel extends AbstractTableModel - implements SimpleBeanValidatorListener { - - private static final long serialVersionUID = 1L; - - /** Logger */ - private static Log log = - LogFactory.getLog(SimpleBeanValidatorMessageTableModel.class); - - public static final String[] columnNames = - {"validator.scope", "validator.field", "validator.message"}; - - public static final Class<?>[] columnClasses = - {NuitonValidatorScope.class, String.class, String.class}; - - /** list of registred validators */ - protected transient List<SimpleBeanValidator<?>> validators; - - /** list of messages actual displayed */ - protected List<SimpleBeanValidatorMessage> data; - - public SimpleBeanValidatorMessageTableModel() { - validators = new ArrayList<SimpleBeanValidator<?>>(); - data = new ArrayList<SimpleBeanValidatorMessage>(); - } - - /** - * Register a validator for this model. - * - * - * Note: a validator can not be register twice in the same model. - * - * @param validator the validator to register - */ - public void registerValidator(SimpleBeanValidator<?> validator) { - if (validators.contains(validator)) { - throw new IllegalArgumentException( - "the validator " + validator + " is already registred in " - + this); - } - validators.add(validator); - validator.addSimpleBeanValidatorListener(this); - } - - public void addMessages(SimpleBeanValidator<?> validator, - String fieldName, - NuitonValidatorScope scope, - String... messages) { - addMessages(validator, fieldName, scope, true, messages); - } - - public void removeMessages(SimpleBeanValidator<?> validator, - String fieldName, - NuitonValidatorScope scope, - String... messages) { - removeMessages(validator, fieldName, scope, true, messages); - } - - public void clear() { - int i = data.size(); - if (i > 0) { - data.clear(); - fireTableRowsDeleted(0, i - 1); - } - } - - public void clearValidators() { - for (SimpleBeanValidator<?> v : validators) { - v.removeSimpleBeanValidatorListener(this); - } - validators.clear(); - } - - /** - * Obtain the message for a given row. - * - * @param rowIndex the row index - * @return the message for the given row index - */ - public SimpleBeanValidatorMessage getRow(int rowIndex) { - SwingUtil.ensureRowIndex(this, rowIndex); - return data.get(rowIndex); - } - - @Override - public boolean isCellEditable(int row, int column) { - // cells are never editable in this model - return false; - } - - @Override - public Class<?> getColumnClass(int columnIndex) { - SwingUtil.ensureColumnIndex(this, columnIndex); - return columnClasses[columnIndex]; - } - - @Override - public String getColumnName(int column) { - SwingUtil.ensureColumnIndex(this, column); - return columnNames[column]; - } - - @Override - public void onFieldChanged(SimpleBeanValidatorEvent event) { - String[] toDelete = event.getMessagesToDelete(); - String[] toAdd = event.getMessagesToAdd(); - String field = event.getField(); - NuitonValidatorScope scope = event.getScope(); - boolean mustAdd = toAdd != null && toAdd.length > 0; - boolean mustDel = toDelete != null && toDelete.length > 0; - - if (log.isTraceEnabled()) { - log.trace("----------------------------------------------------------"); - log.trace(field + " - (" + getRowCount() + ") toAdd " + mustAdd); - log.trace(field + " - (" + getRowCount() + ") toDelete " + mustDel); - } - - SimpleBeanValidator<?> validator = event.getSource(); - - if (mustDel) { - - // removes datas and notify if no messages to add - removeMessages(validator, field, scope, !mustAdd, toDelete); - } - - if (mustAdd) { - - // add new messages, sort datas and notify - addMessages(validator, field, scope, true, toAdd); - } - } - - @Override - public int getRowCount() { - return data.size(); - } - - @Override - public int getColumnCount() { - return columnNames.length; - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - SwingUtil.ensureColumnIndex(this, columnIndex); - SwingUtil.ensureRowIndex(this, rowIndex); - - SimpleBeanValidatorMessage row = data.get(rowIndex); - if (columnIndex == 0) { - // the icon - return row.getScope(); - } - if (columnIndex == 1) { - // the field - return row.getField(); - } - if (columnIndex == 2) { - // the message - return row.getMessage(); - } - - // should never come here - return null; - } - - protected void addMessages(SimpleBeanValidator<?> validator, - String fieldName, - NuitonValidatorScope scope, - boolean sort, - String... messages) { - - - // add new errors - for (String error : messages) { - SimpleBeanValidatorMessage row = - new SimpleBeanValidatorMessage<SimpleBeanValidatorMessage<?>>( - validator, - fieldName, - error, - scope - ); - data.add(row); - if (!sort) { - fireTableRowsInserted(data.size() - 1, data.size() - 1); - } - } - - if (sort) { - - // resort datas - Collections.sort(data); - - // notify - fireTableDataChanged(); - } - } - - protected void removeMessages(SimpleBeanValidator<?> validator, - String fieldName, - NuitonValidatorScope scope, - boolean notify, - String... messages) { - - List<String> messagesToDel = - new ArrayList<String>(Arrays.asList(messages)); - - // do it in reverse mode (only one pass in that way since index - // will stay coherent while removing them) - - for (int i = getRowCount() - 1; i > -1; i--) { - SimpleBeanValidatorMessage error = data.get(i); - if (validator.equals(error.getValidator()) && - error.getScope() == scope && - error.getField().equals(fieldName) && - messagesToDel.contains(error.getMessage())) { - // remove the message - data.remove(i); - if (notify) { - fireTableRowsDeleted(i, i); - } - } - } - } -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SimpleBeanValidatorMessageTableRenderer.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SimpleBeanValidatorMessageTableRenderer.java deleted file mode 100644 index 93d3ab5..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SimpleBeanValidatorMessageTableRenderer.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing; - -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.simple.SimpleBeanValidatorMessage; - -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.table.DefaultTableCellRenderer; -import java.awt.Component; - -import static org.nuiton.i18n.I18n.t; - -/** - * A simple render of a table of validator's messages, says a table that use - * a {@link SimpleBeanValidatorMessageTableModel} model. - * - * @author Tony Chemit - chemit@codelutin.com - * @see SimpleBeanValidatorMessageTableModel - * @since 2.6.23 - */ -public class SimpleBeanValidatorMessageTableRenderer extends DefaultTableCellRenderer { - - private static final long serialVersionUID = 1L; - - @Override - public Component getTableCellRendererComponent(JTable table, - Object value, - boolean isSelected, - boolean hasFocus, - int row, - int column) { - JLabel rendererComponent = (JLabel) - super.getTableCellRendererComponent( - table, - value, - isSelected, - hasFocus, - row, - column - ); - - ImageIcon icon = null; - String text = null; - String toolTipText = null; - - column = table.convertColumnIndexToModel(column); - if (table.getRowSorter() != null) { - row = table.getRowSorter().convertRowIndexToModel(row); - } - - switch (column) { - case 0: - // scope - NuitonValidatorScope scope = (NuitonValidatorScope) value; - icon = SwingValidatorUtil.getIcon(scope); - String label = t(scope.getLabel()); - toolTipText = t("validator.scope.tip", label); - break; - - case 1: - // field name - text = getFieldName(table, (String) value, row); - toolTipText = t("validator.field.tip", text); - break; - - case 2: - // message - text = getMessage(table, (String) value, row); - toolTipText = t("validator.message.tip", text); - break; - } - - rendererComponent.setText(text); - rendererComponent.setToolTipText(toolTipText); - rendererComponent.setIcon(icon); - return rendererComponent; - } - - public ImageIcon getIcon(NuitonValidatorScope scope) { - return SwingValidatorUtil.getIcon(scope); - } - - public String getMessage(JTable table, String value, int row) { - SimpleBeanValidatorMessageTableModel tableModel = - (SimpleBeanValidatorMessageTableModel) table.getModel(); - SimpleBeanValidatorMessage model = tableModel.getRow(row); - return SwingValidatorUtil.getMessage(model); - } - - public String getFieldName(JTable table, String value, int row) { - SimpleBeanValidatorMessageTableModel tableModel = - (SimpleBeanValidatorMessageTableModel) table.getModel(); - return value; - } -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidator.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidator.java deleted file mode 100644 index c2f00a5..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidator.java +++ /dev/null @@ -1,131 +0,0 @@ -package jaxx.runtime.validator.swing; - -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Preconditions; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.validator.NuitonValidator; -import org.nuiton.validator.NuitonValidatorFactory; -import org.nuiton.validator.NuitonValidatorProvider; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.list.BeanListValidator; - -import javax.swing.JComponent; - -/** - * Created on 9/17/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.13 - */ -public class SwingListValidator<B> extends BeanListValidator<B> { - - /** Logger */ - private static final Log log = LogFactory.getLog(SwingListValidator.class); - - /** - * Obtain a new {@link SwingListValidator} for the given parameters. - * - * <b>Note:</b> It will use the default provider of {@link NuitonValidator} - * - * @param type type of bean to validate - * @param context context of validation - * @param scopes authorized scopes (if {@code null}, will use all scopes) - * @param <O> type of bean to validate - * @return the new instanciated {@link BeanListValidator}. - * @throws NullPointerException if type is {@code null} - * @see NuitonValidatorFactory#getDefaultProviderName() - */ - public static <O> SwingListValidator<O> newSwingValidator(Class<O> type, - String context, - NuitonValidatorScope... scopes) throws NullPointerException { - - - // get the provider default name - String providerName = NuitonValidatorFactory.getDefaultProviderName(); - - // get the bean validator with this provider - return newSwingValidator(providerName, - type, - context, - scopes - ); - } - - /** - * Obtain a new {@link SwingListValidator} for the given parameters. - * - * <b>Note:</b> It will use the provider of {@link NuitonValidator} - * defined by the {@code providerName}. - * - * @param providerName name of {@link NuitonValidator} to use - * @param type type of bean to validate - * @param context context of validation - * @param scopes authorized scopes (if {@code null}, will use all scopes) - * @param <O> type of bean to validate - * @return the new instanciated {@link BeanListValidator}. - * @throws NullPointerException if type is {@code null} - * @see NuitonValidatorFactory#getProvider(String) - */ - public static <O> SwingListValidator<O> newSwingValidator(String providerName, - Class<O> type, - String context, - NuitonValidatorScope... scopes) throws NullPointerException { - - Preconditions.checkNotNull(type, "type parameter can not be null."); - - // get delegate validator provider - NuitonValidatorProvider provider = - NuitonValidatorFactory.getProvider(providerName); - - Preconditions.checkState( - provider != null, - "Could not find provider with name " + providerName); - - // create the new instance of bean validator - - return new SwingListValidator<O>( - provider, type, context, scopes - ); - } - - protected JComponent editor; - - public SwingListValidator(NuitonValidatorProvider validatorProvider, Class<B> beanClass, String context) { - super(validatorProvider, beanClass, context); - } - - public SwingListValidator(NuitonValidatorProvider validatorProvider, Class<B> beanClass, String context, NuitonValidatorScope... scopes) { - super(validatorProvider, beanClass, context, scopes); - } - - public JComponent getEditor() { - return editor; - } - - public void setEditor(JComponent editor) { - this.editor = editor; - } - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorDataLocator.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorDataLocator.java deleted file mode 100644 index 3c4bb7d..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorDataLocator.java +++ /dev/null @@ -1,77 +0,0 @@ -package jaxx.runtime.validator.swing; -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.lang3.tuple.Pair; - -import javax.swing.table.TableModel; - -/** - * Object that can locate for a given {@link SwingListValidatorMessage}, - * the cell of this data in a table editor. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.3 - */ -public interface SwingListValidatorDataLocator<O> { - - /** - * Tests if the given type can be managed by this locator. - * - * Useful if there is more than one locator used for a same list - * validation table model. - * - * @param beanType the type of bean to test - * @return {@code true} if this locator can manage this bean type. - */ - boolean acceptType(Class<?> beanType); - - /** - * Locate the cell of the given data. - * - * @param tableModel the table model where data are edited - * @param bean the bean to locate - * @param fieldName the field to locate - * @return the cell where to find data - */ - Pair<Integer, Integer> locateDataCell(TableModel tableModel, - O bean, - String fieldName); - - /** - * Locate the index of the row of the given bean. - * - * @param tableModel the table model where data are edited - * @param bean the bean to find - * @return the row index of the given bean in the table. - */ - int locateBeanRowIndex(TableModel tableModel, O bean); - - /** - * Locate the bean given his row index in the table. - * - * @param tableModel the table model where data are edited - * @param rowIndex the row index of the bean to find in the editor - * @return the bean corresponding to the given row index in the editor - */ - O locateBean(TableModel tableModel, int rowIndex); -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorHighlightPredicate.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorHighlightPredicate.java deleted file mode 100644 index d975f5d..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorHighlightPredicate.java +++ /dev/null @@ -1,139 +0,0 @@ -package jaxx.runtime.validator.swing; -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.jdesktop.swingx.decorator.ComponentAdapter; -import org.jdesktop.swingx.decorator.HighlightPredicate; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.list.BeanListValidator; - -import javax.swing.JTable; -import java.awt.Component; - -/** - * HighLight predicates for a table editor using {@link BeanListValidator} of - * his data. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.3 - */ -public class SwingListValidatorHighlightPredicate<O> implements HighlightPredicate { - - /** - * Filtering scope. - * - * @since 2.5.3 - */ - protected final NuitonValidatorScope scope; - - /** - * Validator (contains data). - * - * @since 2.5.3 - */ - protected final BeanListValidator<O> validator; - - /** - * Data locator to find back data in editor. - * - * @since 2.5.3 - */ - protected final SwingListValidatorDataLocator<O> dataLocator; - - public static <O> SwingListValidatorHighlightPredicate<O> newFatalPredicate( - BeanListValidator<O> validator, - SwingListValidatorDataLocator<O> dataLocator) { - return newPredicate( - NuitonValidatorScope.FATAL, - validator, - dataLocator - ); - } - - public static <O> SwingListValidatorHighlightPredicate<O> newErrorPredicate( - BeanListValidator<O> validator, - SwingListValidatorDataLocator<O> dataLocator) { - return newPredicate( - NuitonValidatorScope.ERROR, - validator, - dataLocator - ); - } - - public static <O> SwingListValidatorHighlightPredicate<O> newWarningPredicate( - BeanListValidator<O> validator, - SwingListValidatorDataLocator<O> dataLocator) { - return newPredicate( - NuitonValidatorScope.WARNING, - validator, - dataLocator - ); - } - - public static <O> SwingListValidatorHighlightPredicate<O> newInfoPredicate( - BeanListValidator<O> validator, - SwingListValidatorDataLocator<O> dataLocator) { - return newPredicate( - NuitonValidatorScope.INFO, - validator, - dataLocator - ); - } - - public static <O> SwingListValidatorHighlightPredicate<O> newPredicate( - NuitonValidatorScope scope, - BeanListValidator<O> validator, - SwingListValidatorDataLocator<O> dataLocator) { - return new SwingListValidatorHighlightPredicate<O>( - scope, - validator, - dataLocator - ); - } - - public SwingListValidatorHighlightPredicate(NuitonValidatorScope scope, - BeanListValidator<O> validator, - SwingListValidatorDataLocator<O> dataLocator) { - this.scope = scope; - this.validator = validator; - this.dataLocator = dataLocator; - } - - @Override - public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { - - int columnIndex = adapter.convertColumnIndexToModel(adapter.column); - - String fieldName = adapter.getColumnName(columnIndex); - - int rowIndex = adapter.convertRowIndexToModel(adapter.row); - JTable component = (JTable) adapter.getComponent(); - O bean = dataLocator.locateBean(component.getModel(), rowIndex); - boolean result = false; - if (bean != null && dataLocator.acceptType(bean.getClass())) { - BeanListValidator.NuitonValidatorContext<O> context = validator.getContext(bean); - NuitonValidatorScope highestScope = context.getHighestScope(fieldName); - result = scope == highestScope; - } - return result; - } -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessage.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessage.java deleted file mode 100644 index bfa7548..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessage.java +++ /dev/null @@ -1,67 +0,0 @@ -package jaxx.runtime.validator.swing; -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.list.BeanListValidator; -import org.nuiton.validator.bean.list.BeanListValidatorMessage; - -import javax.swing.JComponent; - -/** - * TODO - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.3 - */ -public class SwingListValidatorMessage extends BeanListValidatorMessage<SwingListValidatorMessage> { - - private static final long serialVersionUID = 1L; - - /** the optional field's editor */ - protected JComponent editor; - - public SwingListValidatorMessage(BeanListValidator<?> validator, - Object bean, - String fieldName, - String message, - NuitonValidatorScope scope, - JComponent editor) { - super(validator, bean, fieldName, message, scope); - this.editor = editor; - } - - public JComponent getEditor() { - return editor; - } - - @Override - public String toString() { - String s = scope + " - " + - (field == null ? message : field + "[" + getBean() + - "] - " + message); - if (editor != null) { - s = editor.getName() + " : " + s; - } - return s; - } -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessageTableModel.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessageTableModel.java deleted file mode 100644 index 044632c..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessageTableModel.java +++ /dev/null @@ -1,275 +0,0 @@ -package jaxx.runtime.validator.swing; -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import jaxx.runtime.SwingUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.list.BeanListValidator; -import org.nuiton.validator.bean.list.BeanListValidatorEvent; -import org.nuiton.validator.bean.list.BeanListValidatorListener; - -import javax.swing.JComponent; -import javax.swing.table.AbstractTableModel; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * The model of the table of errors. - * - * The model listens list-validators messages and update his internal model - * from it. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.3 - */ -public class SwingListValidatorMessageTableModel extends AbstractTableModel - implements BeanListValidatorListener { - - private static final long serialVersionUID = 1L; - - /** Logger */ - private static Log log = - LogFactory.getLog(SwingListValidatorMessageTableModel.class); - - public static final String[] columnNames = - {"validator.scope", "validator.bean", - "validator.field", "validator.message"}; - - public static final Class<?>[] columnClasses = - {NuitonValidatorScope.class, Object.class, String.class, String.class}; - - /** list of registred validators */ - protected transient List<BeanListValidator<?>> validators; - - /** list of messages actual displayed */ - protected List<SwingListValidatorMessage> data; - - public SwingListValidatorMessageTableModel() { - data = Lists.newArrayList(); - validators = Lists.newArrayList(); - } - - /** - * Register a validator for this model. - * - * - * Note: a validator can not be register twice in the same model. - * - * @param validator the validator to register - */ - public void registerValidator(BeanListValidator<?> validator) { - Preconditions.checkState( - !validators.contains(validator), - "Validator " + validator + " is already registred in " - + this); - validators.add(validator); - validator.addBeanListValidatorListener(this); - } - - public void clear() { - int i = data.size() + data.size(); - if (i > 0) { - data.clear(); - fireTableRowsDeleted(0, i - 1); - } - } - - public void clearValidators() { - for (BeanListValidator<?> v : validators) { - v.removeBeanListValidatorListener(this); - } - validators.clear(); - } - - /** - * Obtain the message for a given row. - * - * @param rowIndex the row index - * @return the message for the given row index - */ - public SwingListValidatorMessage getRow(int rowIndex) { - SwingUtil.ensureRowIndex(this, rowIndex); - return data.get(rowIndex); - } - - @Override - public boolean isCellEditable(int row, int column) { - // cells are never editable in this model - return false; - } - - @Override - public Class<?> getColumnClass(int columnIndex) { - SwingUtil.ensureColumnIndex(this, columnIndex); - return columnClasses[columnIndex]; - } - - @Override - public String getColumnName(int column) { - SwingUtil.ensureColumnIndex(this, column); - return columnNames[column]; - } - - @Override - public void onFieldChanged(BeanListValidatorEvent event) { - String[] toDelete = event.getMessagesToDelete(); - String[] toAdd = event.getMessagesToAdd(); - String field = event.getField(); - Object bean = event.getBean(); - NuitonValidatorScope scope = event.getScope(); - boolean mustAdd = toAdd != null && toAdd.length > 0; - boolean mustDel = toDelete != null && toDelete.length > 0; - - if (log.isTraceEnabled()) { - log.trace("----------------------------------------------------------"); - log.trace(field + " - (" + getRowCount() + ") toAdd " + mustAdd); - log.trace(field + " - (" + getRowCount() + ") toDelete " + mustDel); - } - - BeanListValidator<?> validator = event.getSource(); - - if (mustDel) { - - // removes datas and notify if no messages to add - removeMessages(validator, bean, field, scope, !mustAdd, toDelete); - } - - if (mustAdd) { - - // add new messages, sort datas and notify - addMessages(validator, bean, field, scope, true, toAdd); - } - } - - @Override - public int getRowCount() { - return data.size(); - } - - @Override - public int getColumnCount() { - return columnNames.length; - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - SwingUtil.ensureColumnIndex(this, columnIndex); - SwingUtil.ensureRowIndex(this, rowIndex); - - SwingListValidatorMessage row = data.get(rowIndex); - if (columnIndex == 0) { - // the icon - return row.getScope(); - } - if (columnIndex == 1) { - // the bean - return row.getBean(); - } - if (columnIndex == 2) { - // the field - return row.getField(); - } - if (columnIndex == 3) { - // the message - return row.getMessage(); - } - - // should never come here - return null; - } - - protected void addMessages(BeanListValidator<?> validator, - Object bean, - String fieldName, - NuitonValidatorScope scope, - boolean sort, - String... messages) { - -// JComponent editor = validator == null ? -// null : -// validator.getFieldRepresentation(fieldName); - - JComponent editor = null; - - // add new errors - for (String error : messages) { - SwingListValidatorMessage row = - new SwingListValidatorMessage( - validator, - bean, - fieldName, - error, - scope, - editor - ); - data.add(row); - if (!sort) { - fireTableRowsInserted(data.size() - 1, data.size() - 1); - } - } - - if (sort) { - - // resort datas - Collections.sort(data); - - // notify - fireTableDataChanged(); - } - } - - protected void removeMessages(BeanListValidator<?> validator, - Object bean, - String fieldName, - NuitonValidatorScope scope, - boolean notify, - String... messages) { - - List<String> messagesToDel = - new ArrayList<String>(Arrays.asList(messages)); - - // do it in reverse mode (only one pass in that way since index - // will stay coherent while removing them) - - for (int i = getRowCount() - 1; i > -1; i--) { - SwingListValidatorMessage error = data.get(i); - if (validator.equals(error.getValidator()) && - error.getScope() == scope && - error.getBean() == bean && - error.getField().equals(fieldName) && - messagesToDel.contains(error.getMessage())) { - // remove the message - data.remove(i); - if (notify) { - fireTableRowsDeleted(i, i); - } - } - } - } - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessageTableMouseListener.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessageTableMouseListener.java deleted file mode 100644 index 704e470..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessageTableMouseListener.java +++ /dev/null @@ -1,149 +0,0 @@ -package jaxx.runtime.validator.swing; -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.SwingUtil; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.JTable; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; - -/** - * A mouse listener to edit a cell when double clicking on a validation - * message coming from a {@link SwingValidatorMessageTableModel}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.3 - */ -public class SwingListValidatorMessageTableMouseListener extends MouseAdapter { - - /** Logger */ - private static Log log = - LogFactory.getLog(SwingListValidatorMessageTableMouseListener.class); - - public static final String HIGHLIGHT_ERROR_PROPERTY = "highlightError"; - - /** - * Delegate property change support. - * - * @since 2.5.3 - */ - protected PropertyChangeSupport pcs; - - /** - * The editor of listened bean. - * - * @since 2.5.3 - */ - protected final JTable editor; - - /** - * The cell data locator. - * - * @since 2.5.3 - */ - protected final SwingListValidatorDataLocator dataLocator; - - public SwingListValidatorMessageTableMouseListener( - JTable editor, - SwingListValidatorDataLocator dataLocator) { - this.editor = editor; - this.dataLocator = dataLocator; - pcs = new PropertyChangeSupport(this); - } - - @Override - public void mouseClicked(MouseEvent e) { - super.mouseClicked(e); - if (e.getClickCount() == 2) { - - SwingListValidatorMessage entry = getSelectedMessage(e); - if (entry == null) { - // no entry found - return; - } - - if (dataLocator.acceptType(entry.getBean().getClass())) { - - Pair<Integer, Integer> cell = dataLocator.locateDataCell( - editor.getModel(), - entry.getBean(), - entry.getField()); - - SwingUtil.editCell(editor, cell.getLeft(), cell.getRight()); - } - - } - } - - protected SwingListValidatorMessage getSelectedMessage(MouseEvent e) { - JTable table = (JTable) e.getSource(); - if (!(table.getModel() instanceof SwingListValidatorMessageTableModel)) { - if (log.isWarnEnabled()) { - log.warn("model must be a " + - SwingValidatorMessageTableModel.class + - ", but was " + table.getModel()); - } - return null; - } - - SwingListValidatorMessageTableModel model = - (SwingListValidatorMessageTableModel) table.getModel(); - int index = table.getSelectionModel().getMinSelectionIndex(); - if (index == -1) { - // nothing is selected - return null; - } - if (table.getRowSorter() != null) { - index = table.getRowSorter().convertRowIndexToModel(index); - } - SwingListValidatorMessage entry = model.getRow(index); - if (log.isDebugEnabled()) { - log.debug("selected index: " + index + " : error: " + entry); - } - return entry; - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - pcs.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - pcs.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.removePropertyChangeListener(propertyName, listener); - } - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessageTableRenderer.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessageTableRenderer.java deleted file mode 100644 index 868b206..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessageTableRenderer.java +++ /dev/null @@ -1,132 +0,0 @@ -package jaxx.runtime.validator.swing; -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.nuiton.validator.NuitonValidatorScope; - -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.table.DefaultTableCellRenderer; -import java.awt.Component; - -import static org.nuiton.i18n.I18n.t; - -/** - * TODO - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.3 - */ -public class SwingListValidatorMessageTableRenderer extends DefaultTableCellRenderer { - - private static final long serialVersionUID = 1L; - - @Override - public Component getTableCellRendererComponent(JTable table, - Object value, - boolean isSelected, - boolean hasFocus, - int row, - int column) { - JLabel rendererComponent = (JLabel) - super.getTableCellRendererComponent( - table, - value, - isSelected, - hasFocus, - row, - column - ); - - ImageIcon icon = null; - String text = null; - String toolTipText = null; - - column = table.convertColumnIndexToModel(column); - if (table.getRowSorter() != null) { - row = table.getRowSorter().convertRowIndexToModel(row); - } - - switch (column) { - case 0: - // scope - NuitonValidatorScope scope = (NuitonValidatorScope) value; - icon = SwingValidatorUtil.getIcon(scope); - String label = t(scope.getLabel()); - toolTipText = t("validator.scope.tip", label); - break; - - case 1: - // row bean - text = getBeanValue(table, row); - toolTipText = t("validator.bean.tip", text); - break; - - case 2: - // field name - text = getFieldName(table, (String) value, row); - toolTipText = t("validator.field.tip", text); - break; - - case 3: - // message - text = getMessage(table, (String) value, row); - toolTipText = t("validator.message.tip", text); - break; - } - - rendererComponent.setText(text); - rendererComponent.setToolTipText(toolTipText); - rendererComponent.setIcon(icon); - return rendererComponent; - } - - public ImageIcon getIcon(NuitonValidatorScope scope) { - return SwingValidatorUtil.getIcon(scope); - } - - public String getMessage(JTable table, String value, int row) { - SwingListValidatorMessageTableModel tableModel = - (SwingListValidatorMessageTableModel) table.getModel(); - SwingListValidatorMessage model = tableModel.getRow(row); - return SwingValidatorUtil.getMessage(model); - } - - public String getFieldName(JTable table, String value, int row) { - SwingListValidatorMessageTableModel tableModel = - (SwingListValidatorMessageTableModel) table.getModel(); - SwingListValidatorMessage model = tableModel.getRow(row); - return SwingValidatorUtil.getFieldName(model, value); - } - - public String getBeanValue(JTable table, int row) { - SwingListValidatorMessageTableModel tableModel = - (SwingListValidatorMessageTableModel) table.getModel(); - SwingListValidatorMessage model = tableModel.getRow(row); - return decorateBean(model.getBean()); - } - - protected String decorateBean(Object bean) { - return bean.toString(); - } -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessageWidget.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessageWidget.java deleted file mode 100644 index 9bdf904..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorMessageWidget.java +++ /dev/null @@ -1,294 +0,0 @@ -package jaxx.runtime.validator.swing; - -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.SwingUtil; -import jaxx.runtime.swing.ComponentMover; -import jaxx.runtime.swing.ComponentResizer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.JXTitledPanel; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.list.BeanListValidator; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JRootPane; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.JToggleButton; -import javax.swing.JToolBar; -import javax.swing.KeyStroke; -import javax.swing.ListSelectionModel; -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; -import javax.swing.table.TableCellRenderer; -import java.awt.Component; -import java.awt.Point; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.HierarchyBoundsAdapter; -import java.awt.event.HierarchyEvent; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -import static org.nuiton.i18n.I18n.n; -import static org.nuiton.i18n.I18n.t; - -/** - * @author Sylvain Bavencoff - bavencoff@codelutin.com - * @since 2.10 - */ -public class SwingListValidatorMessageWidget extends JToggleButton { - - private static final Log log = - LogFactory.getLog(SwingListValidatorMessageWidget.class); - - private static final long serialVersionUID = 1L; - - public static final String CLOSE_DIALOG_ACTION = "closeDialog"; - - protected SwingListValidatorMessageTableModel messageTableModel = new SwingListValidatorMessageTableModel(); - - protected JDialog popup = new JDialog(); - - protected JTable messageTable = new JTable(); - - protected Point popupPosition = null; - - public SwingListValidatorMessageWidget() { - super(SwingUtil.createActionIcon("alert-none")); - setToolTipText(t("validator.messageWidget.alert.none")); - - messageTableModel.addTableModelListener(new TableModelListener() { - - public void tableChanged(TableModelEvent e) { - int alerts = messageTableModel.getRowCount(); - String label; - switch (alerts) { - case 0: - label = n("validator.messageWidget.alert.none"); - break; - case 1: - label = n("validator.messageWidget.alert.one"); - break; - default: - label = n("validator.messageWidget.alert.several"); - } - - NuitonValidatorScope maxScope; - String icon; - if (alerts == 0) { - icon = "alert-none"; - - } else { - maxScope = NuitonValidatorScope.INFO; - for (int i = 0; i < alerts; i++) { - NuitonValidatorScope scope = messageTableModel.getRow(i).getScope(); - int diff = scope.compareTo(maxScope); - if (diff < 0) { - maxScope = scope; - } - } - switch (maxScope) { - case INFO: - icon = "alert-info"; - break; - case WARNING: - icon = "alert-warning"; - break; - default: - icon = "alert-error"; - - } - } - - setToolTipText(t(label, alerts)); - setIcon(SwingUtil.createActionIcon(icon)); - } - }); - - messageTable.setModel(messageTableModel); - messageTable.setRowSelectionAllowed(true); - messageTable.setAutoCreateRowSorter(true); - messageTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); - messageTable.setCellSelectionEnabled(false); - messageTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - messageTable.setFillsViewportHeight(true); - - SwingValidatorUtil.installUI(messageTable, - new SwingListValidatorMessageTableRenderer()); - - JScrollPane scrollPanel = new JScrollPane(messageTable); - scrollPanel.setColumnHeaderView(messageTable.getTableHeader()); - - JXTitledPanel titledPanel = new JXTitledPanel(t("validator.messageWidget.title"), scrollPanel); - popup.add(titledPanel); - popup.setTitle(t("validator.messageWidget.title")); - popup.setSize(800, 300); - popup.setAlwaysOnTop(true); - popup.setUndecorated(true); - - ComponentResizer cr = new ComponentResizer(); - cr.registerComponent(popup); - ComponentMover cm = new ComponentMover(); - cm.setDragInsets(cr.getDragInsets()); - cm.registerComponent(popup); - - popup.addWindowListener(new WindowAdapter() { - - @Override - public void windowClosing(WindowEvent e) { - setSelected(false); - } - - }); - - popup.addComponentListener(new ComponentAdapter() { - - @Override - public void componentMoved(ComponentEvent e) { - Component component = e.getComponent(); - if (component.isShowing()) { - popupPosition = component.getLocationOnScreen(); - } - } - - }); - - addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - if (isSelected()) { - popup.setVisible(true); - } else { - popup.dispose(); - } - } - }); - - addHierarchyBoundsListener(new HierarchyBoundsAdapter() { - - @Override - public void ancestorMoved(HierarchyEvent e) { - if (popupPosition == null && isShowing()) { - Point point = new Point(getLocationOnScreen()); - point.translate(-popup.getWidth() + getWidth(), -popup.getHeight()); - popup.setLocation(point); - } - } - }); - - // add a auto-close action - JRootPane rootPane = popup.getRootPane(); - - KeyStroke shortcutClosePopup = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); - - rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( - shortcutClosePopup, CLOSE_DIALOG_ACTION); - - Action closeAction = new AbstractAction() { - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent e) { - popup.dispose(); - setSelected(false); - } - }; - - ImageIcon actionIcon = SwingUtil.createActionIcon("close-dialog"); - closeAction.putValue(Action.SMALL_ICON, actionIcon); - closeAction.putValue(Action.LARGE_ICON_KEY, actionIcon); - closeAction.putValue(Action.ACTION_COMMAND_KEY, "close"); - closeAction.putValue(Action.NAME, "close"); - closeAction.putValue(Action.SHORT_DESCRIPTION, t("validator.messageWidget.closeDialog.tip")); - - rootPane.getActionMap().put(CLOSE_DIALOG_ACTION, closeAction); - - JButton closeButton = new JButton(closeAction); - closeButton.setText(null); - closeButton.setFocusPainted(false); - closeButton.setRequestFocusEnabled(false); - closeButton.setFocusable(false); - - JToolBar jToolBar = new JToolBar(); - jToolBar.setOpaque(false); - jToolBar.add(closeAction); - jToolBar.setBorderPainted(false); - jToolBar.setFloatable(false); - titledPanel.setRightDecoration(jToolBar); - - } - - public void addTableModelListener(TableModelListener listener) { - messageTableModel.addTableModelListener(listener); - } - - public void removeTableModelListener(TableModelListener listener) { - messageTableModel.removeTableModelListener(listener); - } - - public void setDefaultRenderer(TableCellRenderer renderer) { - messageTable.setDefaultRenderer(Object.class, renderer); - } - - /** - * Register a list validator. - * - * @param validator validator to register - * @param dataTable table with data to validate by the validator - * @param dataLocator tool to find data in the data table from the validator messages - */ - public void registerValidator(BeanListValidator validator, - JTable dataTable, - SwingListValidatorDataLocator dataLocator) { - - if (log.isInfoEnabled()) { - log.info("Register validator: " + validator); - } - SwingValidatorUtil.registerListValidator( - validator, - messageTableModel, - dataTable, - messageTable, - dataLocator); - - validator.doValidate(); - } - - /** Clear all the validators. */ - public void clearValidators() { - messageTableModel.clearValidators(); - messageTableModel.clear(); - } - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorTableEditorModelListener.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorTableEditorModelListener.java deleted file mode 100644 index f9f643e..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingListValidatorTableEditorModelListener.java +++ /dev/null @@ -1,149 +0,0 @@ -package jaxx.runtime.validator.swing; -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.collect.Sets; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.validator.bean.list.BeanListValidator; - -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; -import javax.swing.table.TableModel; -import java.util.Set; - -/** - * Listens a table model which is the editor of a list of bean, add and remove - * beans to the target validator. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.3 - */ -public class SwingListValidatorTableEditorModelListener<O> implements TableModelListener { - - /** Logger. */ - private static final Log log = - LogFactory.getLog(SwingListValidatorTableEditorModelListener.class); - - private final SwingListValidatorDataLocator<O> dataLocator; - - private BeanListValidator<O> validator; - - public SwingListValidatorTableEditorModelListener( - BeanListValidator<O> validator, - SwingListValidatorDataLocator<O> dataLocator) { - this.dataLocator = dataLocator; - this.validator = validator; - } - - @Override - public void tableChanged(TableModelEvent e) { - - TableModel model = (TableModel) e.getSource(); - - int type = e.getType(); - - int firstRow = e.getFirstRow(); - int lastRow = e.getLastRow(); - - switch (type) { - case TableModelEvent.INSERT: - - onRowsInserted(model, firstRow, lastRow); - - break; - case TableModelEvent.DELETE: - - onRowsDeleted(model); - - break; - case TableModelEvent.UPDATE: - - if (e.getColumn() == TableModelEvent.ALL_COLUMNS - && firstRow == 0 - && lastRow == Integer.MAX_VALUE) { - - // fireTableDataChanged - - onDataChanged(model); - - } - break; - } - } - - protected void onRowsInserted(TableModel model, int firstRow, int lastRow) { - - Set<O> beans = Sets.newHashSet(); - - for (int i = firstRow; i <= lastRow; i++) { - - O bean = dataLocator.locateBean(model, i); - if (log.isDebugEnabled()) { - log.debug("Add a bean to validator " + bean); - } - beans.add(bean); - } - - validator.addAllBeans(beans); - - } - - protected void onRowsDeleted(TableModel model) { - - - // bean are no more existing in editor, must then find out - // which beans must be deleted from all the beans in the validator - - Set<O> beans = Sets.newHashSet(validator.getBeans()); - for (int i = 0, max = model.getRowCount(); i < max; i++) { - O bean = dataLocator.locateBean(model, i); - if (log.isDebugEnabled()) { - log.debug("Remove a bean from validator " + bean); - } - beans.remove(bean); - } - - validator.removeAllBeans(beans); - - } - - protected void onDataChanged(TableModel model) { - - - // remove all beans from validator - validator.removeAllBeans(); - - // add all beans from model - - Set<O> beans = Sets.newHashSet(); - for (int i = 0, max = model.getRowCount(); i < max; i++) { - O bean = dataLocator.locateBean(model, i); - if (log.isDebugEnabled()) { - log.debug("Add a bean to validator " + bean); - } - beans.add(bean); - } - validator.addAllBeans(beans); - - } -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidator.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidator.java deleted file mode 100644 index 3f2bcc2..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidator.java +++ /dev/null @@ -1,485 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing; - -import com.google.common.base.Preconditions; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; -import jaxx.runtime.validator.swing.ui.AbstractBeanValidatorUI; -import jaxx.runtime.validator.swing.ui.IconValidationUI; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.jxlayer.JXLayer; -import org.nuiton.validator.NuitonValidator; -import org.nuiton.validator.NuitonValidatorFactory; -import org.nuiton.validator.NuitonValidatorProvider; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.simple.SimpleBeanValidator; - -import javax.swing.JComponent; -import java.awt.Container; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -/** - * La surcharge de {@link SimpleBeanValidator} pour les ui swing - * - * Permet d'ajouter facilement le support de la validation des champs d'un bean - * et de le relier a une interface graphique. Utilise xwork pour la validation - * et JXLayer pour la visualisation. - * - * - * Le mieux pour son integration dans Jaxx est de faire de la generation pour - * force la compilation du code suivant: - * - * <pre> - * myValidor.getBean().get<field>(); - * </pre> - * - * et ceci pour chaque field ajoute a la map fieldRepresentation. De cette facon - * meme si le champs field est en texte on a une verification de son existance a - * la compilation. - * - * - * La representation en tag pourrait etre - * <pre> - * <validator id="myValidator" beanClass="{Personne.class}" - * errorList="$list"> - * <field name="name" component="$name"/> - * <field name="firstName" component="$firstName"/> - * <field name="birthDate" component="$birthDate"/> - * </validator> - * <validator beanClass="{Personne.class}" autoField="true" - * errorList="$list"> - * <fieldRepresentation name="name" component="$lastName"/> - * </validator> - * </pre> - * - * dans le premier exemple on fait un mapping explicite des champs, mais on voit - * que le nom du composant graphique est le meme que celui du champs. Pour - * eviter de longue saisie, il est possible d'utiliser le flag <b>autoField</b> - * qui pour chaque champs du ayant une methode get du bean recherche un - * composant avec cet Id. Il est aussi possible de surcharge un champs - * explicitement comme ici name, dans le cas ou le composant qui porterait ce - * nom serait utilise pour autre chose. - * - * - * Il faut un handler particulier pour ce composant car les attributs - * <b>beanClass</b> et <b>autoField</b> ne sont present que dans le XML jaxx et - * servent a la generation. Il faut aussi prendre en compte les elements - * fieldRepresentation fils du tag validator. - * - * - * Voici ce que pourrait etre le code genere par jaxx - * <pre> - * // declaration du bean - * BeanValidator<beanClass> $myValidator; - * // init du bean - * protected void createMyValidator() { - * $myValidator = new BeanValidator<beanClass>(); - * // genere seulement si autoField = true - * for (Method m : beanClass.getMethod()) { - * if (m.getName().startsWith("get")) { - * String fieldName = m.getName().substring(3).toLowerCase(); - * $myValidator.setFieldRepresentation(fieldName, - * $objectMap.get(fieldName)); - * } - * } - * // pour chaque tag fieldRepresentation - * myValidator.setFieldRepresentation("name", $lastName); - * // si beanClass est specifie et n'est pas Object, on force l'acces au - * champs - * // pour validation a la compilation - * $myValidator.getBean().getName(); - * $objectMap.put("myValidator", $myValidator); - * } - * </pre> - * - * @param <B> le type de bean a valider - * @author Tony Chemit - chemit@codelutin.com - * @version 1.0 - */ -public class SwingValidator<B> extends SimpleBeanValidator<B> { - - /** Logger */ - private static final Log log = LogFactory.getLog(SwingValidator.class); - - private static final Class<? extends AbstractBeanValidatorUI> - DEFAULT_UI_CLASS = IconValidationUI.class; - - /** - * Obtain a new {@link SimpleBeanValidator} for the given parameters. - * - * <b>Note:</b> It will use the default provider of {@link NuitonValidator} - * - * @param type type of bean to validate - * @param context context of validation - * @param scopes authorized scopes (if {@code null}, will use all scopes) - * @param <O> type of bean to validate - * @return the new instanciated {@link SimpleBeanValidator}. - * @throws NullPointerException if type is {@code null} - * @see NuitonValidatorFactory#getDefaultProviderName() - */ - public static <O> SwingValidator<O> newValidator( - Class<O> type, - String context, - NuitonValidatorScope... scopes) throws NullPointerException { - - - // get the provider default name - String providerName = NuitonValidatorFactory.getDefaultProviderName(); - - // get the bean validator with this provider - return newValidator(providerName, - type, - context, - scopes - ); - } - - /** - * Obtain a new {@link SimpleBeanValidator} for the given parameters. - * - * <b>Note:</b> It will use the provider of {@link NuitonValidator} - * defined by the {@code providerName}. - * - * @param providerName name of {@link NuitonValidator} to use - * @param type type of bean to validate - * @param context context of validation - * @param scopes authorized scopes (if {@code null}, will use all scopes) - * @param <O> type of bean to validate - * @return the new instanciated {@link SimpleBeanValidator}. - * @throws NullPointerException if type is {@code null} - * @see NuitonValidatorFactory#getProvider(String) - */ - public static <O> SwingValidator<O> newValidator( - String providerName, - Class<O> type, - String context, - NuitonValidatorScope... scopes) throws NullPointerException { - - Preconditions.checkNotNull(type, - "type parameter can not be null."); - - // get delegate validator provider - NuitonValidatorProvider provider = - NuitonValidatorFactory.getProvider(providerName); - - Preconditions.checkState( - provider != null, - "Could not find provider with name " + providerName); - - // create the new instance of bean validator - - return new SwingValidator<O>( - provider, type, context, scopes); - } - - /** - * permet de faire le lien en un champs du bean et l'objet qui permet de - * l'editer - */ - protected final Map<String, JComponent> fieldRepresentation; - - /** Object servant a contenir la liste des erreurs */ - protected SwingValidatorMessageListModel errorListModel; - - /** Object servant a contenir la liste des erreurs */ - protected SwingValidatorMessageTableModel errorTableModel; - - /** ui renderer class */ - protected Class<? extends AbstractBeanValidatorUI> uiClass; - - public SwingValidator(NuitonValidatorProvider provider, - Class<B> beanClass, - String contextName, - NuitonValidatorScope... filterScopes) { - super(provider, beanClass, contextName, filterScopes); - fieldRepresentation = new HashMap<String, JComponent>(); - } - - public SwingValidator(Class<B> beanClass, - String contextName, - NuitonValidatorScope... filterScopes) { - super(NuitonValidatorFactory.getDefaultProvider(), - beanClass, - contextName, - filterScopes - ); - fieldRepresentation = new HashMap<String, JComponent>(); - } - - public SwingValidator(Class<B> beanClass, String contextName) { - this(beanClass, contextName, NuitonValidatorScope.values()); - } - - /** - * To reload a bean in the validator. - * - * This method is used to reload ui, since some editors could not exist when - * validator is init, so some messages should not be attached to an editor. - */ - public void reloadBean() { - B b = getBean(); - if (log.isInfoEnabled()) { - log.info("Will reload bean : " + b); - } - if (b != null) { - setBean(null); - setBean(b); - } - } - - public JComponent getFieldRepresentation(String fieldname) { - return fieldRepresentation.get(fieldname); - } - - public Class<? extends AbstractBeanValidatorUI> getUiClass() { - return uiClass; - } - - public void setErrorListModel( - SwingValidatorMessageListModel errorListModel) { - this.errorListModel = errorListModel; - if (errorListModel != null) { - // register the validator in the model list - errorListModel.registerValidator(this); - } - } - - public void setErrorTableModel( - SwingValidatorMessageTableModel errorTableModel) { - this.errorTableModel = errorTableModel; - if (errorTableModel != null) { - // register the validator in the model table - errorTableModel.registerValidator(this); - } - } - - public void setUiClass(Class<? extends AbstractBeanValidatorUI> uiClass) { - this.uiClass = uiClass; - } - - @Override - public void setContext(String context) { - String oldContext = getContext(); - - super.setContext(context); - - if (context == null && oldContext == null || - context != null && context.equals(oldContext)) { - - // same context do nothing - return; - } - if (fieldRepresentation != null) { - - // must reinstall ui - installUIs(); - } - } - - /** - * Permet d'indiquer le composant graphique responsable de l'affichage d'un - * attribut du bean - * - * @param fieldname the field name in the bean - * @param c the editor component for the field - */ - public void setFieldRepresentation(String fieldname, JComponent c) { - boolean fieldFound = getDelegate().getEffectiveFields().contains(fieldname); - - if (!fieldFound) { - // no field registred in the validator - if (log.isWarnEnabled()) { - log.warn("the field '" + fieldname + - "' is not defined in validator (no rules on it)"); - } - } else { - if (log.isInfoEnabled()) { - log.info("register field [" + fieldname + "] with component : " + - c.getName() - ); - } - fieldRepresentation.put(fieldname, c); - } - } - - public void setFieldRepresentation( - Map<String, JComponent> fieldRepresentation) { - for (Map.Entry<String, JComponent> e : fieldRepresentation.entrySet()) { - setFieldRepresentation(e.getKey(), e.getValue()); - } - } - - @Override - public SwingValidator<?> getParentValidator() { - return (SwingValidator<?>) super.getParentValidator(); - } - - public void setParentValidator(SwingValidator<?> parentValidator) { - super.setParentValidator(parentValidator); - } - - /** install ui on required components */ - public void installUIs() { - if (fieldRepresentation == null) { - throw new NullPointerException( - "fieldRepresentation is null, must init before " + - "invoking installUIs method..."); - } - - if (uiClass == null) { - // use the default one - uiClass = DEFAULT_UI_CLASS; - } - - // compute reverse map of fieldRepresentation : a same editor can - // reference more than one field - Multimap<JComponent, String> fieldsByEditor = - ArrayListMultimap.create(); - for (Entry<String, JComponent> entry : - fieldRepresentation.entrySet()) { - fieldsByEditor.put(entry.getValue(), entry.getKey()); - } - - for (JComponent editor : fieldsByEditor.keySet()) { - Collection<String> fields = fieldsByEditor.get(editor); - try { - setMessageRepresentation( - editor, - fields, - uiClass - ); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - -// for (Entry<String, JComponent> entry : -// fieldRepresentation.entrySet()) { -// try { -// setMessageRepresentation( -// entry.getKey(), -// null, -// entry.getValue(), -// uiClass -// ); -// } catch (Exception e) { -// throw new RuntimeException(e); -// } -// } - } - - protected void setMessageRepresentation( - JComponent c, - Collection<String> fieldnames, - Class<? extends AbstractBeanValidatorUI> uiClass) - throws InvocationTargetException, - IllegalAccessException, - InstantiationException, - NoSuchMethodException { - - Preconditions.checkNotNull(c, "No editor"); - - // ajout du jxlayer sous ce composant - Container container = c.getParent(); - if (container instanceof JXLayer<?>) { - JXLayer jx = (JXLayer<?>) container; - Object oldUI = jx.getUI(); - if (oldUI != null && oldUI instanceof AbstractBeanValidatorUI) { - - // supression de l'ancien layer - removeSimpleBeanValidatorListener((AbstractBeanValidatorUI) oldUI); - } - Constructor<? extends AbstractBeanValidatorUI> cons = - uiClass.getConstructor(Collection.class); - AbstractBeanValidatorUI ui = cons.newInstance(fieldnames); - -// ui.setEnabled(true); - addSimpleBeanValidatorListener(ui); - jx.setUI(ui); - } - } - - @Deprecated - protected void setMessageRepresentation( - String fieldname, - JComponent old, - JComponent c, - Class<? extends AbstractBeanValidatorUI> uiClass) - throws InvocationTargetException, - IllegalAccessException, - InstantiationException, - NoSuchMethodException { - if (old == c) { - // same component, nothing to do - return; - } - - boolean fieldFound = getDelegate().getEffectiveFields().contains(fieldname); - - if (!fieldFound) { - // this case should not appear since fieldName has already been - // check in method addFieldRepresentation - return; - } - if (old != null) { - // suppression du jxlayer sous l'ancien composant - Container container = old.getParent(); - if (container instanceof JXLayer<?>) { - JXLayer<?> jx = (JXLayer<?>) container; - Object ui = jx.getUI(); - if (ui != null && ui instanceof AbstractBeanValidatorUI) { - removeSimpleBeanValidatorListener((AbstractBeanValidatorUI) ui); - } - - jx.setUI(null); - } - } - if (c != null) { - // ajout du jxlayer sous ce composant - Container container = c.getParent(); - if (container instanceof JXLayer<?>) { - JXLayer jx = (JXLayer<?>) container; - Object oldUI = jx.getUI(); - if (oldUI != null && oldUI instanceof AbstractBeanValidatorUI) { - - // supression de l'ancien layer - removeSimpleBeanValidatorListener((AbstractBeanValidatorUI) oldUI); - } - Constructor<? extends AbstractBeanValidatorUI> cons = - uiClass.getConstructor(String.class); - AbstractBeanValidatorUI ui = cons.newInstance(fieldname); - -// ui.setEnabled(true); - addSimpleBeanValidatorListener(ui); - jx.setUI(ui); - } - } - } - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessage.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessage.java deleted file mode 100644 index 26a09d0..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessage.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing; - -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.simple.SimpleBeanValidatorMessage; - -import javax.swing.JComponent; - -/** - * The object to box a validation message within an swing ui. - * - * @author Tony Chemit - chemit@codelutin.com - * @see SimpleBeanValidatorMessage - * @since 1.3 - */ -public class SwingValidatorMessage extends SimpleBeanValidatorMessage<SwingValidatorMessage> { - - private static final long serialVersionUID = 1L; - - /** the optional field's editor */ - protected JComponent editor; - - public SwingValidatorMessage(SwingValidator<?> validator, - String fieldName, - String message, - NuitonValidatorScope scope, - JComponent editor) { - super(validator, fieldName, message, scope); - this.editor = editor; - } - - public JComponent getEditor() { - return editor; - } - - @Override - public String toString() { - String s = scope + " - " + - (field == null ? message : field + " - " + message); - if (editor != null) { - s = editor.getName() + " : " + s; - } - return s; - } -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListModel.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListModel.java deleted file mode 100644 index 8d6e567..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListModel.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.simple.SimpleBeanValidatorEvent; -import org.nuiton.validator.bean.simple.SimpleBeanValidatorListener; - -import javax.swing.AbstractListModel; -import javax.swing.JComponent; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * The model of the list of validation's messages - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class SwingValidatorMessageListModel - extends AbstractListModel - implements SimpleBeanValidatorListener { - - private static final long serialVersionUID = 1L; - - /** Logger */ - private static Log log = LogFactory.getLog(SwingValidatorMessageListModel.class); - - /** list of registred validators */ - protected transient List<SwingValidator<?>> validators; - - /** list of messages actual displayed */ - protected List<SwingValidatorMessage> data; - - public SwingValidatorMessageListModel() { - validators = new ArrayList<SwingValidator<?>>(); - data = new ArrayList<SwingValidatorMessage>(); - } - - public boolean isEmpty() { - return getSize() == 0; - } - - public void registerValidator(SwingValidator<?> validator) { - if (validators.contains(validator)) { - throw new IllegalArgumentException( - "the validator " + validator + " is already registred in " - + this); - } - validators.add(validator); - validator.addSimpleBeanValidatorListener(this); - } - - public void clear() { - int i = data.size(); - if (i > 0) { - data.clear(); - fireIntervalRemoved(this, 0, i - 1); - } - } - - @Override - public int getSize() { - return data.size(); - } - - @Override - public Object getElementAt(int index) { - ensureRowIndex(index); - return data.get(index); - } - - @Override - public void onFieldChanged(SimpleBeanValidatorEvent event) { - String[] toDelete = event.getMessagesToDelete(); - String[] toAdd = event.getMessagesToAdd(); - String field = event.getField(); - NuitonValidatorScope scope = event.getScope(); - boolean mustAdd = toAdd != null && toAdd.length > 0; - boolean mustDel = toDelete != null && toDelete.length > 0; - - if (log.isTraceEnabled()) { - log.trace("----------------------------------------------------------"); - log.trace(field + " - (" + getSize() + ") toAdd " + mustAdd); - log.trace(field + " - (" + getSize() + ") toDelete " + mustDel); - } - - SwingValidator<?> validator = (SwingValidator<?>) event.getSource(); - - if (mustDel) { - - // removes datas and notify if no messages to add - removeMessages(validator, field, scope, !mustAdd, toDelete); - } - - if (mustAdd) { - - // add new messages, sort datas and notify - addMessages(validator, field, scope, true, toAdd); - } - } - - protected void ensureRowIndex(int index) throws ArrayIndexOutOfBoundsException { - if (index < -1 || index >= getSize()) { - throw new ArrayIndexOutOfBoundsException( - "the rowIndex was " + index + ", but should be int [0," + - (getSize() - 1) + "]"); - } - } - - protected void addMessages(SwingValidator<?> validator, - String field, - NuitonValidatorScope scope, - boolean sort, - String... messages) { - - JComponent editor = validator.getFieldRepresentation(field); - // add new errors - for (String error : messages) { - SwingValidatorMessage row = new SwingValidatorMessage( - validator, - field, - error, - scope, - editor - ); - data.add(row); - if (!sort) { - fireIntervalAdded(this, data.size() - 1, data.size() - 1); - } - } - - if (sort) { - - // resort datas - Collections.sort(data); - - // notify - fireContentsChanged(this, 0, getSize() - 1); - } - } - - protected void removeMessages(SwingValidator<?> validator, - String field, - NuitonValidatorScope scope, - boolean notify, - String... messages) { - - List<String> messagesToDel = - new ArrayList<String>(Arrays.asList(messages)); - - // do it in reverse mode (only one pass in that way since index - // will stay coherent while removing them) - - for (int i = getSize() - 1; i > -1; i--) { - SwingValidatorMessage error = data.get(i); - if (error.getValidator().equals(validator) && - error.getScope() == scope && - error.getField().equals(field) && - messagesToDel.contains(error.getMessage())) { - // remove the message - data.remove(i); - if (notify) { - fireIntervalRemoved(this, i, i); - } - } - } - } -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListMouseListener.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListMouseListener.java deleted file mode 100644 index c44160d..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListMouseListener.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.JComponent; -import javax.swing.JList; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -/** - * A mouse listener to put on a {@link JList} with a {@link - * SwingValidatorMessageListModel} as a model. - * - * When a double click occurs, find the selected error in model and then focus - * to the associated component of error. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class SwingValidatorMessageListMouseListener extends MouseAdapter { - - /** Logger */ - static private Log log = - LogFactory.getLog(SwingValidatorMessageListMouseListener.class); - - @Override - public void mouseClicked(MouseEvent e) { - super.mouseClicked(e); - if (e.getClickCount() == 2) { - - SwingValidatorMessage entry = getSelectedMessage(e); - if (entry == null) { - // no entry found - return; - } - JComponent component = entry.getEditor(); - if (component != null) { - component.requestFocus(); - } - } - } - - protected SwingValidatorMessage getSelectedMessage(MouseEvent e) { - JList list = (JList) e.getSource(); - if (!(list.getModel() instanceof SwingValidatorMessageListModel)) { - if (log.isWarnEnabled()) { - log.warn("model must be a " + - SwingValidatorMessageListModel.class + ", but was " + - list.getModel()); - } - return null; - } - - SwingValidatorMessageListModel model = - (SwingValidatorMessageListModel) list.getModel(); - int index = list.getSelectionModel().getMinSelectionIndex(); - if (index == -1) { - // nothing is selected - return null; - } - SwingValidatorMessage entry = - (SwingValidatorMessage) model.getElementAt(index); - if (log.isDebugEnabled()) { - log.debug("selected index: " + index + " : error: " + entry); - } - return entry; - } - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListRenderer.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListRenderer.java deleted file mode 100644 index f419a81..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListRenderer.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing; - -import org.nuiton.validator.NuitonValidatorScope; - -import javax.swing.DefaultListCellRenderer; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JList; -import java.awt.Component; - -import static org.nuiton.i18n.I18n.t; - -/** - * A simple render of a table of validator's messages, says a table that use a - * {@link SwingValidatorMessageTableModel} model. - * - * @author Tony Chemit - chemit@codelutin.com - * @see SwingValidatorMessageTableModel - * @since 1.3 - */ -public class SwingValidatorMessageListRenderer extends DefaultListCellRenderer { - - private static final long serialVersionUID = 1L; - - protected String format = "%1$-20s - %2$s"; - - protected String formatTip = "%1$-20s - %2$-20s : %3$s"; - - public SwingValidatorMessageListRenderer() { - } - - public SwingValidatorMessageListRenderer(String format) { - this.format = format; - } - - public String getFormat() { - return format; - } - - public void setFormat(String format) { - this.format = format; - } - - @Override - public Component getListCellRendererComponent(JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) { - - JLabel rendererComponent = (JLabel) - super.getListCellRendererComponent( - list, - value, - index, - isSelected, - cellHasFocus - ); - - SwingValidatorMessage model = (SwingValidatorMessage) value; - - // scope - ImageIcon icon = SwingValidatorUtil.getIcon(model.getScope()); - - // field name - String fieldName = getFieldName( - list, - model.getField(), - index - ); - - // message - String message = getMessage(model); - - // text to display - String text = String.format(format, fieldName, message); - - String label = t(model.getScope().getLabel()); - String tmp = t("validator.scope.tip", label); - String tmp2 = t("validator.field.tip", fieldName); - - String tooltTipText = String.format(formatTip, tmp, tmp2, message); - - - rendererComponent.setText(text); - rendererComponent.setToolTipText(tooltTipText); - rendererComponent.setIcon(icon); - - return rendererComponent; - } - - public ImageIcon getIcon(NuitonValidatorScope scope) { - return SwingValidatorUtil.getIcon(scope); - } - - public String getMessage(SwingValidatorMessage model) { - return SwingValidatorUtil.getMessage(model); - } - - public String getFieldName(JList list, String value, int row) { - SwingValidatorMessageListModel tableModel = - (SwingValidatorMessageListModel) list.getModel(); - SwingValidatorMessage model = - (SwingValidatorMessage) tableModel.getElementAt(row); - return SwingValidatorUtil.getFieldName(model, value); - } -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableModel.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableModel.java deleted file mode 100644 index 2da5995..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableModel.java +++ /dev/null @@ -1,360 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing; - -import jaxx.runtime.SwingUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.simple.SimpleBeanValidatorEvent; -import org.nuiton.validator.bean.simple.SimpleBeanValidatorListener; - -import javax.swing.JComponent; -import javax.swing.table.AbstractTableModel; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * The model of the table of errors. - * - * The model listens validators messages and update his internal model from it. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 1.3 - */ -public class SwingValidatorMessageTableModel - extends AbstractTableModel - implements SimpleBeanValidatorListener { - - private static final long serialVersionUID = 1L; - - /** Logger */ - private static Log log = - LogFactory.getLog(SwingValidatorMessageTableModel.class); - - public static final String[] columnNames = - {"validator.scope", "validator.field", "validator.message"}; - - public static final Class<?>[] columnClasses = - {NuitonValidatorScope.class, String.class, String.class}; - - /** list of registred validators */ - protected transient List<SwingValidator<?>> validators; - - /** list of messages actual displayed */ - protected List<SwingValidatorMessage> data; - - public SwingValidatorMessageTableModel() { - validators = new ArrayList<SwingValidator<?>>(); - data = new ArrayList<SwingValidatorMessage>(); - } - - /** - * Register a validator for this model. - * - * - * Note: a validator can not be register twice in the same model. - * - * @param validator the validator to register - */ - public void registerValidator(SwingValidator<?> validator) { - if (validators.contains(validator)) { - throw new IllegalArgumentException( - "the validator " + validator + " is already registred in " - + this); - } - validators.add(validator); - validator.addSimpleBeanValidatorListener(this); - } - - public void addMessages(SwingValidator<?> validator, - String fieldName, - NuitonValidatorScope scope, - String... messages) { - addMessages(validator, fieldName, scope, true, messages); - } - - public void addMessages(JComponent editor, - String fieldName, - NuitonValidatorScope scope, - String... messages) { - addMessages(editor, fieldName, scope, true, messages); - } - - public void removeMessages(JComponent editor, NuitonValidatorScope scope) { - - if (editor == null) { - // no editor, so nothing to do - return; - } - // do it in reverse mode (only one pass in that way since index - // will stay coherent while removing them) - - for (int i = getRowCount() - 1; i > -1; i--) { - SwingValidatorMessage error = data.get(i); - if (editor.equals(error.getEditor()) && - (scope == null || error.getScope() == scope)) { - // remove the message - data.remove(i); - fireTableRowsDeleted(i, i); - } - } - } - - public void removeMessages(SwingValidator<?> validator, - String fieldName, - NuitonValidatorScope scope, - String... messages) { - removeMessages(validator, fieldName, scope, true, messages); - } - - public void removeMessages(JComponent editor, - String fieldName, - NuitonValidatorScope scope) { - removeMessages(editor, fieldName, scope, true); - } - - public void clear() { - int i = data.size(); - if (i > 0) { - data.clear(); - fireTableRowsDeleted(0, i - 1); - } - } - - public void clearValidators() { - for (SwingValidator<?> v : validators) { - v.removeSimpleBeanValidatorListener(this); - } - validators.clear(); - } - - /** - * Obtain the message for a given row. - * - * @param rowIndex the row index - * @return the message for the given row index - */ - public SwingValidatorMessage getRow(int rowIndex) { - SwingUtil.ensureRowIndex(this, rowIndex); - return data.get(rowIndex); - } - - @Override - public boolean isCellEditable(int row, int column) { - // cells are never editable in this model - return false; - } - - @Override - public Class<?> getColumnClass(int columnIndex) { - SwingUtil.ensureColumnIndex(this, columnIndex); - return columnClasses[columnIndex]; - } - - @Override - public String getColumnName(int column) { - SwingUtil.ensureColumnIndex(this, column); - return columnNames[column]; - } - - @Override - public void onFieldChanged(SimpleBeanValidatorEvent event) { - String[] toDelete = event.getMessagesToDelete(); - String[] toAdd = event.getMessagesToAdd(); - String field = event.getField(); - NuitonValidatorScope scope = event.getScope(); - boolean mustAdd = toAdd != null && toAdd.length > 0; - boolean mustDel = toDelete != null && toDelete.length > 0; - - if (log.isTraceEnabled()) { - log.trace("----------------------------------------------------------"); - log.trace(field + " - (" + getRowCount() + ") toAdd " + mustAdd); - log.trace(field + " - (" + getRowCount() + ") toDelete " + mustDel); - } - - SwingValidator<?> validator = (SwingValidator<?>) event.getSource(); - - if (mustDel) { - - // removes datas and notify if no messages to add - removeMessages(validator, field, scope, !mustAdd, toDelete); - } - - if (mustAdd) { - - // add new messages, sort datas and notify - addMessages(validator, field, scope, true, toAdd); - } - } - - @Override - public int getRowCount() { - return data.size(); - } - - @Override - public int getColumnCount() { - return columnNames.length; - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - SwingUtil.ensureColumnIndex(this, columnIndex); - SwingUtil.ensureRowIndex(this, rowIndex); - - SwingValidatorMessage row = data.get(rowIndex); - if (columnIndex == 0) { - // the icon - return row.getScope(); - } - if (columnIndex == 1) { - // the field - return row.getField(); - } - if (columnIndex == 2) { - // the message - return row.getMessage(); - } - - // should never come here - return null; - } - - protected void addMessages(SwingValidator<?> validator, - String fieldName, - NuitonValidatorScope scope, - boolean sort, - String... messages) { - - JComponent editor = validator == null ? - null : - validator.getFieldRepresentation(fieldName); - // add new errors - for (String error : messages) { - SwingValidatorMessage row = - new SwingValidatorMessage( - validator, - fieldName, - error, - scope, - editor - ); - data.add(row); - if (!sort) { - fireTableRowsInserted(data.size() - 1, data.size() - 1); - } - } - - if (sort) { - - // resort datas - Collections.sort(data); - - // notify - fireTableDataChanged(); - } - } - - protected void addMessages(JComponent editor, - String fieldName, - NuitonValidatorScope scope, - boolean sort, - String... messages) { - - // add new errors - for (String error : messages) { - SwingValidatorMessage row = - new SwingValidatorMessage( - null, - fieldName, - error, - scope, - editor - ); - data.add(row); - if (!sort) { - fireTableRowsInserted(data.size() - 1, data.size() - 1); - } - } - - if (sort) { - - // resort datas - Collections.sort(data); - - // notify - fireTableDataChanged(); - } - } - - protected void removeMessages(SwingValidator<?> validator, - String fieldName, - NuitonValidatorScope scope, - boolean notify, - String... messages) { - - List<String> messagesToDel = - new ArrayList<String>(Arrays.asList(messages)); - - // do it in reverse mode (only one pass in that way since index - // will stay coherent while removing them) - - for (int i = getRowCount() - 1; i > -1; i--) { - SwingValidatorMessage error = data.get(i); - if (validator.equals(error.getValidator()) && - error.getScope() == scope && - error.getField().equals(fieldName) && - messagesToDel.contains(error.getMessage())) { - // remove the message - data.remove(i); - if (notify) { - fireTableRowsDeleted(i, i); - } - } - } - } - - protected void removeMessages(JComponent editor, - String fieldName, - NuitonValidatorScope scope, - boolean notify) { - - // do it in reverse mode (only one pass in that way since index - // will stay coherent while removing them) - - for (int i = getRowCount() - 1; i > -1; i--) { - SwingValidatorMessage error = data.get(i); - if (editor.equals(error.getEditor()) && - (scope == null || error.getScope() == scope) && - error.getField().equals(fieldName)) { - // remove the message - data.remove(i); - if (notify) { - fireTableRowsDeleted(i, i); - } - } - } - } -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableMouseListener.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableMouseListener.java deleted file mode 100644 index fb705bf..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableMouseListener.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.JComponent; -import javax.swing.JList; -import javax.swing.JTable; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; - -/** - * A mouse listener to put on a {@link JList} with a {@link - * SwingValidatorMessageTableModel} as a model. - * - * When a double click occurs, find the selected error in model and then focus - * to the associated component of error. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class SwingValidatorMessageTableMouseListener extends MouseAdapter { - - /** Logger */ - private static Log log = - LogFactory.getLog(SwingValidatorMessageTableMouseListener.class); - - public static final String HIGHLIGHT_ERROR_PROPERTY = "highlightError"; - - /** delgate property change support */ - protected PropertyChangeSupport pcs; - - public SwingValidatorMessageTableMouseListener() { - pcs = new PropertyChangeSupport(this); - } - - @Override - public void mouseClicked(MouseEvent e) { - super.mouseClicked(e); - if (e.getClickCount() == 2) { - - SwingValidatorMessage entry = getSelectedMessage(e); - if (entry == null) { - // no entry found - return; - } - JComponent component = entry.getEditor(); - if (component != null) { - pcs.firePropertyChange(HIGHLIGHT_ERROR_PROPERTY, null, entry); - if (component.isVisible()) { - component.requestFocus(); - } - } - } - } - - - protected SwingValidatorMessage getSelectedMessage(MouseEvent e) { - JTable table = (JTable) e.getSource(); - if (!(table.getModel() instanceof SwingValidatorMessageTableModel)) { - if (log.isWarnEnabled()) { - log.warn("model must be a " + - SwingValidatorMessageTableModel.class + - ", but was " + table.getModel()); - } - return null; - } - - SwingValidatorMessageTableModel model = - (SwingValidatorMessageTableModel) table.getModel(); - int index = table.getSelectionModel().getMinSelectionIndex(); - if (index == -1) { - // nothing is selected - return null; - } - if (table.getRowSorter() != null) { - index = table.getRowSorter().convertRowIndexToModel(index); - } - SwingValidatorMessage entry = model.getRow(index); - if (log.isDebugEnabled()) { - log.debug("selected index: " + index + " : error: " + entry); - } - return entry; - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - pcs.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - pcs.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.removePropertyChangeListener(propertyName, listener); - } - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableRenderer.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableRenderer.java deleted file mode 100644 index 91cbfba..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableRenderer.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing; - -import org.nuiton.validator.NuitonValidatorScope; - -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.table.DefaultTableCellRenderer; -import java.awt.Component; - -import static org.nuiton.i18n.I18n.t; - -/** - * A simple render of a table of validator's messages, says a table that use - * a {@link SwingValidatorMessageTableModel} model. - * - * @author Tony Chemit - chemit@codelutin.com - * @see SwingValidatorMessageTableModel - * @since 1.3 - */ -public class SwingValidatorMessageTableRenderer extends DefaultTableCellRenderer { - - private static final long serialVersionUID = 1L; - - @Override - public Component getTableCellRendererComponent(JTable table, - Object value, - boolean isSelected, - boolean hasFocus, - int row, - int column) { - JLabel rendererComponent = (JLabel) - super.getTableCellRendererComponent( - table, - value, - isSelected, - hasFocus, - row, - column - ); - - ImageIcon icon = null; - String text = null; - String toolTipText = null; - -// column = table.convertColumnIndexToModel(column); -// if (table.getRowSorter() != null) { -// row = table.getRowSorter().convertRowIndexToModel(row); -// } - - switch (column) { - case 0: - // scope - NuitonValidatorScope scope = (NuitonValidatorScope) value; - icon = SwingValidatorUtil.getIcon(scope); - String label = t(scope.getLabel()); - toolTipText = t("validator.scope.tip", label); - break; - - case 1: - // field name - text = getFieldName(table, (String) value, row); - toolTipText = t("validator.field.tip", text); - break; - - case 2: - // message - text = getMessage(table, (String) value, row); - toolTipText = t("validator.message.tip", text); - break; - } - - rendererComponent.setText(text); - rendererComponent.setToolTipText(toolTipText); - rendererComponent.setIcon(icon); - return rendererComponent; - } - - public ImageIcon getIcon(NuitonValidatorScope scope) { - return SwingValidatorUtil.getIcon(scope); - } - - public String getMessage(JTable table, String value, int row) { - SwingValidatorMessageTableModel tableModel = - (SwingValidatorMessageTableModel) table.getModel(); - SwingValidatorMessage model = tableModel.getRow(row); - return SwingValidatorUtil.getMessage(model); - } - - public String getFieldName(JTable table, String value, int row) { - SwingValidatorMessageTableModel tableModel = - (SwingValidatorMessageTableModel) table.getModel(); - SwingValidatorMessage model = tableModel.getRow(row); - return SwingValidatorUtil.getFieldName(model, value); - } -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageWidget.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageWidget.java deleted file mode 100644 index 44e98a0..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageWidget.java +++ /dev/null @@ -1,279 +0,0 @@ - -package jaxx.runtime.validator.swing; - -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.SwingUtil; -import jaxx.runtime.swing.ComponentMover; -import jaxx.runtime.swing.ComponentResizer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.JXTitledPanel; -import org.nuiton.validator.NuitonValidatorScope; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JRootPane; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.JToggleButton; -import javax.swing.JToolBar; -import javax.swing.KeyStroke; -import javax.swing.ListSelectionModel; -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; -import java.awt.Component; -import java.awt.Point; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.HierarchyBoundsAdapter; -import java.awt.event.HierarchyEvent; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -import static org.nuiton.i18n.I18n.t; -import static org.nuiton.i18n.I18n.n; - -/** - * Button which opens a popup containing a table with the errors found - * by registered validators. - * - * @author Kevin Morin - morin@codelutin.com - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.10 - */ -public class SwingValidatorMessageWidget extends JToggleButton { - - private static final Log log = - LogFactory.getLog(SwingValidatorMessageWidget.class); - - private static final long serialVersionUID = 1L; - - public static final String CLOSE_DIALOG_ACTION = "closeDialog"; - - protected SwingValidatorMessageTableModel errorTableModel = new SwingValidatorMessageTableModel(); - - protected JDialog popup = new JDialog(); - - protected JTable errorTable = new JTable(); - - protected Point popupPosition = null; - - public SwingValidatorMessageWidget() { - super(SwingUtil.createActionIcon("alert-none")); - setToolTipText(t("validator.messageWidget.alert.none")); - - errorTableModel.addTableModelListener(new TableModelListener() { - - public void tableChanged(TableModelEvent e) { - int alerts = errorTableModel.getRowCount(); - String label; - switch (alerts) { - case 0: - label = n("validator.messageWidget.alert.none"); - break; - case 1: - label = n("validator.messageWidget.alert.one"); - break; - default: - label = n("validator.messageWidget.alert.several"); - } - - NuitonValidatorScope maxScope; - String icon; - if (alerts == 0) { - icon = "alert-none"; - - } else { - maxScope = NuitonValidatorScope.INFO; - for (int i = 0; i < alerts; i++) { - NuitonValidatorScope scope = errorTableModel.getRow(i).getScope(); - int diff = scope.compareTo(maxScope); - if (diff < 0) { - maxScope = scope; - } - } - switch (maxScope) { - case INFO: - icon = "alert-info"; - break; - case WARNING: - icon = "alert-warning"; - break; - default: - icon = "alert-error"; - - } - } - - setToolTipText(t(label, alerts)); - setIcon(SwingUtil.createActionIcon(icon)); - } - }); - - errorTable.setModel(errorTableModel); - errorTable.setRowSelectionAllowed(true); - errorTable.setAutoCreateRowSorter(true); - errorTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); - errorTable.setCellSelectionEnabled(false); - errorTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - errorTable.setFillsViewportHeight(true); - - SwingValidatorUtil.installUI(errorTable, - new SwingValidatorMessageTableRenderer()); - - JScrollPane scrollPanel = new JScrollPane(errorTable); - scrollPanel.setColumnHeaderView(errorTable.getTableHeader()); - - JXTitledPanel titledPanel = new JXTitledPanel(t("validator.messageWidget.title"), scrollPanel); - popup.add(titledPanel); - popup.setTitle(t("validator.messageWidget.title")); - popup.setSize(800, 300); - popup.setAlwaysOnTop(true); - popup.setUndecorated(true); - - ComponentResizer cr = new ComponentResizer(); - cr.registerComponent(popup); - ComponentMover cm = new ComponentMover(); - cm.setDragInsets(cr.getDragInsets()); - cm.registerComponent(popup); - - popup.addWindowListener(new WindowAdapter() { - - @Override - public void windowClosing(WindowEvent e) { - setSelected(false); - } - - }); - - popup.addComponentListener(new ComponentAdapter() { - - @Override - public void componentMoved(ComponentEvent e) { - Component component = e.getComponent(); - if (component.isShowing()) { - popupPosition = component.getLocationOnScreen(); - } - } - - }); - - addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - if (isSelected()) { - popup.setVisible(true); - } else { - popup.dispose(); - } - } - }); - - addHierarchyBoundsListener(new HierarchyBoundsAdapter() { - - @Override - public void ancestorMoved(HierarchyEvent e) { - if (popupPosition == null && isShowing()) { - Point point = new Point(getLocationOnScreen()); - point.translate(-popup.getWidth() + getWidth(), -popup.getHeight()); - popup.setLocation(point); - } - } - }); - - // add a auto-close action - JRootPane rootPane = popup.getRootPane(); - - KeyStroke shortcutClosePopup = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); - - rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( - shortcutClosePopup, CLOSE_DIALOG_ACTION); - - Action closeAction = new AbstractAction() { - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent e) { - popup.dispose(); - setSelected(false); - } - }; - - ImageIcon actionIcon = SwingUtil.createActionIcon("close-dialog"); - closeAction.putValue(Action.SMALL_ICON, actionIcon); - closeAction.putValue(Action.LARGE_ICON_KEY, actionIcon); - closeAction.putValue(Action.ACTION_COMMAND_KEY, "close"); - closeAction.putValue(Action.NAME, "close"); - closeAction.putValue(Action.SHORT_DESCRIPTION, t("validator.messageWidget.closeDialog.tip")); - - rootPane.getActionMap().put(CLOSE_DIALOG_ACTION, closeAction); - - JButton closeButton = new JButton(closeAction); - closeButton.setText(null); - closeButton.setFocusPainted(false); - closeButton.setRequestFocusEnabled(false); - closeButton.setFocusable(false); - - JToolBar jToolBar = new JToolBar(); - jToolBar.setOpaque(false); - jToolBar.add(closeAction); - jToolBar.setBorderPainted(false); - jToolBar.setFloatable(false); - titledPanel.setRightDecoration(jToolBar); - - } - - public void addTableModelListener(TableModelListener listener) { - errorTableModel.addTableModelListener(listener); - } - - public void removeTableModelListener(TableModelListener listener) { - errorTableModel.removeTableModelListener(listener); - } - - /** - * Registers a validator. - * - * @param validator - */ - public void registerValidator(SwingValidator validator) { - errorTableModel.registerValidator(validator); - validator.reloadBean(); - } - - /** Clears all the validators. */ - public void clearValidators() { - errorTableModel.clearValidators(); - errorTableModel.clear(); - } - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorUtil.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorUtil.java deleted file mode 100644 index 8939f71..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorUtil.java +++ /dev/null @@ -1,762 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.JAXXValidator; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.validator.swing.meta.Validator; -import jaxx.runtime.validator.swing.meta.ValidatorField; -import jaxx.runtime.validator.swing.unified.UnifiedValidatorMessage; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.JXTable; -import org.jdesktop.swingx.decorator.ColorHighlighter; -import org.nuiton.util.ReflectUtil; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.list.BeanListValidator; -import org.nuiton.validator.bean.simple.SimpleBeanValidatorMessage; -import org.nuiton.validator.bean.simple.SimpleBeanValidators; - -import javax.swing.ImageIcon; -import javax.swing.JComponent; -import javax.swing.JList; -import javax.swing.JTable; -import javax.swing.RowSorter; -import javax.swing.SortOrder; -import java.awt.Color; -import java.awt.event.MouseListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; - -import static org.nuiton.i18n.I18n.n; - -/** - * The helper class for swing validation module. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class SwingValidatorUtil extends SimpleBeanValidators { - - /** Logger */ - static private final Log log = LogFactory.getLog(SwingValidatorUtil.class); - - protected static EnumMap<NuitonValidatorScope, ImageIcon> icons; - - protected static EnumMap<NuitonValidatorScope, Color> colors; - - public static EnumMap<NuitonValidatorScope, ImageIcon> getIcons() { - if (icons == null) { - icons = new EnumMap<NuitonValidatorScope, ImageIcon>(NuitonValidatorScope.class); - icons.put(NuitonValidatorScope.FATAL, SwingUtil.createImageIcon("fatal.png")); - icons.put(NuitonValidatorScope.ERROR, SwingUtil.createImageIcon("error.png")); - icons.put(NuitonValidatorScope.WARNING, SwingUtil.createImageIcon("warning.png")); - icons.put(NuitonValidatorScope.INFO, SwingUtil.createImageIcon("info.png")); - } - return icons; - } - - public static EnumMap<NuitonValidatorScope, Color> getColors() { - if (colors == null) { - colors = new EnumMap<NuitonValidatorScope, Color>(NuitonValidatorScope.class); - colors.put(NuitonValidatorScope.FATAL, Color.MAGENTA); - colors.put(NuitonValidatorScope.ERROR, Color.RED); - colors.put(NuitonValidatorScope.WARNING, Color.YELLOW); - colors.put(NuitonValidatorScope.INFO, Color.GREEN); - } - return colors; - } - - public static Color getColor(NuitonValidatorScope scope) { - return scope == null ? null : getColors().get(scope); - } - - public static ImageIcon getIcon(NuitonValidatorScope scope) { - return scope == null ? null : getIcons().get(scope); - } - - public static ImageIcon getFatalIcon() { - return getIcons().get(NuitonValidatorScope.FATAL); - } - - public static ImageIcon getErrorIcon() { - return getIcons().get(NuitonValidatorScope.ERROR); - } - - public static ImageIcon getWarningIcon() { - return getIcons().get(NuitonValidatorScope.WARNING); - } - - public static ImageIcon getInfoIcon() { - return getIcons().get(NuitonValidatorScope.INFO); - } - - protected SwingValidatorUtil() { - // no instance - } - - public static <O> SwingValidator<O> newValidator(Class<O> type, - String context) { - -// if (BeanValidatorFactory.isDefaultCreator()) { -// -// // set the swing bean validator creator -// BeanValidatorFactory.setCreator(new DefaultSwingValidatorCreator()); -// } - return SwingValidator.newValidator(type, context); - } - - /** - * To install all the stuff for validation on a {@link JAXXValidator} ui. - * - * This method is called after validators has beeen detected in the ui (via - * the method {@link #detectValidators(JAXXValidator)}).. - * - * It will first find and register all validator field via the method - * {@link JAXXValidator#registerValidatorFields()}, then for each - * validators it will install ui for it (says connect validator to ui via layers) - * and will reload attached bean to make visible bean validation state on ui. - * - * This method is always inovked by a generated jaxx-validator file at the - * end of the {@code $completeSetup} method. - * - * @param ui the validator ui to init. - */ - public static void installUI(JAXXValidator ui) { - - // first install fields with validation - ui.registerValidatorFields(); - -// detectValidatorFields(ui); - - // for each validator install uis + reload bean - - List<String> validatorIds = ui.getValidatorIds(); - for (String validatorId : validatorIds) { - SwingValidator<?> validator = ui.getValidator(validatorId); - - // install uis - validator.installUIs(); - - // reload attached bean (to see validation on uis) - validator.reloadBean(); - } - } - - /** - * Given a {@link JAXXValidator} ui, detects on it all the validators it - * contains. - * - * A validator is detected from the annotation {@link Validator} placed on - * his field. - * - * This method is always inovked by a generated jaxx-validator file at the - * end of the {@code $completeSetup} method. - * - * @param ui the ui where to seek for validators. - * @return the list of ids of validators found on the given ui - */ - public static List<String> detectValidators(JAXXValidator ui) { - List<String> validatorIds = new ArrayList<String>(); - Map<Field, Validator> validators = ReflectUtil.getFieldAnnotation( - ui.getClass(), - Validator.class, - true - ); - - for (Map.Entry<Field, Validator> entry : validators.entrySet()) { - Field field = entry.getKey(); - Validator annotation = entry.getValue(); - String validatorId = annotation.validatorId(); - validatorIds.add(validatorId); - if (log.isInfoEnabled()) { - log.info("Detect validator [" + annotation.validatorId() + - "] on field " + field.getName()); - } - } - return Collections.unmodifiableList(validatorIds); - } - - /** - * Detects on a {@link JAXXValidator} ui all the validator fields it - * contains. - * - * A validator field is detected via the annotation placed on his field or - * his getter (in cas of inheritance). - * - * Each field found will be registred to his corresponding validator via - * the method {@link SwingValidator#setFieldRepresentation(String, JComponent)}. - * - * By default, this method is invoked in the generated method - * {@link JAXXValidator#registerValidatorFields()} by a generated - * jaxx-validator file. - * - * @param ui the ui to seek - */ - public static void detectValidatorFields(JAXXValidator ui) { - - Multimap<JComponent, ValidatorField> editors = getValidatorEditors(ui); - - try { - - for (String validatorId : ui.getValidatorIds()) { - SwingValidator<?> validator = ui.getValidator(validatorId); - - for (Map.Entry<JComponent, ValidatorField> entry : - editors.entries()) { - ValidatorField fieldAnnotation = entry.getValue(); - JComponent editor = entry.getKey(); - if (!validatorId.equals(fieldAnnotation.validatorId())) { - - // not good validator, skip this field - continue; - } - String[] propertyNames = fieldAnnotation.propertyName(); - for (String propertyName : propertyNames) { - if (log.isInfoEnabled()) { - log.info("Detects for validator [" + validatorId + - "] property " + propertyName + - " for editor " + fieldAnnotation.editorName()); - } - validator.setFieldRepresentation(propertyName, editor); - } - } - } - - } finally { - - editors.clear(); - } - } - - /** - * Prepare the ui where to display the validators messages. - * - * @param errorTable the table where to display validators messages - * @param render renderer to use - */ - public static void installUI(JTable errorTable, - SwingValidatorMessageTableRenderer render) { - errorTable.setDefaultRenderer(Object.class, render); - errorTable.getRowSorter().setSortKeys( - Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); - SwingUtil.setI18nTableHeaderRenderer( - errorTable, - n("validator.scope.header"), - n("validator.scope.header.tip"), - n("validator.field.header"), - n("validator.field.header.tip"), - n("validator.message.header"), - n("validator.message.header.tip")); - // register a single 'goto widget error' mouse listener on errorTable - registerErrorTableMouseListener(errorTable); - SwingUtil.fixTableColumnWidth(errorTable, 0, 25); - } - - /** - * Prepare the ui where to display the validators messages. - * - * @param errorTable the table where to display simpleBean validators messages - * @param render renderer to use - * @since 2.6.23 - */ - public static void installUI(JTable errorTable, - SimpleBeanValidatorMessageTableRenderer render) { - errorTable.setDefaultRenderer(Object.class, render); - errorTable.getRowSorter().setSortKeys( - Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); - SwingUtil.setI18nTableHeaderRenderer( - errorTable, - n("validator.scope.header"), - n("validator.scope.header.tip"), - n("validator.field.header"), - n("validator.field.header.tip"), - n("validator.message.header"), - n("validator.message.header.tip")); - SwingUtil.fixTableColumnWidth(errorTable, 0, 25); - } - - /** - * Prepare the ui where to display the validators messages. - * - * @param errorTable the table where to display validators messages - * @param render renderer to use - * @since 2.5.3 - */ - public static void installUI(JTable errorTable, - SwingListValidatorMessageTableRenderer render) { - - errorTable.setDefaultRenderer(Object.class, render); - errorTable.getRowSorter().setSortKeys( - Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); - SwingUtil.setI18nTableHeaderRenderer( - errorTable, - n("validator.scope.header"), - n("validator.scope.header.tip"), - n("validator.bean.header"), - n("validator.bean.header.tip"), - n("validator.field.header"), - n("validator.field.header.tip"), - n("validator.message.header"), - n("validator.message.header.tip")); - SwingUtil.fixTableColumnWidth(errorTable, 0, 25); - - } - - /** - * Prepare the ui where to display the validators messages. - * - * @param errorTableModel - * @param errorTable the table where to display validators messages - * @since 2.5.3 - */ - public static <O> void registerListValidator(BeanListValidator<O> validator, - SwingListValidatorMessageTableModel errorTableModel, - JTable dataTable, - JTable errorTable, - SwingListValidatorDataLocator<O> dataLocator) { - - // register the validator to the error table model - errorTableModel.registerValidator(validator); - - - // add click listener to go to cell - errorTable.addMouseListener(new SwingListValidatorMessageTableMouseListener( - dataTable, - dataLocator - )); - - // listen on editor model to add / remove bean into validator - dataTable.getModel().addTableModelListener( - new SwingListValidatorTableEditorModelListener<O>(validator, dataLocator)); - } - - /** - * Add hightlighters on the editor of beans. - * - * @param validator the validator where to find bean states - * @param editor the editor of beans - * @param dataLocator the data locator - * @param scopes scopes to hightlight - * @param <O> type of bean to validate - * @since 2.5.3 - */ - public static <O> void addHightLighterOnEditor(BeanListValidator<O> validator, - JXTable editor, - SwingListValidatorDataLocator<O> dataLocator, - NuitonValidatorScope... scopes) { - - for (NuitonValidatorScope scope : scopes) { - - SwingListValidatorHighlightPredicate<O> predicate = SwingListValidatorHighlightPredicate.newPredicate( - scope, - validator, dataLocator - ); - - ColorHighlighter highlighter = new ColorHighlighter(predicate); - highlighter.setBackground(SwingValidatorUtil.getColor(scope)); - editor.addHighlighter(highlighter); - } - } - - /** - * Register for a given validator list ui a validator mouse listener. - * - * Note: there is only one listener registred for a given list model, so - * invoking this method tiwce or more will have no effect. - * - * @param list the validation ui list - * @return the listener instanciate or found - * @see SwingValidatorMessageListMouseListener - */ - public static SwingValidatorMessageListMouseListener registerErrorListMouseListener(JList list) { - SwingValidatorMessageListMouseListener listener = - getErrorListMouseListener(list); - - if (listener != null) { - return listener; - } - listener = new SwingValidatorMessageListMouseListener(); - if (log.isDebugEnabled()) { - log.debug(listener.toString()); - } - list.addMouseListener(listener); - return listener; - } - - /** - * Register for a given validator table ui a validator mouse listener - * - * Note: there is onlt one listener registred for a givne table model, so - * invokin this method twice or more will have no effect. - * - * @param table the validator table ui - * @return the listener instanciate or found - * @see SwingValidatorMessageTableMouseListener - */ - public static SwingValidatorMessageTableMouseListener registerErrorTableMouseListener(JTable table) { - SwingValidatorMessageTableMouseListener listener = - getErrorTableMouseListener(table); - - if (listener != null) { - return listener; - } - listener = new SwingValidatorMessageTableMouseListener(); - if (log.isDebugEnabled()) { - log.debug(listener.toString()); - } - table.addMouseListener(listener); - return listener; - } - - /** - * @param list the validator list ui - * @return the validator list mouse listener, or <code>null</code> if not - * found - * @see SwingValidatorMessageListMouseListener - */ - public static SwingValidatorMessageListMouseListener getErrorListMouseListener(JList list) { - if (list != null) { - for (MouseListener listener : list.getMouseListeners()) { - if (listener instanceof SwingValidatorMessageListMouseListener) { - return (SwingValidatorMessageListMouseListener) listener; - } - } - } - return null; - } - - /** - * @param table the validator table ui - * @return the validator table mouse listener, or <code>null</code> if not - * found - * @see SwingValidatorMessageTableMouseListener - */ - public static SwingValidatorMessageTableMouseListener getErrorTableMouseListener(JTable table) { - if (table != null) { - for (MouseListener listener : table.getMouseListeners()) { - if (listener instanceof SwingValidatorMessageTableMouseListener) { - return (SwingValidatorMessageTableMouseListener) listener; - } - } - } - return null; - } - - /** - * @param table the validator table ui - * @return the validator table mouse listener, or <code>null</code> if not - * found - * @see SwingValidatorMessageTableMouseListener - */ - public static SwingValidatorMessageTableMouseListener getListErrorTableMouseListener(JTable table) { - if (table != null) { - for (MouseListener listener : table.getMouseListeners()) { - if (listener instanceof SwingValidatorMessageTableMouseListener) { - return (SwingValidatorMessageTableMouseListener) listener; - } - } - } - return null; - } - - public static String getMessage(SwingValidatorMessage model) { - String text = model.getMessage(); - if (model.getField() != null) { - text = model.getI18nError(text); - } - return text; - } - - public static String getMessage(SimpleBeanValidatorMessage model) { - String text = model.getMessage(); - if (model.getField() != null) { - text = model.getI18nError(text); - } - return text; - } - - public static String getMessage(SwingListValidatorMessage model) { - String text = model.getMessage(); - if (model.getField() != null) { - text = model.getI18nError(text); - } - return text; - } - - public static String getMessage(UnifiedValidatorMessage model) { - String text = model.getMessage(); - if (model.getField() != null) { - text = model.getI18nError(text); - } - return text; - } - - public static String getFieldName(SwingValidatorMessage model, String value) { - String text = null; - JComponent editor = model.getEditor(); - if (editor != null) { - text = (String) editor.getClientProperty("validatorLabel"); - /*if (l != null) { - text = I18n.t(l); - } else { - // TODO should try the text - }*/ - } - if (text == null) { - text = value; - } - return text; - } - - public static String getFieldName(SwingListValidatorMessage model, String value) { - String text = null; - JComponent editor = model.getEditor(); - if (editor != null) { - text = (String) editor.getClientProperty("validatorLabel"); - /*if (l != null) { - text = I18n.t(l); - } else { - // TODO should try the text - }*/ - } - if (text == null) { - text = value; - } - return text; - } - - public static String getFieldName(UnifiedValidatorMessage model, String value) { - return getFieldName(model, value, null); - } - - public static String getFieldName(UnifiedValidatorMessage model, String value, String valueFallBack) { - String text = null; - JComponent editor = model.getEditor(); - Object validatorLabel = null; - if (editor != null) { - - validatorLabel = editor.getClientProperty("validatorLabel"); - - } - - if (validatorLabel != null) { - - if (model.isSimpleValidator()) { - - text = (String) validatorLabel; - - } else { - - Map<String, String> validatorLabelMap = (Map<String, String>) validatorLabel; - - String field = model.getField(); - text = validatorLabelMap.get(field); - - } - } - - if (text == null && valueFallBack != null) { - text = valueFallBack; - } - - if (text == null) { - text = value; - } - - return text; - } - - /** - * Method to listen the modification of the context name and at each time - * reload fields of the ui. - * - * @param validator validator to listen - * @param ui ui to refresh when context name has changed - * @since 2.2.1 - */ - public static void listenValidatorContextNameAndRefreshFields( - SwingValidator<?> validator, - final JAXXValidator ui) { - - PropertyChangeListener listener = new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - SwingValidator<?> validator = (SwingValidator<?>) evt.getSource(); - if (log.isInfoEnabled()) { - log.info("Context name changed to [" + evt.getNewValue() + - "] for validator " + validator.getType()); - } - ui.registerValidatorFields(); - } - }; - validator.addPropertyChangeListener( - SwingValidator.CONTEXT_PROPERTY, - listener - ); - } - -// /** -// * Default bean validator creator to use in the {@link BeanValidatorFactory}. -// * -// * @author Tony Chemit - chemit@codelutin.com -// * @since 2.1 -// */ -// public static class DefaultSwingValidatorCreator implements BeanValidatorFactory.BeanValidatorCreator { -// -// @Override -// public <O> BeanValidator<O> newBeanValidator(NuitonValidatorProvider provider, Class<O> type, String context, NuitonValidatorScope... scopes) { -// BeanValidator<O> beanValidator = new SwingValidator<O>(provider, -// type, -// context, -// scopes -// ); -// return beanValidator; -// } -// } - - /** - * Convinient method to attach a bean to all validators of an JAXXObject. - * - * It is possible to exclude some validator to be treated. - * - * @param ui the ui containing the validatros to treate - * @param bean the bean to attach in validators (can be null) - * @param excludeIds the list of validator id to exclude - */ - @SuppressWarnings({"unchecked"}) - public static void setValidatorBean(JAXXObject ui, - Object bean, - String... excludeIds) { - if (!JAXXValidator.class.isAssignableFrom(ui.getClass())) { - return; - } - JAXXValidator jaxxValidator = (JAXXValidator) ui; - List<String> validatorIds = jaxxValidator.getValidatorIds(); - if (excludeIds.length > 0) { - validatorIds = new ArrayList<String>(validatorIds); - for (String excludeId : excludeIds) { - validatorIds.remove(excludeId); - } - } - for (String validatorId : validatorIds) { - SwingValidator beanValidator = - jaxxValidator.getValidator(validatorId); - if (bean == null || beanValidator.getType().isAssignableFrom( - bean.getClass())) { - // touch validator, only if fits the bean type (or bean is null) - beanValidator.setBean(bean); - } - } - } - - /** - * Convinient method to set the changed property to all validators of an - * JAXXObject. - * - * It is possible to exclude some validator to be treated. - * - * @param ui the ui containing the validatros to treate - * @param newValue the new value to set in changed validator property - * @param excludeIds the list of validator id to exclude - */ - @SuppressWarnings({"unchecked"}) - public static void setValidatorChanged(JAXXObject ui, - boolean newValue, - String... excludeIds) { - if (!JAXXValidator.class.isAssignableFrom(ui.getClass())) { - return; - } - JAXXValidator jaxxValidator = (JAXXValidator) ui; - List<String> validatorIds = jaxxValidator.getValidatorIds(); - if (excludeIds.length > 0) { - validatorIds = new ArrayList<String>(validatorIds); - for (String excludeId : excludeIds) { - validatorIds.remove(excludeId); - } - } - for (String validatorId : validatorIds) { - SwingValidator<?> beanValidator = - jaxxValidator.getValidator(validatorId); - beanValidator.setChanged(newValue); - } - } - - protected static Multimap<JComponent, ValidatorField> getValidatorEditors(JAXXValidator ui) { - - Multimap<JComponent, ValidatorField> editors = ArrayListMultimap.create(); - - Map<Field, ValidatorField> validatorFields = null; - Map<Method, ValidatorField> validatorMethods = null; - try { - - validatorFields = ReflectUtil.getFieldAnnotation( - ui.getClass(), - ValidatorField.class, - true - ); - - validatorMethods = ReflectUtil.getMethodAnnotation( - ui.getClass(), - ValidatorField.class, - true - ); - for (Map.Entry<Field, ValidatorField> fieldEntry : validatorFields.entrySet()) { - Field field = fieldEntry.getKey(); - field.setAccessible(true); - ValidatorField fieldAnnotation = fieldEntry.getValue(); - JComponent editor = (JComponent) field.get(ui); - editors.put(editor, fieldAnnotation); - } - - for (Map.Entry<Method, ValidatorField> fieldEntry : validatorMethods.entrySet()) { - Method method = fieldEntry.getKey(); - method.setAccessible(true); - ValidatorField fieldAnnotation = fieldEntry.getValue(); - JComponent editor = (JComponent) method.invoke(ui); - editors.put(editor, fieldAnnotation); - } - - } catch (Exception e) { - throw new IllegalStateException("Could not init validators on ui " + ui, e); - } finally { - if (validatorFields != null) { - validatorFields.clear(); - } - if (validatorMethods != null) { - validatorMethods.clear(); - } - } - return editors; - } - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/meta/Validator.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/meta/Validator.java deleted file mode 100644 index 68f9cbd..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/meta/Validator.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing.meta; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation to put on each field validator. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.3 - */ -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -public @interface Validator { - - /** - * Obtain the id of the validator. - * - * @return the id of the validator. - */ - String validatorId(); -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/meta/ValidatorField.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/meta/ValidatorField.java deleted file mode 100644 index dbd1f01..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/meta/ValidatorField.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing.meta; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation to put on each field or method linked to a validator. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.3 - */ -@Target(value = {ElementType.FIELD, ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface ValidatorField { - /** - * Obtain the id of the validator used for the field. - * - * @return the id of the validator used for the field. - */ - String validatorId(); - - /** - * Obtain the name of the bean property(ies) to validate. - * - * @return the name of the property(ies) to validate - */ - String[] propertyName(); - - /** - * Obtain the name of the property editor. - * - * If empty, then use the {@link #propertyName()}. - * - * @return the name of the property editor - */ - String editorName() default ""; -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/AbstractBeanValidatorUI.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/AbstractBeanValidatorUI.java deleted file mode 100644 index ccc7ca6..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/AbstractBeanValidatorUI.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing.ui; - -import com.google.common.collect.Ordering; -import com.google.common.collect.Sets; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.jxlayer.plaf.AbstractLayerUI; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.simple.SimpleBeanValidator; -import org.nuiton.validator.bean.simple.SimpleBeanValidatorEvent; -import org.nuiton.validator.bean.simple.SimpleBeanValidatorListener; - -import javax.swing.JComponent; -import java.util.Collection; -import java.util.Set; - -/** - * Abstract renderer - * - * @author Tony Chemit - chemit@codelutin.com - */ -public abstract class AbstractBeanValidatorUI extends AbstractLayerUI<JComponent> implements SimpleBeanValidatorListener { - - /** Logger */ - private static final Log log = LogFactory.getLog(AbstractBeanValidatorUI.class); - - private static final long serialVersionUID = 1L; - - /** - * Actual scope to display in the layer. - * - * This field will be recomputed each time a new event arrived on this - * field. - */ - protected NuitonValidatorScope scope; - - /** Field name in validator. */ - protected final Set<String> fields; - - protected AbstractBeanValidatorUI(String field) { - this(Sets.newHashSet(field)); - } - - protected AbstractBeanValidatorUI(Collection<String> fields) { - this.fields = Sets.newHashSet(fields); - if (log.isDebugEnabled()) { - log.debug("install " + this + "<fields:" + this.fields + ">"); - } - } - - public NuitonValidatorScope getScope() { - return scope; - } - - @Override - public void onFieldChanged(SimpleBeanValidatorEvent event) { - if (fields.contains(event.getField())) { - - scope = getHighestScope(event); - if (log.isDebugEnabled()) { - log.debug("set new scope : " + scope + " to field " + fields); - } - // ask to repaint the layer - setDirty(true); - } - } - - protected NuitonValidatorScope getHighestScope(SimpleBeanValidatorEvent event) { - SimpleBeanValidator<?> source = event.getSource(); - Set<NuitonValidatorScope> scopes = Sets.newHashSet(); - for (String field : fields) { - NuitonValidatorScope scope = source.getHighestScope(field); - if (scope != null) { - scopes.add(scope); - } - } - return scopes.isEmpty() ? null : Ordering.natural().max(scopes); - } - - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/IconValidationUI.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/IconValidationUI.java deleted file mode 100644 index 7fe1c53..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/IconValidationUI.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing.ui; - -import com.google.common.collect.Sets; -import jaxx.runtime.validator.swing.SwingValidatorUtil; -import org.jdesktop.jxlayer.JXLayer; -import org.nuiton.validator.NuitonValidatorScope; - -import javax.swing.BorderFactory; -import javax.swing.JComponent; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.util.Collection; -import java.util.EnumMap; -import java.util.Set; - - -/** - * An implementation of {@link AbstractBeanValidatorUI} which paints a icon on - * top right corner. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class IconValidationUI extends AbstractBeanValidatorUI { - - private static final long serialVersionUID = 1L; - - // The icon to be shown at the layer's corner - - protected EnumMap<NuitonValidatorScope, BufferedImage> icons; - - public IconValidationUI(String field) { - this(Sets.newHashSet(field)); - } - - public IconValidationUI(Collection<String> fields) { - super(fields); - icons = new EnumMap<NuitonValidatorScope, BufferedImage>(NuitonValidatorScope.class); - - for (NuitonValidatorScope scope : NuitonValidatorScope.values()) { - - BufferedImage image = prepareIcon(SwingValidatorUtil.getColor(scope)); - icons.put(scope, image); - } - } - - @Override - public void installUI(JComponent c) { - super.installUI(c); - c.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 3)); - } - - @Override - public void uninstallUI(JComponent c) { - super.uninstallUI(c); - c.setBorder(null); - } - - @Override - protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { - super.paintLayer(g2, l); - // There is no need to take insets into account for this painter - NuitonValidatorScope scope = getScope(); - if (scope != null) { - BufferedImage icon = icons.get(scope); - g2.drawImage(icon, l.getWidth() - icon.getWidth() - 1, 0, null); - } - } - - protected static BufferedImage prepareIcon(Color color) { - int width = 7; - int height = 8; - BufferedImage icon = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g2 = (Graphics2D) icon.getGraphics(); - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); - g2.setColor(color); - g2.fillRect(0, 0, width, height); - g2.setColor(Color.WHITE); - g2.drawLine(0, 0, width, height); - g2.drawLine(0, height, width, 0); - g2.dispose(); - return icon; - } - - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/ImageValidationUI.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/ImageValidationUI.java deleted file mode 100644 index 7a76836..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/ImageValidationUI.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing.ui; - -import com.google.common.collect.Sets; -import jaxx.runtime.validator.swing.SwingValidatorUtil; -import org.jdesktop.jxlayer.JXLayer; -import org.nuiton.validator.NuitonValidatorScope; - -import javax.swing.BorderFactory; -import javax.swing.ImageIcon; -import javax.swing.JComponent; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.util.Collection; -import java.util.EnumMap; -import java.util.Set; - - -/** - * An implementation of {@link AbstractBeanValidatorUI} which paints a icon on - * top right corner. - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class ImageValidationUI extends AbstractBeanValidatorUI { - - private static final long serialVersionUID = 1L; - - protected EnumMap<NuitonValidatorScope, BufferedImage> icons; - - public ImageValidationUI(String fields) { - this(Sets.newHashSet(fields)); - } - - public ImageValidationUI(Collection<String> fields) { - super(fields); - icons = new EnumMap<NuitonValidatorScope, BufferedImage>(NuitonValidatorScope.class); - - for (NuitonValidatorScope scope : NuitonValidatorScope.values()) { - - BufferedImage image = prepareIcon(SwingValidatorUtil.getIcon(scope)); - icons.put(scope, image); - } - } - - protected static BufferedImage prepareIcon(ImageIcon image) { - BufferedImage icon = new BufferedImage(image.getIconWidth(), image.getIconHeight(), BufferedImage.TYPE_INT_ARGB); - Graphics2D g2 = (Graphics2D) icon.getGraphics(); - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); - g2.drawImage(image.getImage(), 0, 0, null); - g2.dispose(); - return icon; - } - - @Override - public void installUI(JComponent c) { - super.installUI(c); - c.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 3)); - } - - @Override - public void uninstallUI(JComponent c) { - super.uninstallUI(c); - c.setBorder(null); - } - - @Override - protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { - super.paintLayer(g2, l); - NuitonValidatorScope scope = getScope(); - if (scope != null) { - BufferedImage icon = icons.get(scope); - g2.drawImage(icon, l.getWidth() - icon.getWidth() - 1, 0, null); - } - } -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/TranslucentValidationUI.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/TranslucentValidationUI.java deleted file mode 100644 index bc692ca..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/TranslucentValidationUI.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.validator.swing.ui; - -import jaxx.runtime.validator.swing.SwingValidatorUtil; -import org.jdesktop.jxlayer.JXLayer; -import org.nuiton.validator.NuitonValidatorScope; - -import javax.swing.JComponent; -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.Rectangle; -import java.util.Collection; -import java.util.Set; - -/** - * An implementation of {@link AbstractBeanValidatorUI} which paints a - * translucent backgroud color (green for ok, red for error, yellow for - * warning). - * - * @author Tony Chemit - chemit@codelutin.com - */ -public class TranslucentValidationUI extends AbstractBeanValidatorUI { - - private static final long serialVersionUID = 1L; - - public TranslucentValidationUI(String field) { - super(field); - } - - public TranslucentValidationUI(Collection<String> fields) { - super(fields); - } - - @Override - protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { - // paints the layer as is - super.paintLayer(g2, l); - - // to be in sync with the view if the layer has a border - Insets layerInsets = l.getInsets(); - g2.translate(layerInsets.left, layerInsets.top); - - JComponent view = l.getView(); - // To prevent painting on view's border - Insets insets = view.getInsets(); - g2.clip(new Rectangle(insets.left, insets.top, - view.getWidth() - insets.left - insets.right, - view.getHeight() - insets.top - insets.bottom)); - - NuitonValidatorScope scope = getScope(); - - Color c = scope == null ? Color.WHITE : SwingValidatorUtil.getColor(scope); - g2.setColor(c); - g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .2f)); - g2.fillRect(0, 0, l.getWidth(), l.getHeight()); - } -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessage.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessage.java deleted file mode 100644 index 99bd1c9..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessage.java +++ /dev/null @@ -1,198 +0,0 @@ -package jaxx.runtime.validator.swing.unified; - -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.validator.swing.SwingValidator; -import org.apache.commons.lang3.ObjectUtils; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.AbstractValidator; - -import javax.swing.JComponent; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.StringTokenizer; - -import static org.nuiton.i18n.I18n.t; - -/** - * Created on 8/15/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.10 - */ -public class UnifiedValidatorMessage implements Comparable<UnifiedValidatorMessage>, Serializable { - - private static final long serialVersionUID = 1L; - - /** the validator that produce the message */ - protected final AbstractValidator<?> validator; - - /** the bean on which event occurs. */ - protected final Object bean; - - /** the field that produce the message */ - protected final String field; - - /** the label of the message (to be displayed somewhere) */ - protected final String message; - - /** the scope of the message */ - protected final NuitonValidatorScope scope; - - /** the optional field's editor */ - protected JComponent editor; - - protected final boolean simpleValidator; - - public UnifiedValidatorMessage(AbstractValidator<?> validator, - Object bean, - String field, - String message, - NuitonValidatorScope scope, - JComponent editor) { - this.field = field; - this.bean = bean; - this.validator = validator; - this.message = message == null ? null : message.trim(); - this.scope = scope; - this.simpleValidator = validator instanceof SwingValidator<?>; - this.editor = editor; - } - - public AbstractValidator<?> getValidator() { - return validator; - } - - public String getField() { - return field; - } - - public NuitonValidatorScope getScope() { - return scope; - } - - public String getMessage() { - return message; - } - - public Object getBean() { - return bean; - } - - public JComponent getEditor() { - return editor; - } - - public boolean isSimpleValidator() { - return simpleValidator; - } - - @Override - public int compareTo(UnifiedValidatorMessage o) { - // sort on scope - int result = getScope().compareTo(o.getScope()); - if (result == 0) { - - // sort on bean - - if (simpleValidator) { - - if (o.simpleValidator) { - result = 0; - } else { - // this message must go up (simple message) - result = -1; - } - } else { - if (o.simpleValidator) { - // that message must go up (simple message) - result = 1; - } - } - if (result == 0) { - - // sort on field name - result = field.compareTo(o.field); - if (result == 0) { - // sort on message - result = message.compareTo(o.message); - } - } - } - return result; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof UnifiedValidatorMessage)) { - return false; - } - - UnifiedValidatorMessage that = (UnifiedValidatorMessage) o; - - return field.equals(that.field) && - ObjectUtils.equals(bean, that.bean) && - ObjectUtils.equals(message, that.message) && - scope == that.scope; - } - - @Override - public int hashCode() { - int result = field.hashCode(); - result = 31 * result + (bean != null ? bean.hashCode() : 0); - result = 31 * result + (message != null ? message.hashCode() : 0); - result = 31 * result + (scope != null ? scope.hashCode() : 0); - return result; - } - - @Override - public String toString() { - String s = scope + " - " + - (field == null ? message : field + "[" + getBean() + - "] - " + message); - if (editor != null) { - s = editor.getName() + " : " + s; - } - return s; - } - - public String getI18nError(String error) { - String text; - if (!error.contains("##")) { - text = t(error); - } else { - StringTokenizer stk = new StringTokenizer(error, "##"); - String errorName = stk.nextToken(); - List<String> args = new ArrayList<String>(); - while (stk.hasMoreTokens()) { - args.add(stk.nextToken()); - } - text = t(errorName, args.toArray()); - } - return text; - } -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageTableModel.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageTableModel.java deleted file mode 100644 index afc8720..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageTableModel.java +++ /dev/null @@ -1,473 +0,0 @@ -package jaxx.runtime.validator.swing.unified; - -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.validator.swing.SwingListValidator; -import jaxx.runtime.validator.swing.SwingValidator; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.AbstractValidator; -import org.nuiton.validator.bean.list.BeanListValidator; -import org.nuiton.validator.bean.list.BeanListValidatorEvent; -import org.nuiton.validator.bean.list.BeanListValidatorListener; -import org.nuiton.validator.bean.simple.SimpleBeanValidatorEvent; -import org.nuiton.validator.bean.simple.SimpleBeanValidatorListener; - -import javax.swing.JComponent; -import javax.swing.table.AbstractTableModel; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * Created on 8/15/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.10 - */ -public class UnifiedValidatorMessageTableModel extends AbstractTableModel { - - private static final long serialVersionUID = 1L; - - /** Logger */ - private static Log log = - LogFactory.getLog(UnifiedValidatorMessageTableModel.class); - - public static final String[] columnNames = - {"validator.scope", - "validator.bean", - "validator.field", - "validator.message"}; - - public static final Class<?>[] columnClasses = - {NuitonValidatorScope.class, Object.class, String.class, String.class}; - - /** list of registred validators */ - protected List<AbstractValidator<?>> validators; - - /** list of messages actual displayed */ - protected List<UnifiedValidatorMessage> data; - - protected transient BeanListValidatorListener listValidatorListener; - - protected transient SimpleBeanValidatorListener simpleValidatorListener; - - public UnifiedValidatorMessageTableModel() { - data = Lists.newArrayList(); - validators = Lists.newArrayList(); - } - - /** - * Register a validator for this model. - * - * - * Note: a validator can not be register twice in the same model. - * - * @param validator the validator to register - */ - public void registerValidator(SwingValidator<?> validator) { - if (validators.contains(validator)) { - throw new IllegalArgumentException( - "the validator " + validator + " is already registred in " - + this); - } - validators.add(validator); - validator.addSimpleBeanValidatorListener(getSimpleValidatorListener()); - } - - /** - * Register a validator for this model. - * - * - * Note: a validator can not be register twice in the same model. - * - * @param validator the validator to register - */ - public void registerValidator(BeanListValidator<?> validator) { - Preconditions.checkState( - !validators.contains(validator), - "Validator " + validator + " is already registred in " - + this); - validators.add(validator); - validator.addBeanListValidatorListener(getListValidatorListener()); - } - - public void clear() { - int i = data.size(); - if (i > 0) { - data.clear(); - fireTableRowsDeleted(0, i - 1); - } - } - - public void clearValidators() { - for (AbstractValidator<?> v : validators) { - if (v instanceof BeanListValidator) { - ((BeanListValidator) v).removeBeanListValidatorListener(getListValidatorListener()); - } else if (v instanceof SwingValidator) { - ((SwingValidator) v).removeSimpleBeanValidatorListener(getSimpleValidatorListener()); - } - } - validators.clear(); - } - - @Override - public boolean isCellEditable(int row, int column) { - // cells are never editable in this model - return false; - } - - @Override - public Class<?> getColumnClass(int columnIndex) { - SwingUtil.ensureColumnIndex(this, columnIndex); - return columnClasses[columnIndex]; - } - - @Override - public String getColumnName(int column) { - SwingUtil.ensureColumnIndex(this, column); - return columnNames[column]; - } - - @Override - public int getRowCount() { - return data.size(); - } - - @Override - public int getColumnCount() { - return columnNames.length; - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - SwingUtil.ensureColumnIndex(this, columnIndex); - SwingUtil.ensureRowIndex(this, rowIndex); - - UnifiedValidatorMessage message = data.get(rowIndex); - - Object result; - - switch (columnIndex) { - case 0:// the icon - result = message.getScope(); - - break; - case 1: - // the bean - result = message.isSimpleValidator() ? "-" : message.getBean(); - break; - case 2: - // the field - result = message.getField(); - break; - case 3: - // the message - result = message.getMessage(); - break; - default: - throw new IllegalStateException("Can't come here"); - } - - return result; - } - - /** - * Obtain the message for a given row. - * - * @param rowIndex the row index - * @return the message for the given row index - */ - public UnifiedValidatorMessage getRow(int rowIndex) { - SwingUtil.ensureRowIndex(this, rowIndex); - return data.get(rowIndex); - } - - protected void addMessages(SwingValidator<?> validator, - String fieldName, - NuitonValidatorScope scope, - boolean sort, - String... messages) { - - JComponent editor = validator == null ? - null : - validator.getFieldRepresentation(fieldName); - // add new errors - for (String error : messages) { - UnifiedValidatorMessage row = - new UnifiedValidatorMessage( - validator, - null, - fieldName, - error, - scope, - editor - ); - data.add(row); - if (!sort) { - fireTableRowsInserted(data.size() - 1, data.size() - 1); - } - } - - if (sort) { - - // resort datas - Collections.sort(data); - - // notify - fireTableDataChanged(); - } - } - -// protected void addMessages(JComponent editor, -// String fieldName, -// NuitonValidatorScope scope, -// boolean sort, -// String... messages) { -// -// // add new errors -// for (String message : messages) { -// UnifiedValidatorMessage row = -// new UnifiedValidatorMessage( -// null, -// null, -// fieldName, -// message, -// scope, -// editor); -// data.add(row); -// if (!sort) { -// fireTableRowsInserted(data.size() - 1, data.size() - 1); -// } -// } -// -// if (sort) { -// -// // resort datas -// Collections.sort(data); -// -// // notify -// fireTableDataChanged(); -// } -// } - - protected void addMessages(BeanListValidator<?> validator, - Object bean, - String fieldName, - NuitonValidatorScope scope, - boolean sort, - String... messages) { - - JComponent editor = null; - - if (validator instanceof SwingListValidator<?>) { - editor = ((SwingListValidator) validator).getEditor(); - } - - // add new errors - for (String message : messages) { - UnifiedValidatorMessage row = - new UnifiedValidatorMessage( - validator, - bean, - fieldName, - message, - scope, - editor); - data.add(row); - if (!sort) { - fireTableRowsInserted(data.size() - 1, data.size() - 1); - } - } - - if (sort) { - - // resort datas - Collections.sort(data); - - // notify - fireTableDataChanged(); - } - } - - protected void removeMessages(SwingValidator<?> validator, - String fieldName, - NuitonValidatorScope scope, - boolean notify, - String... messages) { - - List<String> messagesToDel = - new ArrayList<String>(Arrays.asList(messages)); - - // do it in reverse mode (only one pass in that way since index - // will stay coherent while removing them) - - for (int i = getRowCount() - 1; i > -1; i--) { - UnifiedValidatorMessage message = data.get(i); - - if (validator.equals(message.getValidator()) - && message.getScope() == scope - && message.getField().equals(fieldName) - && messagesToDel.contains(message.getMessage())) { - // remove the message - data.remove(i); - if (notify) { - fireTableRowsDeleted(i, i); - } - } - - } - } - - protected void removeMessages(JComponent editor, - String fieldName, - NuitonValidatorScope scope, - boolean notify) { - - // do it in reverse mode (only one pass in that way since index - // will stay coherent while removing them) - - for (int i = getRowCount() - 1; i > -1; i--) { - UnifiedValidatorMessage message = data.get(i); - if (editor.equals(message.getEditor()) - && (scope == null || message.getScope() == scope) - && message.getField().equals(fieldName)) { - // remove the message - data.remove(i); - if (notify) { - fireTableRowsDeleted(i, i); - } - } - } - } - - protected void removeMessages(BeanListValidator<?> validator, - Object bean, - String fieldName, - NuitonValidatorScope scope, - boolean notify, - String... messages) { - - List<String> messagesToDel = - new ArrayList<String>(Arrays.asList(messages)); - - // do it in reverse mode (only one pass in that way since index - // will stay coherent while removing them) - - for (int i = getRowCount() - 1; i > -1; i--) { - UnifiedValidatorMessage message = data.get(i); - if (validator.equals(message.getValidator()) - && message.getScope() == scope - && message.getBean() == bean - && message.getField().equals(fieldName) - && messagesToDel.contains(message.getMessage())) { - // remove the message - data.remove(i); - if (notify) { - fireTableRowsDeleted(i, i); - } - } - } - } - - protected BeanListValidatorListener getListValidatorListener() { - if (listValidatorListener == null) { - listValidatorListener = new BeanListValidatorListener() { - @Override - public void onFieldChanged(BeanListValidatorEvent event) { - String[] toDelete = event.getMessagesToDelete(); - String[] toAdd = event.getMessagesToAdd(); - String field = event.getField(); - Object bean = event.getBean(); - NuitonValidatorScope scope = event.getScope(); - boolean mustAdd = toAdd != null && toAdd.length > 0; - boolean mustDel = toDelete != null && toDelete.length > 0; - - if (log.isTraceEnabled()) { - log.trace("----------------------------------------------------------"); - log.trace(field + " - (" + getRowCount() + ") toAdd " + mustAdd); - log.trace(field + " - (" + getRowCount() + ") toDelete " + mustDel); - } - - BeanListValidator<?> validator = event.getSource(); - - if (mustDel) { - - // removes datas and notify if no messages to add - removeMessages(validator, bean, field, scope, !mustAdd, toDelete); - } - - if (mustAdd) { - - // add new messages, sort datas and notify - addMessages(validator, bean, field, scope, true, toAdd); - } - } - }; - } - return listValidatorListener; - } - - protected SimpleBeanValidatorListener getSimpleValidatorListener() { - if (simpleValidatorListener == null) { - simpleValidatorListener = new SimpleBeanValidatorListener() { - @Override - public void onFieldChanged(SimpleBeanValidatorEvent event) { - String[] toDelete = event.getMessagesToDelete(); - String[] toAdd = event.getMessagesToAdd(); - String field = event.getField(); - NuitonValidatorScope scope = event.getScope(); - boolean mustAdd = toAdd != null && toAdd.length > 0; - boolean mustDel = toDelete != null && toDelete.length > 0; - - if (log.isTraceEnabled()) { - log.trace("----------------------------------------------------------"); - log.trace(field + " - (" + getRowCount() + ") toAdd " + mustAdd); - log.trace(field + " - (" + getRowCount() + ") toDelete " + mustDel); - } - - SwingValidator<?> validator = (SwingValidator<?>) event.getSource(); - - if (mustDel) { - - // removes datas and notify if no messages to add - removeMessages(validator, field, scope, !mustAdd, toDelete); - } - - if (mustAdd) { - - // add new messages, sort datas and notify - addMessages(validator, field, scope, true, toAdd); - } - } - }; - } - return simpleValidatorListener; - } - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageTableMouseListener.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageTableMouseListener.java deleted file mode 100644 index c6a1448..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageTableMouseListener.java +++ /dev/null @@ -1,158 +0,0 @@ -package jaxx.runtime.validator.swing.unified; - -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.SwingUtil; -import jaxx.runtime.validator.swing.SwingListValidatorDataLocator; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.JComponent; -import javax.swing.JTable; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; - -/** - * Created on 8/15/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.10 - */ -public class UnifiedValidatorMessageTableMouseListener extends MouseAdapter { - - /** Logger */ - private static Log log = - LogFactory.getLog(UnifiedValidatorMessageTableMouseListener.class); - - public static final String HIGHLIGHT_ERROR_PROPERTY = "highlightError"; - - /** - * Delegate property change support. - */ - protected final PropertyChangeSupport pcs; - - /** - * The editor of listened bean. - */ - protected final JTable editor; - - /** - * The cell data locator. - */ - protected final SwingListValidatorDataLocator<Object> dataLocator; - - public UnifiedValidatorMessageTableMouseListener(JTable editor, - SwingListValidatorDataLocator dataLocator) { - this.editor = editor; - this.dataLocator = dataLocator; - this.pcs = new PropertyChangeSupport(this); - } - - @Override - public void mouseClicked(MouseEvent e) { - super.mouseClicked(e); - if (e.getClickCount() == 2) { - - UnifiedValidatorMessage entry = getSelectedMessage(e); - if (entry == null) { - // no entry found - return; - } - - if (entry.isSimpleValidator()) { - - JComponent component = entry.getEditor(); - if (component != null) { - pcs.firePropertyChange(HIGHLIGHT_ERROR_PROPERTY, null, entry); - if (component.isVisible()) { - component.requestFocus(); - } - } - - } else { - - if (dataLocator.acceptType(entry.getBean().getClass())) { - - Pair<Integer, Integer> cell = dataLocator.locateDataCell( - editor.getModel(), - entry.getBean(), - entry.getField()); - - SwingUtil.editCell(editor, cell.getLeft(), cell.getRight()); - } - - } - - } - } - - protected UnifiedValidatorMessage getSelectedMessage(MouseEvent e) { - JTable table = (JTable) e.getSource(); - if (!(table.getModel() instanceof UnifiedValidatorMessageTableModel)) { - if (log.isWarnEnabled()) { - log.warn("model must be a " + - UnifiedValidatorMessageTableModel.class + - ", but was " + table.getModel()); - } - return null; - } - - UnifiedValidatorMessageTableModel model = - (UnifiedValidatorMessageTableModel) table.getModel(); - int index = table.getSelectionModel().getMinSelectionIndex(); - if (index == -1) { - // nothing is selected - return null; - } - if (table.getRowSorter() != null) { - index = table.getRowSorter().convertRowIndexToModel(index); - } - UnifiedValidatorMessage entry = model.getRow(index); - if (log.isDebugEnabled()) { - log.debug("selected index: " + index + " : error: " + entry); - } - return entry; - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - pcs.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - pcs.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, - PropertyChangeListener listener) { - pcs.removePropertyChangeListener(propertyName, listener); - } - -} \ No newline at end of file diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageTableRenderer.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageTableRenderer.java deleted file mode 100644 index 28c5cdc..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageTableRenderer.java +++ /dev/null @@ -1,187 +0,0 @@ -package jaxx.runtime.validator.swing.unified; - -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.collect.Maps; -import jaxx.runtime.validator.swing.SwingValidatorUtil; -import org.apache.commons.lang3.StringUtils; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.simple.SimpleBeanValidator; - -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.table.DefaultTableCellRenderer; -import java.awt.Component; -import java.util.Map; - -import static org.nuiton.i18n.I18n.t; - -/** - * Created on 8/15/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.10 - */ -public class UnifiedValidatorMessageTableRenderer extends DefaultTableCellRenderer { - - private static final long serialVersionUID = 1L; - - protected final Map<String, String> fieldNameMap = Maps.newHashMap(); - - @Override - public Component getTableCellRendererComponent(JTable table, - Object value, - boolean isSelected, - boolean hasFocus, - int row, - int column) { - JLabel rendererComponent = (JLabel) - super.getTableCellRendererComponent( - table, - value, - isSelected, - hasFocus, - row, - column - ); - - ImageIcon icon = null; - String text = null; - String toolTipText = null; - - column = table.convertColumnIndexToModel(column); - if (table.getRowSorter() != null) { - row = table.getRowSorter().convertRowIndexToModel(row); - } - - if (column == 0) { - - // scope - NuitonValidatorScope scope = (NuitonValidatorScope) value; - icon = getIcon(row, scope); - toolTipText = getIconTip(row, scope); - - } else { - - UnifiedValidatorMessageTableModel tableModel = - (UnifiedValidatorMessageTableModel) table.getModel(); - UnifiedValidatorMessage validatorMessage = tableModel.getRow(row); - - switch (column) { - - case 1: - - // row bean - - if (validatorMessage.isSimpleValidator()) { - - text = getSimpleBeanValidatorValue(row, validatorMessage); - toolTipText = getSimpleBeanValidatorValueTip(row, text); - - } else { - - text = getListBeanValidatorValue(row, validatorMessage); - toolTipText = getListBeanValidatorValueTip(row, text); - - } - break; - - case 2: - - // field name - text = getFieldName(row, validatorMessage, (String) value); - toolTipText = getFieldNameTip(row, text); - break; - - case 3: - - // message - text = getMessage(row, validatorMessage); - toolTipText = getMessageTip(row, text); - break; - - } - - } - - rendererComponent.setText(text); - rendererComponent.setToolTipText(toolTipText); - rendererComponent.setIcon(icon); - return rendererComponent; - } - - public ImageIcon getIcon(int row, NuitonValidatorScope scope) { - return SwingValidatorUtil.getIcon(scope); - } - - public String getIconTip(int row, NuitonValidatorScope scope) { - String label = t(scope.getLabel()); - return t("validator.scope.tip", label); - } - - public String getMessage(int row, UnifiedValidatorMessage model) { - return SwingValidatorUtil.getMessage(model); - } - - public String getMessageTip(int row, String message) { - return t("validator.message.tip", message); - } - - public String getFieldName(int row, UnifiedValidatorMessage model, String value) { - return SwingValidatorUtil.getFieldName(model, value, fieldNameMap.get(value)); - } - - public String getFieldNameTip(int row, String fieldName) { - return t("validator.field.tip", fieldName); - } - - public String getListBeanValidatorValue(int row, UnifiedValidatorMessage model) { - return decorateBean(model.getBean()); - } - - public String getListBeanValidatorValueTip(int row, String beanValue) { - return StringUtils.isEmpty(beanValue) ? null : t("validator.bean.tip", row, beanValue); - } - - public String getSimpleBeanValidatorValue(int row, UnifiedValidatorMessage model) { - return decorateBean(((SimpleBeanValidator) model.getValidator()).getBean()); - } - - public String getSimpleBeanValidatorValueTip(int row, String simpleBeanValue) { - return null; - } - - protected String decorateBean(Object bean) { - return bean == null ? "" : bean.toString(); - } - - public void clearFieldNameMap() { - fieldNameMap.clear(); - } - - public void addFieldName(String field, String name) { - fieldNameMap.put(field, name); - } - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageUtil.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageUtil.java deleted file mode 100644 index f546daf..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageUtil.java +++ /dev/null @@ -1,187 +0,0 @@ -package jaxx.runtime.validator.swing.unified; - -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.SwingUtil; -import jaxx.runtime.validator.swing.SwingListValidatorDataLocator; -import jaxx.runtime.validator.swing.SwingListValidatorTableEditorModelListener; -import jaxx.runtime.validator.swing.SwingValidator; -import jaxx.runtime.validator.swing.SwingValidatorMessageTableMouseListener; -import org.nuiton.validator.bean.list.BeanListValidator; - -import javax.swing.JTable; -import javax.swing.RowSorter; -import javax.swing.SortOrder; -import javax.swing.table.TableModel; -import java.awt.event.MouseListener; -import java.util.Arrays; - -import static org.nuiton.i18n.I18n.n; - -/** - * Created on 8/15/14. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.10 - */ -public class UnifiedValidatorMessageUtil { - - /** - * Prepare the ui where to display the validators messages. - * - * @param errorTable the table where to display validators messages - * @param render renderer to use - */ - public static void installUI(JTable errorTable, - UnifiedValidatorMessageTableRenderer render) { - - errorTable.setDefaultRenderer(Object.class, render); - errorTable.getRowSorter().setSortKeys( - Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); - - SwingUtil.setI18nTableHeaderRenderer( - errorTable, - n("validator.scope.header"), - n("validator.scope.header.tip"), - n("validator.bean.header"), - n("validator.bean.header.tip"), - n("validator.field.header"), - n("validator.field.header.tip"), - n("validator.message.header"), - n("validator.message.header.tip")); - SwingUtil.fixTableColumnWidth(errorTable, 0, 25); - - } - - /** - * Prepare the ui where to display the validators messages. - * - * @param messageTable the table where to display validators messages - */ - public static <O> void registerValidator(SwingValidator<O> validator, - JTable messageTable) { - - UnifiedValidatorMessageTableModel messageTableModel = getModel(messageTable); - - // register the validator to the error table model - messageTableModel.registerValidator(validator); - - // add the mouse listener - UnifiedValidatorMessageTableMouseListener listener = getUnifiedValidatorMessageTableMouseListener(messageTable); - - if (listener == null) { - registerErrorTableMouseListener(messageTable, null, null); - } - - } - - /** - * Prepare the ui where to display the validators messages. - * - * @param validator validator to register - * @param messageTable the table where to display validators messages - * @param dataTable table with data to validate by the validator - * @param dataLocator tool to find data in the data table from the validator messages - */ - public static <O> void registerValidator(BeanListValidator<O> validator, - JTable messageTable, - JTable dataTable, - SwingListValidatorDataLocator<O> dataLocator) { - - UnifiedValidatorMessageTableModel messageTableModel = getModel(messageTable); - - // register the validator to the error table model - messageTableModel.registerValidator(validator); - - // add the mouse listener - registerErrorTableMouseListener(messageTable, dataTable, dataLocator); - - // listen on editor model to add / remove bean into validator - dataTable.getModel().addTableModelListener( - new SwingListValidatorTableEditorModelListener<O>(validator, dataLocator)); - } - - /** - * Register for a given validator table ui a validator mouse listener. - * - * If a previous such listener was registered, then we will remove it and register a new one. - * - * @param messageTable the validator table ui - * @param dataTable table with data to validate by the validator - * @param dataLocator tool to find data in the data table from the validator messages - * @see UnifiedValidatorMessageTableMouseListener - */ - public static <O> void registerErrorTableMouseListener(JTable messageTable, - JTable dataTable, - SwingListValidatorDataLocator<O> dataLocator) { - UnifiedValidatorMessageTableMouseListener listener = - getUnifiedValidatorMessageTableMouseListener(messageTable); - - if (listener != null) { - - // remove existing listener - messageTable.removeMouseListener(listener); - - } - - listener = new UnifiedValidatorMessageTableMouseListener(dataTable, dataLocator); - messageTable.addMouseListener(listener); - - } - - /** - * @param table the validator table ui - * @return the validator table mouse listener, or <code>null</code> if not found - * @see SwingValidatorMessageTableMouseListener - */ - public static UnifiedValidatorMessageTableMouseListener getUnifiedValidatorMessageTableMouseListener(JTable table) { - - UnifiedValidatorMessageTableMouseListener result = null; - - for (MouseListener listener : table.getMouseListeners()) { - - if (listener instanceof UnifiedValidatorMessageTableMouseListener) { - - result = (UnifiedValidatorMessageTableMouseListener) listener; - break; - - } - } - - return result; - - } - - protected static UnifiedValidatorMessageTableModel getModel(JTable messageTable) { - - TableModel model = messageTable.getModel(); - - if (!(model instanceof UnifiedValidatorMessageTableModel)) { - throw new IllegalStateException("messageTable is not using a UnifiedValidatorMessageTableModel model: " + model); - } - - return (UnifiedValidatorMessageTableModel) model; - - } - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageWidget.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageWidget.java deleted file mode 100644 index 2ab4d40..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/UnifiedValidatorMessageWidget.java +++ /dev/null @@ -1,319 +0,0 @@ -package jaxx.runtime.validator.swing.unified; - -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.SwingUtil; -import jaxx.runtime.swing.ComponentMover; -import jaxx.runtime.swing.ComponentResizer; -import jaxx.runtime.validator.swing.SwingListValidatorDataLocator; -import jaxx.runtime.validator.swing.SwingListValidatorMessageTableRenderer; -import jaxx.runtime.validator.swing.SwingValidator; -import jaxx.runtime.validator.swing.SwingValidatorUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.JXTitledPanel; -import org.nuiton.validator.NuitonValidatorScope; -import org.nuiton.validator.bean.list.BeanListValidator; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JRootPane; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.JToggleButton; -import javax.swing.JToolBar; -import javax.swing.KeyStroke; -import javax.swing.ListSelectionModel; -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; -import javax.swing.table.TableCellRenderer; -import java.awt.Component; -import java.awt.Point; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.HierarchyBoundsAdapter; -import java.awt.event.HierarchyEvent; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -import static org.nuiton.i18n.I18n.n; -import static org.nuiton.i18n.I18n.t; - -/** - * @author Tony Chemit - chemit@codelutin.com - * @since 2.10 - */ -public class UnifiedValidatorMessageWidget extends JToggleButton { - - private static final Log log = - LogFactory.getLog(UnifiedValidatorMessageWidget.class); - - private static final long serialVersionUID = 1L; - - public static final String CLOSE_DIALOG_ACTION = "closeDialog"; - - protected UnifiedValidatorMessageTableModel messageTableModel = new UnifiedValidatorMessageTableModel(); - - protected JDialog popup = new JDialog(); - - protected JTable messageTable = new JTable(); - - protected Point popupPosition = null; - - public UnifiedValidatorMessageWidget() { - super(SwingUtil.createActionIcon("alert-none")); - setToolTipText(t("validator.messageWidget.alert.none")); - - messageTableModel.addTableModelListener(new TableModelListener() { - - public void tableChanged(TableModelEvent e) { - int alerts = messageTableModel.getRowCount(); - String label; - switch (alerts) { - case 0: - label = n("validator.messageWidget.alert.none"); - break; - case 1: - label = n("validator.messageWidget.alert.one"); - break; - default: - label = n("validator.messageWidget.alert.several"); - } - - NuitonValidatorScope maxScope; - String icon; - if (alerts == 0) { - icon = "alert-none"; - - } else { - maxScope = NuitonValidatorScope.INFO; - for (int i = 0; i < alerts; i++) { - NuitonValidatorScope scope = messageTableModel.getRow(i).getScope(); - int diff = scope.compareTo(maxScope); - if (diff < 0) { - maxScope = scope; - } - } - switch (maxScope) { - case INFO: - icon = "alert-info"; - break; - case WARNING: - icon = "alert-warning"; - break; - default: - icon = "alert-error"; - - } - } - - setToolTipText(t(label, alerts)); - setIcon(SwingUtil.createActionIcon(icon)); - } - }); - - messageTable.setModel(messageTableModel); - messageTable.setRowSelectionAllowed(true); - messageTable.setAutoCreateRowSorter(true); - messageTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); - messageTable.setCellSelectionEnabled(false); - messageTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - messageTable.setFillsViewportHeight(true); - - SwingValidatorUtil.installUI(messageTable, - new SwingListValidatorMessageTableRenderer()); - - JScrollPane scrollPanel = new JScrollPane(messageTable); - scrollPanel.setColumnHeaderView(messageTable.getTableHeader()); - - JXTitledPanel titledPanel = new JXTitledPanel(t("validator.messageWidget.title"), scrollPanel); - popup.add(titledPanel); - popup.setTitle(t("validator.messageWidget.title")); - popup.setSize(800, 300); - popup.setAlwaysOnTop(true); - popup.setUndecorated(true); - - ComponentResizer cr = new ComponentResizer(); - cr.registerComponent(popup); - ComponentMover cm = new ComponentMover(); - cm.setDragInsets(cr.getDragInsets()); - cm.registerComponent(popup); - - popup.addWindowListener(new WindowAdapter() { - - @Override - public void windowClosing(WindowEvent e) { - setSelected(false); - } - - }); - - popup.addComponentListener(new ComponentAdapter() { - - @Override - public void componentMoved(ComponentEvent e) { - Component component = e.getComponent(); - if (component.isShowing()) { - popupPosition = component.getLocationOnScreen(); - } - } - - }); - - addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - if (isSelected()) { - popup.setVisible(true); - } else { - popup.dispose(); - } - } - }); - - addHierarchyBoundsListener(new HierarchyBoundsAdapter() { - - @Override - public void ancestorMoved(HierarchyEvent e) { - if (popupPosition == null && isShowing()) { - Point point = new Point(getLocationOnScreen()); - point.translate(-popup.getWidth() + getWidth(), -popup.getHeight()); - popup.setLocation(point); - } - } - }); - - // add a auto-close action - JRootPane rootPane = popup.getRootPane(); - - KeyStroke shortcutClosePopup = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); - - rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( - shortcutClosePopup, CLOSE_DIALOG_ACTION); - - Action closeAction = new AbstractAction() { - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent e) { - popup.dispose(); - setSelected(false); - } - }; - - ImageIcon actionIcon = SwingUtil.createActionIcon("close-dialog"); - closeAction.putValue(Action.SMALL_ICON, actionIcon); - closeAction.putValue(Action.LARGE_ICON_KEY, actionIcon); - closeAction.putValue(Action.ACTION_COMMAND_KEY, "close"); - closeAction.putValue(Action.NAME, "close"); - closeAction.putValue(Action.SHORT_DESCRIPTION, t("validator.messageWidget.closeDialog.tip")); - - rootPane.getActionMap().put(CLOSE_DIALOG_ACTION, closeAction); - - JButton closeButton = new JButton(closeAction); - closeButton.setText(null); - closeButton.setFocusPainted(false); - closeButton.setRequestFocusEnabled(false); - closeButton.setFocusable(false); - - JToolBar jToolBar = new JToolBar(); - jToolBar.setOpaque(false); - jToolBar.add(closeAction); - jToolBar.setBorderPainted(false); - jToolBar.setFloatable(false); - titledPanel.setRightDecoration(jToolBar); - - } - - public void addTableModelListener(TableModelListener listener) { - messageTableModel.addTableModelListener(listener); - } - - public void removeTableModelListener(TableModelListener listener) { - messageTableModel.removeTableModelListener(listener); - } - - public void setDefaultRenderer(TableCellRenderer renderer) { - messageTable.setDefaultRenderer(Object.class, renderer); - } - - public TableCellRenderer getDefaultRenderer() { - return messageTable.getDefaultRenderer(Object.class); - } - - /** - * Register a simple validator. - * - * @param validator validator to register - */ - public void registerValidator(SwingValidator validator) { - - if (log.isInfoEnabled()) { - log.info("Register validator: " + validator); - } - - UnifiedValidatorMessageUtil.registerValidator( - validator, - messageTable); - - validator.doValidate(); - } - - /** - * Register a list validator. - * - * @param validator validator to register - * @param dataTable table with data to validate by the validator - * @param dataLocator tool to find data in the data table from the validator messages - */ - public void registerValidator(BeanListValidator validator, - JTable dataTable, - SwingListValidatorDataLocator dataLocator) { - - if (log.isInfoEnabled()) { - log.info("Register validator: " + validator); - } - UnifiedValidatorMessageUtil.registerValidator( - validator, - messageTable, - dataTable, - dataLocator); - - validator.doValidate(); - } - - /** Clear all the validators. */ - public void clearValidators() { - messageTableModel.clearValidators(); - messageTableModel.clear(); - } - -} diff --git a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/package-info.java b/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/package-info.java deleted file mode 100644 index 5705780..0000000 --- a/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/unified/package-info.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * To unify Simple and List validators. - * - * Created on 8/15/14. - * @author Tony Chemit - chemit@codelutin.com - * @since 2.10 - */ -package jaxx.runtime.validator.swing.unified; - -/* - * #%L - * JAXX :: Validator - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/JAXXValidator.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/JAXXValidator.java new file mode 100644 index 0000000..eba2154 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/JAXXValidator.java @@ -0,0 +1,61 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator; + + +import org.nuiton.jaxx.validator.swing.SwingValidator; + +import javax.swing.JComponent; +import java.util.List; + +/** + * The contract of a validator-able object. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public interface JAXXValidator { + + /** + * Obtain a validator from his id + * + * @param validatorId validator id + * @return the associated validator, or <code>null</code> if not find + */ + SwingValidator<?> getValidator(String validatorId); + + /** @return the list of ids of all registred validator */ + List<String> getValidatorIds(); + + /** + * Init the fields representation. + * + * This method is generated and should be called each time the context name + * of a validator has changed, since when using method + * {@link SwingValidator#setFieldRepresentation(String, JComponent)} + * is invoked at init, if a field is not watched for the selected context, + * then after when changing context name, the field will not be notified of any changed... + * + * @since 2.2.1 + */ + void registerValidatorFields(); + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SimpleBeanValidatorMessageTableModel.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SimpleBeanValidatorMessageTableModel.java new file mode 100644 index 0000000..30bc2fa --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SimpleBeanValidatorMessageTableModel.java @@ -0,0 +1,269 @@ +package org.nuiton.jaxx.validator.swing; + +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.simple.SimpleBeanValidator; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorEvent; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorListener; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorMessage; + +import javax.swing.table.AbstractTableModel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * A model of the table of errors based on {@link SimpleBeanValidatorMessage}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6.23 + */ +public class SimpleBeanValidatorMessageTableModel extends AbstractTableModel + implements SimpleBeanValidatorListener { + + private static final long serialVersionUID = 1L; + + /** Logger */ + private static Log log = + LogFactory.getLog(SimpleBeanValidatorMessageTableModel.class); + + public static final String[] columnNames = + {"validator.scope", "validator.field", "validator.message"}; + + public static final Class<?>[] columnClasses = + {NuitonValidatorScope.class, String.class, String.class}; + + /** list of registred validators */ + protected transient List<SimpleBeanValidator<?>> validators; + + /** list of messages actual displayed */ + protected List<SimpleBeanValidatorMessage> data; + + public SimpleBeanValidatorMessageTableModel() { + validators = new ArrayList<SimpleBeanValidator<?>>(); + data = new ArrayList<SimpleBeanValidatorMessage>(); + } + + /** + * Register a validator for this model. + * + * + * Note: a validator can not be register twice in the same model. + * + * @param validator the validator to register + */ + public void registerValidator(SimpleBeanValidator<?> validator) { + if (validators.contains(validator)) { + throw new IllegalArgumentException( + "the validator " + validator + " is already registred in " + + this); + } + validators.add(validator); + validator.addSimpleBeanValidatorListener(this); + } + + public void addMessages(SimpleBeanValidator<?> validator, + String fieldName, + NuitonValidatorScope scope, + String... messages) { + addMessages(validator, fieldName, scope, true, messages); + } + + public void removeMessages(SimpleBeanValidator<?> validator, + String fieldName, + NuitonValidatorScope scope, + String... messages) { + removeMessages(validator, fieldName, scope, true, messages); + } + + public void clear() { + int i = data.size(); + if (i > 0) { + data.clear(); + fireTableRowsDeleted(0, i - 1); + } + } + + public void clearValidators() { + for (SimpleBeanValidator<?> v : validators) { + v.removeSimpleBeanValidatorListener(this); + } + validators.clear(); + } + + /** + * Obtain the message for a given row. + * + * @param rowIndex the row index + * @return the message for the given row index + */ + public SimpleBeanValidatorMessage getRow(int rowIndex) { + SwingUtil.ensureRowIndex(this, rowIndex); + return data.get(rowIndex); + } + + @Override + public boolean isCellEditable(int row, int column) { + // cells are never editable in this model + return false; + } + + @Override + public Class<?> getColumnClass(int columnIndex) { + SwingUtil.ensureColumnIndex(this, columnIndex); + return columnClasses[columnIndex]; + } + + @Override + public String getColumnName(int column) { + SwingUtil.ensureColumnIndex(this, column); + return columnNames[column]; + } + + @Override + public void onFieldChanged(SimpleBeanValidatorEvent event) { + String[] toDelete = event.getMessagesToDelete(); + String[] toAdd = event.getMessagesToAdd(); + String field = event.getField(); + NuitonValidatorScope scope = event.getScope(); + boolean mustAdd = toAdd != null && toAdd.length > 0; + boolean mustDel = toDelete != null && toDelete.length > 0; + + if (log.isTraceEnabled()) { + log.trace("----------------------------------------------------------"); + log.trace(field + " - (" + getRowCount() + ") toAdd " + mustAdd); + log.trace(field + " - (" + getRowCount() + ") toDelete " + mustDel); + } + + SimpleBeanValidator<?> validator = event.getSource(); + + if (mustDel) { + + // removes datas and notify if no messages to add + removeMessages(validator, field, scope, !mustAdd, toDelete); + } + + if (mustAdd) { + + // add new messages, sort datas and notify + addMessages(validator, field, scope, true, toAdd); + } + } + + @Override + public int getRowCount() { + return data.size(); + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + SwingUtil.ensureColumnIndex(this, columnIndex); + SwingUtil.ensureRowIndex(this, rowIndex); + + SimpleBeanValidatorMessage row = data.get(rowIndex); + if (columnIndex == 0) { + // the icon + return row.getScope(); + } + if (columnIndex == 1) { + // the field + return row.getField(); + } + if (columnIndex == 2) { + // the message + return row.getMessage(); + } + + // should never come here + return null; + } + + protected void addMessages(SimpleBeanValidator<?> validator, + String fieldName, + NuitonValidatorScope scope, + boolean sort, + String... messages) { + + + // add new errors + for (String error : messages) { + SimpleBeanValidatorMessage row = + new SimpleBeanValidatorMessage<SimpleBeanValidatorMessage<?>>( + validator, + fieldName, + error, + scope + ); + data.add(row); + if (!sort) { + fireTableRowsInserted(data.size() - 1, data.size() - 1); + } + } + + if (sort) { + + // resort datas + Collections.sort(data); + + // notify + fireTableDataChanged(); + } + } + + protected void removeMessages(SimpleBeanValidator<?> validator, + String fieldName, + NuitonValidatorScope scope, + boolean notify, + String... messages) { + + List<String> messagesToDel = + new ArrayList<String>(Arrays.asList(messages)); + + // do it in reverse mode (only one pass in that way since index + // will stay coherent while removing them) + + for (int i = getRowCount() - 1; i > -1; i--) { + SimpleBeanValidatorMessage error = data.get(i); + if (validator.equals(error.getValidator()) && + error.getScope() == scope && + error.getField().equals(fieldName) && + messagesToDel.contains(error.getMessage())) { + // remove the message + data.remove(i); + if (notify) { + fireTableRowsDeleted(i, i); + } + } + } + } +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SimpleBeanValidatorMessageTableRenderer.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SimpleBeanValidatorMessageTableRenderer.java new file mode 100644 index 0000000..195ee27 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SimpleBeanValidatorMessageTableRenderer.java @@ -0,0 +1,117 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing; + +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorMessage; + +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import java.awt.Component; + +import static org.nuiton.i18n.I18n.t; + +/** + * A simple render of a table of validator's messages, says a table that use + * a {@link SimpleBeanValidatorMessageTableModel} model. + * + * @author Tony Chemit - chemit@codelutin.com + * @see SimpleBeanValidatorMessageTableModel + * @since 2.6.23 + */ +public class SimpleBeanValidatorMessageTableRenderer extends DefaultTableCellRenderer { + + private static final long serialVersionUID = 1L; + + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, + int column) { + JLabel rendererComponent = (JLabel) + super.getTableCellRendererComponent( + table, + value, + isSelected, + hasFocus, + row, + column + ); + + ImageIcon icon = null; + String text = null; + String toolTipText = null; + + column = table.convertColumnIndexToModel(column); + if (table.getRowSorter() != null) { + row = table.getRowSorter().convertRowIndexToModel(row); + } + + switch (column) { + case 0: + // scope + NuitonValidatorScope scope = (NuitonValidatorScope) value; + icon = SwingValidatorUtil.getIcon(scope); + String label = t(scope.getLabel()); + toolTipText = t("validator.scope.tip", label); + break; + + case 1: + // field name + text = getFieldName(table, (String) value, row); + toolTipText = t("validator.field.tip", text); + break; + + case 2: + // message + text = getMessage(table, (String) value, row); + toolTipText = t("validator.message.tip", text); + break; + } + + rendererComponent.setText(text); + rendererComponent.setToolTipText(toolTipText); + rendererComponent.setIcon(icon); + return rendererComponent; + } + + public ImageIcon getIcon(NuitonValidatorScope scope) { + return SwingValidatorUtil.getIcon(scope); + } + + public String getMessage(JTable table, String value, int row) { + SimpleBeanValidatorMessageTableModel tableModel = + (SimpleBeanValidatorMessageTableModel) table.getModel(); + SimpleBeanValidatorMessage model = tableModel.getRow(row); + return SwingValidatorUtil.getMessage(model); + } + + public String getFieldName(JTable table, String value, int row) { + SimpleBeanValidatorMessageTableModel tableModel = + (SimpleBeanValidatorMessageTableModel) table.getModel(); + return value; + } +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidator.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidator.java new file mode 100644 index 0000000..f09c1d7 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidator.java @@ -0,0 +1,131 @@ +package org.nuiton.jaxx.validator.swing; + +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.validator.NuitonValidator; +import org.nuiton.validator.NuitonValidatorFactory; +import org.nuiton.validator.NuitonValidatorProvider; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.list.BeanListValidator; + +import javax.swing.JComponent; + +/** + * Created on 9/17/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.13 + */ +public class SwingListValidator<B> extends BeanListValidator<B> { + + /** Logger */ + private static final Log log = LogFactory.getLog(SwingListValidator.class); + + /** + * Obtain a new {@link SwingListValidator} for the given parameters. + * + * <b>Note:</b> It will use the default provider of {@link NuitonValidator} + * + * @param type type of bean to validate + * @param context context of validation + * @param scopes authorized scopes (if {@code null}, will use all scopes) + * @param <O> type of bean to validate + * @return the new instanciated {@link BeanListValidator}. + * @throws NullPointerException if type is {@code null} + * @see NuitonValidatorFactory#getDefaultProviderName() + */ + public static <O> SwingListValidator<O> newSwingValidator(Class<O> type, + String context, + NuitonValidatorScope... scopes) throws NullPointerException { + + + // get the provider default name + String providerName = NuitonValidatorFactory.getDefaultProviderName(); + + // get the bean validator with this provider + return newSwingValidator(providerName, + type, + context, + scopes + ); + } + + /** + * Obtain a new {@link SwingListValidator} for the given parameters. + * + * <b>Note:</b> It will use the provider of {@link NuitonValidator} + * defined by the {@code providerName}. + * + * @param providerName name of {@link NuitonValidator} to use + * @param type type of bean to validate + * @param context context of validation + * @param scopes authorized scopes (if {@code null}, will use all scopes) + * @param <O> type of bean to validate + * @return the new instanciated {@link BeanListValidator}. + * @throws NullPointerException if type is {@code null} + * @see NuitonValidatorFactory#getProvider(String) + */ + public static <O> SwingListValidator<O> newSwingValidator(String providerName, + Class<O> type, + String context, + NuitonValidatorScope... scopes) throws NullPointerException { + + Preconditions.checkNotNull(type, "type parameter can not be null."); + + // get delegate validator provider + NuitonValidatorProvider provider = + NuitonValidatorFactory.getProvider(providerName); + + Preconditions.checkState( + provider != null, + "Could not find provider with name " + providerName); + + // create the new instance of bean validator + + return new SwingListValidator<O>( + provider, type, context, scopes + ); + } + + protected JComponent editor; + + public SwingListValidator(NuitonValidatorProvider validatorProvider, Class<B> beanClass, String context) { + super(validatorProvider, beanClass, context); + } + + public SwingListValidator(NuitonValidatorProvider validatorProvider, Class<B> beanClass, String context, NuitonValidatorScope... scopes) { + super(validatorProvider, beanClass, context, scopes); + } + + public JComponent getEditor() { + return editor; + } + + public void setEditor(JComponent editor) { + this.editor = editor; + } + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorDataLocator.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorDataLocator.java new file mode 100644 index 0000000..717f4ca --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorDataLocator.java @@ -0,0 +1,77 @@ +package org.nuiton.jaxx.validator.swing; +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.lang3.tuple.Pair; + +import javax.swing.table.TableModel; + +/** + * Object that can locate for a given {@link SwingListValidatorMessage}, + * the cell of this data in a table editor. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.3 + */ +public interface SwingListValidatorDataLocator<O> { + + /** + * Tests if the given type can be managed by this locator. + * + * Useful if there is more than one locator used for a same list + * validation table model. + * + * @param beanType the type of bean to test + * @return {@code true} if this locator can manage this bean type. + */ + boolean acceptType(Class<?> beanType); + + /** + * Locate the cell of the given data. + * + * @param tableModel the table model where data are edited + * @param bean the bean to locate + * @param fieldName the field to locate + * @return the cell where to find data + */ + Pair<Integer, Integer> locateDataCell(TableModel tableModel, + O bean, + String fieldName); + + /** + * Locate the index of the row of the given bean. + * + * @param tableModel the table model where data are edited + * @param bean the bean to find + * @return the row index of the given bean in the table. + */ + int locateBeanRowIndex(TableModel tableModel, O bean); + + /** + * Locate the bean given his row index in the table. + * + * @param tableModel the table model where data are edited + * @param rowIndex the row index of the bean to find in the editor + * @return the bean corresponding to the given row index in the editor + */ + O locateBean(TableModel tableModel, int rowIndex); +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorHighlightPredicate.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorHighlightPredicate.java new file mode 100644 index 0000000..70394c2 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorHighlightPredicate.java @@ -0,0 +1,139 @@ +package org.nuiton.jaxx.validator.swing; +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.jdesktop.swingx.decorator.ComponentAdapter; +import org.jdesktop.swingx.decorator.HighlightPredicate; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.list.BeanListValidator; + +import javax.swing.JTable; +import java.awt.Component; + +/** + * HighLight predicates for a table editor using {@link BeanListValidator} of + * his data. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.3 + */ +public class SwingListValidatorHighlightPredicate<O> implements HighlightPredicate { + + /** + * Filtering scope. + * + * @since 2.5.3 + */ + protected final NuitonValidatorScope scope; + + /** + * Validator (contains data). + * + * @since 2.5.3 + */ + protected final BeanListValidator<O> validator; + + /** + * Data locator to find back data in editor. + * + * @since 2.5.3 + */ + protected final SwingListValidatorDataLocator<O> dataLocator; + + public static <O> SwingListValidatorHighlightPredicate<O> newFatalPredicate( + BeanListValidator<O> validator, + SwingListValidatorDataLocator<O> dataLocator) { + return newPredicate( + NuitonValidatorScope.FATAL, + validator, + dataLocator + ); + } + + public static <O> SwingListValidatorHighlightPredicate<O> newErrorPredicate( + BeanListValidator<O> validator, + SwingListValidatorDataLocator<O> dataLocator) { + return newPredicate( + NuitonValidatorScope.ERROR, + validator, + dataLocator + ); + } + + public static <O> SwingListValidatorHighlightPredicate<O> newWarningPredicate( + BeanListValidator<O> validator, + SwingListValidatorDataLocator<O> dataLocator) { + return newPredicate( + NuitonValidatorScope.WARNING, + validator, + dataLocator + ); + } + + public static <O> SwingListValidatorHighlightPredicate<O> newInfoPredicate( + BeanListValidator<O> validator, + SwingListValidatorDataLocator<O> dataLocator) { + return newPredicate( + NuitonValidatorScope.INFO, + validator, + dataLocator + ); + } + + public static <O> SwingListValidatorHighlightPredicate<O> newPredicate( + NuitonValidatorScope scope, + BeanListValidator<O> validator, + SwingListValidatorDataLocator<O> dataLocator) { + return new SwingListValidatorHighlightPredicate<O>( + scope, + validator, + dataLocator + ); + } + + public SwingListValidatorHighlightPredicate(NuitonValidatorScope scope, + BeanListValidator<O> validator, + SwingListValidatorDataLocator<O> dataLocator) { + this.scope = scope; + this.validator = validator; + this.dataLocator = dataLocator; + } + + @Override + public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { + + int columnIndex = adapter.convertColumnIndexToModel(adapter.column); + + String fieldName = adapter.getColumnName(columnIndex); + + int rowIndex = adapter.convertRowIndexToModel(adapter.row); + JTable component = (JTable) adapter.getComponent(); + O bean = dataLocator.locateBean(component.getModel(), rowIndex); + boolean result = false; + if (bean != null && dataLocator.acceptType(bean.getClass())) { + BeanListValidator.NuitonValidatorContext<O> context = validator.getContext(bean); + NuitonValidatorScope highestScope = context.getHighestScope(fieldName); + result = scope == highestScope; + } + return result; + } +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessage.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessage.java new file mode 100644 index 0000000..23280b0 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessage.java @@ -0,0 +1,67 @@ +package org.nuiton.jaxx.validator.swing; +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.list.BeanListValidator; +import org.nuiton.validator.bean.list.BeanListValidatorMessage; + +import javax.swing.JComponent; + +/** + * TODO + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.3 + */ +public class SwingListValidatorMessage extends BeanListValidatorMessage<SwingListValidatorMessage> { + + private static final long serialVersionUID = 1L; + + /** the optional field's editor */ + protected JComponent editor; + + public SwingListValidatorMessage(BeanListValidator<?> validator, + Object bean, + String fieldName, + String message, + NuitonValidatorScope scope, + JComponent editor) { + super(validator, bean, fieldName, message, scope); + this.editor = editor; + } + + public JComponent getEditor() { + return editor; + } + + @Override + public String toString() { + String s = scope + " - " + + (field == null ? message : field + "[" + getBean() + + "] - " + message); + if (editor != null) { + s = editor.getName() + " : " + s; + } + return s; + } +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessageTableModel.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessageTableModel.java new file mode 100644 index 0000000..136e1e2 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessageTableModel.java @@ -0,0 +1,275 @@ +package org.nuiton.jaxx.validator.swing; +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.list.BeanListValidator; +import org.nuiton.validator.bean.list.BeanListValidatorEvent; +import org.nuiton.validator.bean.list.BeanListValidatorListener; + +import javax.swing.JComponent; +import javax.swing.table.AbstractTableModel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * The model of the table of errors. + * + * The model listens list-validators messages and update his internal model + * from it. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.3 + */ +public class SwingListValidatorMessageTableModel extends AbstractTableModel + implements BeanListValidatorListener { + + private static final long serialVersionUID = 1L; + + /** Logger */ + private static Log log = + LogFactory.getLog(SwingListValidatorMessageTableModel.class); + + public static final String[] columnNames = + {"validator.scope", "validator.bean", + "validator.field", "validator.message"}; + + public static final Class<?>[] columnClasses = + {NuitonValidatorScope.class, Object.class, String.class, String.class}; + + /** list of registred validators */ + protected transient List<BeanListValidator<?>> validators; + + /** list of messages actual displayed */ + protected List<SwingListValidatorMessage> data; + + public SwingListValidatorMessageTableModel() { + data = Lists.newArrayList(); + validators = Lists.newArrayList(); + } + + /** + * Register a validator for this model. + * + * + * Note: a validator can not be register twice in the same model. + * + * @param validator the validator to register + */ + public void registerValidator(BeanListValidator<?> validator) { + Preconditions.checkState( + !validators.contains(validator), + "Validator " + validator + " is already registred in " + + this); + validators.add(validator); + validator.addBeanListValidatorListener(this); + } + + public void clear() { + int i = data.size() + data.size(); + if (i > 0) { + data.clear(); + fireTableRowsDeleted(0, i - 1); + } + } + + public void clearValidators() { + for (BeanListValidator<?> v : validators) { + v.removeBeanListValidatorListener(this); + } + validators.clear(); + } + + /** + * Obtain the message for a given row. + * + * @param rowIndex the row index + * @return the message for the given row index + */ + public SwingListValidatorMessage getRow(int rowIndex) { + SwingUtil.ensureRowIndex(this, rowIndex); + return data.get(rowIndex); + } + + @Override + public boolean isCellEditable(int row, int column) { + // cells are never editable in this model + return false; + } + + @Override + public Class<?> getColumnClass(int columnIndex) { + SwingUtil.ensureColumnIndex(this, columnIndex); + return columnClasses[columnIndex]; + } + + @Override + public String getColumnName(int column) { + SwingUtil.ensureColumnIndex(this, column); + return columnNames[column]; + } + + @Override + public void onFieldChanged(BeanListValidatorEvent event) { + String[] toDelete = event.getMessagesToDelete(); + String[] toAdd = event.getMessagesToAdd(); + String field = event.getField(); + Object bean = event.getBean(); + NuitonValidatorScope scope = event.getScope(); + boolean mustAdd = toAdd != null && toAdd.length > 0; + boolean mustDel = toDelete != null && toDelete.length > 0; + + if (log.isTraceEnabled()) { + log.trace("----------------------------------------------------------"); + log.trace(field + " - (" + getRowCount() + ") toAdd " + mustAdd); + log.trace(field + " - (" + getRowCount() + ") toDelete " + mustDel); + } + + BeanListValidator<?> validator = event.getSource(); + + if (mustDel) { + + // removes datas and notify if no messages to add + removeMessages(validator, bean, field, scope, !mustAdd, toDelete); + } + + if (mustAdd) { + + // add new messages, sort datas and notify + addMessages(validator, bean, field, scope, true, toAdd); + } + } + + @Override + public int getRowCount() { + return data.size(); + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + SwingUtil.ensureColumnIndex(this, columnIndex); + SwingUtil.ensureRowIndex(this, rowIndex); + + SwingListValidatorMessage row = data.get(rowIndex); + if (columnIndex == 0) { + // the icon + return row.getScope(); + } + if (columnIndex == 1) { + // the bean + return row.getBean(); + } + if (columnIndex == 2) { + // the field + return row.getField(); + } + if (columnIndex == 3) { + // the message + return row.getMessage(); + } + + // should never come here + return null; + } + + protected void addMessages(BeanListValidator<?> validator, + Object bean, + String fieldName, + NuitonValidatorScope scope, + boolean sort, + String... messages) { + +// JComponent editor = validator == null ? +// null : +// validator.getFieldRepresentation(fieldName); + + JComponent editor = null; + + // add new errors + for (String error : messages) { + SwingListValidatorMessage row = + new SwingListValidatorMessage( + validator, + bean, + fieldName, + error, + scope, + editor + ); + data.add(row); + if (!sort) { + fireTableRowsInserted(data.size() - 1, data.size() - 1); + } + } + + if (sort) { + + // resort datas + Collections.sort(data); + + // notify + fireTableDataChanged(); + } + } + + protected void removeMessages(BeanListValidator<?> validator, + Object bean, + String fieldName, + NuitonValidatorScope scope, + boolean notify, + String... messages) { + + List<String> messagesToDel = + new ArrayList<String>(Arrays.asList(messages)); + + // do it in reverse mode (only one pass in that way since index + // will stay coherent while removing them) + + for (int i = getRowCount() - 1; i > -1; i--) { + SwingListValidatorMessage error = data.get(i); + if (validator.equals(error.getValidator()) && + error.getScope() == scope && + error.getBean() == bean && + error.getField().equals(fieldName) && + messagesToDel.contains(error.getMessage())) { + // remove the message + data.remove(i); + if (notify) { + fireTableRowsDeleted(i, i); + } + } + } + } + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessageTableMouseListener.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessageTableMouseListener.java new file mode 100644 index 0000000..7fc6fe9 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessageTableMouseListener.java @@ -0,0 +1,149 @@ +package org.nuiton.jaxx.validator.swing; +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JTable; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +/** + * A mouse listener to edit a cell when double clicking on a validation + * message coming from a {@link SwingValidatorMessageTableModel}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.3 + */ +public class SwingListValidatorMessageTableMouseListener extends MouseAdapter { + + /** Logger */ + private static Log log = + LogFactory.getLog(SwingListValidatorMessageTableMouseListener.class); + + public static final String HIGHLIGHT_ERROR_PROPERTY = "highlightError"; + + /** + * Delegate property change support. + * + * @since 2.5.3 + */ + protected PropertyChangeSupport pcs; + + /** + * The editor of listened bean. + * + * @since 2.5.3 + */ + protected final JTable editor; + + /** + * The cell data locator. + * + * @since 2.5.3 + */ + protected final SwingListValidatorDataLocator dataLocator; + + public SwingListValidatorMessageTableMouseListener( + JTable editor, + SwingListValidatorDataLocator dataLocator) { + this.editor = editor; + this.dataLocator = dataLocator; + pcs = new PropertyChangeSupport(this); + } + + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + if (e.getClickCount() == 2) { + + SwingListValidatorMessage entry = getSelectedMessage(e); + if (entry == null) { + // no entry found + return; + } + + if (dataLocator.acceptType(entry.getBean().getClass())) { + + Pair<Integer, Integer> cell = dataLocator.locateDataCell( + editor.getModel(), + entry.getBean(), + entry.getField()); + + SwingUtil.editCell(editor, cell.getLeft(), cell.getRight()); + } + + } + } + + protected SwingListValidatorMessage getSelectedMessage(MouseEvent e) { + JTable table = (JTable) e.getSource(); + if (!(table.getModel() instanceof SwingListValidatorMessageTableModel)) { + if (log.isWarnEnabled()) { + log.warn("model must be a " + + SwingValidatorMessageTableModel.class + + ", but was " + table.getModel()); + } + return null; + } + + SwingListValidatorMessageTableModel model = + (SwingListValidatorMessageTableModel) table.getModel(); + int index = table.getSelectionModel().getMinSelectionIndex(); + if (index == -1) { + // nothing is selected + return null; + } + if (table.getRowSorter() != null) { + index = table.getRowSorter().convertRowIndexToModel(index); + } + SwingListValidatorMessage entry = model.getRow(index); + if (log.isDebugEnabled()) { + log.debug("selected index: " + index + " : error: " + entry); + } + return entry; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessageTableRenderer.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessageTableRenderer.java new file mode 100644 index 0000000..f087822 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessageTableRenderer.java @@ -0,0 +1,132 @@ +package org.nuiton.jaxx.validator.swing; +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.validator.NuitonValidatorScope; + +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import java.awt.Component; + +import static org.nuiton.i18n.I18n.t; + +/** + * TODO + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.3 + */ +public class SwingListValidatorMessageTableRenderer extends DefaultTableCellRenderer { + + private static final long serialVersionUID = 1L; + + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, + int column) { + JLabel rendererComponent = (JLabel) + super.getTableCellRendererComponent( + table, + value, + isSelected, + hasFocus, + row, + column + ); + + ImageIcon icon = null; + String text = null; + String toolTipText = null; + + column = table.convertColumnIndexToModel(column); + if (table.getRowSorter() != null) { + row = table.getRowSorter().convertRowIndexToModel(row); + } + + switch (column) { + case 0: + // scope + NuitonValidatorScope scope = (NuitonValidatorScope) value; + icon = SwingValidatorUtil.getIcon(scope); + String label = t(scope.getLabel()); + toolTipText = t("validator.scope.tip", label); + break; + + case 1: + // row bean + text = getBeanValue(table, row); + toolTipText = t("validator.bean.tip", text); + break; + + case 2: + // field name + text = getFieldName(table, (String) value, row); + toolTipText = t("validator.field.tip", text); + break; + + case 3: + // message + text = getMessage(table, (String) value, row); + toolTipText = t("validator.message.tip", text); + break; + } + + rendererComponent.setText(text); + rendererComponent.setToolTipText(toolTipText); + rendererComponent.setIcon(icon); + return rendererComponent; + } + + public ImageIcon getIcon(NuitonValidatorScope scope) { + return SwingValidatorUtil.getIcon(scope); + } + + public String getMessage(JTable table, String value, int row) { + SwingListValidatorMessageTableModel tableModel = + (SwingListValidatorMessageTableModel) table.getModel(); + SwingListValidatorMessage model = tableModel.getRow(row); + return SwingValidatorUtil.getMessage(model); + } + + public String getFieldName(JTable table, String value, int row) { + SwingListValidatorMessageTableModel tableModel = + (SwingListValidatorMessageTableModel) table.getModel(); + SwingListValidatorMessage model = tableModel.getRow(row); + return SwingValidatorUtil.getFieldName(model, value); + } + + public String getBeanValue(JTable table, int row) { + SwingListValidatorMessageTableModel tableModel = + (SwingListValidatorMessageTableModel) table.getModel(); + SwingListValidatorMessage model = tableModel.getRow(row); + return decorateBean(model.getBean()); + } + + protected String decorateBean(Object bean) { + return bean.toString(); + } +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessageWidget.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessageWidget.java new file mode 100644 index 0000000..8b13b84 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorMessageWidget.java @@ -0,0 +1,294 @@ +package org.nuiton.jaxx.validator.swing; + +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.swing.ComponentMover; +import org.nuiton.jaxx.runtime.swing.ComponentResizer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTitledPanel; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.list.BeanListValidator; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JRootPane; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import javax.swing.KeyStroke; +import javax.swing.ListSelectionModel; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.HierarchyBoundsAdapter; +import java.awt.event.HierarchyEvent; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import static org.nuiton.i18n.I18n.n; +import static org.nuiton.i18n.I18n.t; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + * @since 2.10 + */ +public class SwingListValidatorMessageWidget extends JToggleButton { + + private static final Log log = + LogFactory.getLog(SwingListValidatorMessageWidget.class); + + private static final long serialVersionUID = 1L; + + public static final String CLOSE_DIALOG_ACTION = "closeDialog"; + + protected SwingListValidatorMessageTableModel messageTableModel = new SwingListValidatorMessageTableModel(); + + protected JDialog popup = new JDialog(); + + protected JTable messageTable = new JTable(); + + protected Point popupPosition = null; + + public SwingListValidatorMessageWidget() { + super(SwingUtil.createActionIcon("alert-none")); + setToolTipText(t("validator.messageWidget.alert.none")); + + messageTableModel.addTableModelListener(new TableModelListener() { + + public void tableChanged(TableModelEvent e) { + int alerts = messageTableModel.getRowCount(); + String label; + switch (alerts) { + case 0: + label = n("validator.messageWidget.alert.none"); + break; + case 1: + label = n("validator.messageWidget.alert.one"); + break; + default: + label = n("validator.messageWidget.alert.several"); + } + + NuitonValidatorScope maxScope; + String icon; + if (alerts == 0) { + icon = "alert-none"; + + } else { + maxScope = NuitonValidatorScope.INFO; + for (int i = 0; i < alerts; i++) { + NuitonValidatorScope scope = messageTableModel.getRow(i).getScope(); + int diff = scope.compareTo(maxScope); + if (diff < 0) { + maxScope = scope; + } + } + switch (maxScope) { + case INFO: + icon = "alert-info"; + break; + case WARNING: + icon = "alert-warning"; + break; + default: + icon = "alert-error"; + + } + } + + setToolTipText(t(label, alerts)); + setIcon(SwingUtil.createActionIcon(icon)); + } + }); + + messageTable.setModel(messageTableModel); + messageTable.setRowSelectionAllowed(true); + messageTable.setAutoCreateRowSorter(true); + messageTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); + messageTable.setCellSelectionEnabled(false); + messageTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + messageTable.setFillsViewportHeight(true); + + SwingValidatorUtil.installUI(messageTable, + new SwingListValidatorMessageTableRenderer()); + + JScrollPane scrollPanel = new JScrollPane(messageTable); + scrollPanel.setColumnHeaderView(messageTable.getTableHeader()); + + JXTitledPanel titledPanel = new JXTitledPanel(t("validator.messageWidget.title"), scrollPanel); + popup.add(titledPanel); + popup.setTitle(t("validator.messageWidget.title")); + popup.setSize(800, 300); + popup.setAlwaysOnTop(true); + popup.setUndecorated(true); + + ComponentResizer cr = new ComponentResizer(); + cr.registerComponent(popup); + ComponentMover cm = new ComponentMover(); + cm.setDragInsets(cr.getDragInsets()); + cm.registerComponent(popup); + + popup.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + setSelected(false); + } + + }); + + popup.addComponentListener(new ComponentAdapter() { + + @Override + public void componentMoved(ComponentEvent e) { + Component component = e.getComponent(); + if (component.isShowing()) { + popupPosition = component.getLocationOnScreen(); + } + } + + }); + + addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + if (isSelected()) { + popup.setVisible(true); + } else { + popup.dispose(); + } + } + }); + + addHierarchyBoundsListener(new HierarchyBoundsAdapter() { + + @Override + public void ancestorMoved(HierarchyEvent e) { + if (popupPosition == null && isShowing()) { + Point point = new Point(getLocationOnScreen()); + point.translate(-popup.getWidth() + getWidth(), -popup.getHeight()); + popup.setLocation(point); + } + } + }); + + // add a auto-close action + JRootPane rootPane = popup.getRootPane(); + + KeyStroke shortcutClosePopup = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); + + rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( + shortcutClosePopup, CLOSE_DIALOG_ACTION); + + Action closeAction = new AbstractAction() { + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + popup.dispose(); + setSelected(false); + } + }; + + ImageIcon actionIcon = SwingUtil.createActionIcon("close-dialog"); + closeAction.putValue(Action.SMALL_ICON, actionIcon); + closeAction.putValue(Action.LARGE_ICON_KEY, actionIcon); + closeAction.putValue(Action.ACTION_COMMAND_KEY, "close"); + closeAction.putValue(Action.NAME, "close"); + closeAction.putValue(Action.SHORT_DESCRIPTION, t("validator.messageWidget.closeDialog.tip")); + + rootPane.getActionMap().put(CLOSE_DIALOG_ACTION, closeAction); + + JButton closeButton = new JButton(closeAction); + closeButton.setText(null); + closeButton.setFocusPainted(false); + closeButton.setRequestFocusEnabled(false); + closeButton.setFocusable(false); + + JToolBar jToolBar = new JToolBar(); + jToolBar.setOpaque(false); + jToolBar.add(closeAction); + jToolBar.setBorderPainted(false); + jToolBar.setFloatable(false); + titledPanel.setRightDecoration(jToolBar); + + } + + public void addTableModelListener(TableModelListener listener) { + messageTableModel.addTableModelListener(listener); + } + + public void removeTableModelListener(TableModelListener listener) { + messageTableModel.removeTableModelListener(listener); + } + + public void setDefaultRenderer(TableCellRenderer renderer) { + messageTable.setDefaultRenderer(Object.class, renderer); + } + + /** + * Register a list validator. + * + * @param validator validator to register + * @param dataTable table with data to validate by the validator + * @param dataLocator tool to find data in the data table from the validator messages + */ + public void registerValidator(BeanListValidator validator, + JTable dataTable, + SwingListValidatorDataLocator dataLocator) { + + if (log.isInfoEnabled()) { + log.info("Register validator: " + validator); + } + SwingValidatorUtil.registerListValidator( + validator, + messageTableModel, + dataTable, + messageTable, + dataLocator); + + validator.doValidate(); + } + + /** Clear all the validators. */ + public void clearValidators() { + messageTableModel.clearValidators(); + messageTableModel.clear(); + } + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorTableEditorModelListener.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorTableEditorModelListener.java new file mode 100644 index 0000000..3bcd236 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingListValidatorTableEditorModelListener.java @@ -0,0 +1,149 @@ +package org.nuiton.jaxx.validator.swing; +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.Sets; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.validator.bean.list.BeanListValidator; + +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.table.TableModel; +import java.util.Set; + +/** + * Listens a table model which is the editor of a list of bean, add and remove + * beans to the target validator. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.3 + */ +public class SwingListValidatorTableEditorModelListener<O> implements TableModelListener { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(SwingListValidatorTableEditorModelListener.class); + + private final SwingListValidatorDataLocator<O> dataLocator; + + private BeanListValidator<O> validator; + + public SwingListValidatorTableEditorModelListener( + BeanListValidator<O> validator, + SwingListValidatorDataLocator<O> dataLocator) { + this.dataLocator = dataLocator; + this.validator = validator; + } + + @Override + public void tableChanged(TableModelEvent e) { + + TableModel model = (TableModel) e.getSource(); + + int type = e.getType(); + + int firstRow = e.getFirstRow(); + int lastRow = e.getLastRow(); + + switch (type) { + case TableModelEvent.INSERT: + + onRowsInserted(model, firstRow, lastRow); + + break; + case TableModelEvent.DELETE: + + onRowsDeleted(model); + + break; + case TableModelEvent.UPDATE: + + if (e.getColumn() == TableModelEvent.ALL_COLUMNS + && firstRow == 0 + && lastRow == Integer.MAX_VALUE) { + + // fireTableDataChanged + + onDataChanged(model); + + } + break; + } + } + + protected void onRowsInserted(TableModel model, int firstRow, int lastRow) { + + Set<O> beans = Sets.newHashSet(); + + for (int i = firstRow; i <= lastRow; i++) { + + O bean = dataLocator.locateBean(model, i); + if (log.isDebugEnabled()) { + log.debug("Add a bean to validator " + bean); + } + beans.add(bean); + } + + validator.addAllBeans(beans); + + } + + protected void onRowsDeleted(TableModel model) { + + + // bean are no more existing in editor, must then find out + // which beans must be deleted from all the beans in the validator + + Set<O> beans = Sets.newHashSet(validator.getBeans()); + for (int i = 0, max = model.getRowCount(); i < max; i++) { + O bean = dataLocator.locateBean(model, i); + if (log.isDebugEnabled()) { + log.debug("Remove a bean from validator " + bean); + } + beans.remove(bean); + } + + validator.removeAllBeans(beans); + + } + + protected void onDataChanged(TableModel model) { + + + // remove all beans from validator + validator.removeAllBeans(); + + // add all beans from model + + Set<O> beans = Sets.newHashSet(); + for (int i = 0, max = model.getRowCount(); i < max; i++) { + O bean = dataLocator.locateBean(model, i); + if (log.isDebugEnabled()) { + log.debug("Add a bean to validator " + bean); + } + beans.add(bean); + } + validator.addAllBeans(beans); + + } +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidator.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidator.java new file mode 100644 index 0000000..5a235c1 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidator.java @@ -0,0 +1,485 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import org.nuiton.jaxx.validator.swing.ui.AbstractBeanValidatorUI; +import org.nuiton.jaxx.validator.swing.ui.IconValidationUI; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.jxlayer.JXLayer; +import org.nuiton.validator.NuitonValidator; +import org.nuiton.validator.NuitonValidatorFactory; +import org.nuiton.validator.NuitonValidatorProvider; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.simple.SimpleBeanValidator; + +import javax.swing.JComponent; +import java.awt.Container; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +/** + * La surcharge de {@link SimpleBeanValidator} pour les ui swing + * + * Permet d'ajouter facilement le support de la validation des champs d'un bean + * et de le relier a une interface graphique. Utilise xwork pour la validation + * et JXLayer pour la visualisation. + * + * + * Le mieux pour son integration dans Jaxx est de faire de la generation pour + * force la compilation du code suivant: + * + * <pre> + * myValidor.getBean().get<field>(); + * </pre> + * + * et ceci pour chaque field ajoute a la map fieldRepresentation. De cette facon + * meme si le champs field est en texte on a une verification de son existance a + * la compilation. + * + * + * La representation en tag pourrait etre + * <pre> + * <validator id="myValidator" beanClass="{Personne.class}" + * errorList="$list"> + * <field name="name" component="$name"/> + * <field name="firstName" component="$firstName"/> + * <field name="birthDate" component="$birthDate"/> + * </validator> + * <validator beanClass="{Personne.class}" autoField="true" + * errorList="$list"> + * <fieldRepresentation name="name" component="$lastName"/> + * </validator> + * </pre> + * + * dans le premier exemple on fait un mapping explicite des champs, mais on voit + * que le nom du composant graphique est le meme que celui du champs. Pour + * eviter de longue saisie, il est possible d'utiliser le flag <b>autoField</b> + * qui pour chaque champs du ayant une methode get du bean recherche un + * composant avec cet Id. Il est aussi possible de surcharge un champs + * explicitement comme ici name, dans le cas ou le composant qui porterait ce + * nom serait utilise pour autre chose. + * + * + * Il faut un handler particulier pour ce composant car les attributs + * <b>beanClass</b> et <b>autoField</b> ne sont present que dans le XML jaxx et + * servent a la generation. Il faut aussi prendre en compte les elements + * fieldRepresentation fils du tag validator. + * + * + * Voici ce que pourrait etre le code genere par jaxx + * <pre> + * // declaration du bean + * BeanValidator<beanClass> $myValidator; + * // init du bean + * protected void createMyValidator() { + * $myValidator = new BeanValidator<beanClass>(); + * // genere seulement si autoField = true + * for (Method m : beanClass.getMethod()) { + * if (m.getName().startsWith("get")) { + * String fieldName = m.getName().substring(3).toLowerCase(); + * $myValidator.setFieldRepresentation(fieldName, + * $objectMap.get(fieldName)); + * } + * } + * // pour chaque tag fieldRepresentation + * myValidator.setFieldRepresentation("name", $lastName); + * // si beanClass est specifie et n'est pas Object, on force l'acces au + * champs + * // pour validation a la compilation + * $myValidator.getBean().getName(); + * $objectMap.put("myValidator", $myValidator); + * } + * </pre> + * + * @param <B> le type de bean a valider + * @author Tony Chemit - chemit@codelutin.com + * @version 1.0 + */ +public class SwingValidator<B> extends SimpleBeanValidator<B> { + + /** Logger */ + private static final Log log = LogFactory.getLog(SwingValidator.class); + + private static final Class<? extends AbstractBeanValidatorUI> + DEFAULT_UI_CLASS = IconValidationUI.class; + + /** + * Obtain a new {@link SimpleBeanValidator} for the given parameters. + * + * <b>Note:</b> It will use the default provider of {@link NuitonValidator} + * + * @param type type of bean to validate + * @param context context of validation + * @param scopes authorized scopes (if {@code null}, will use all scopes) + * @param <O> type of bean to validate + * @return the new instanciated {@link SimpleBeanValidator}. + * @throws NullPointerException if type is {@code null} + * @see NuitonValidatorFactory#getDefaultProviderName() + */ + public static <O> SwingValidator<O> newValidator( + Class<O> type, + String context, + NuitonValidatorScope... scopes) throws NullPointerException { + + + // get the provider default name + String providerName = NuitonValidatorFactory.getDefaultProviderName(); + + // get the bean validator with this provider + return newValidator(providerName, + type, + context, + scopes + ); + } + + /** + * Obtain a new {@link SimpleBeanValidator} for the given parameters. + * + * <b>Note:</b> It will use the provider of {@link NuitonValidator} + * defined by the {@code providerName}. + * + * @param providerName name of {@link NuitonValidator} to use + * @param type type of bean to validate + * @param context context of validation + * @param scopes authorized scopes (if {@code null}, will use all scopes) + * @param <O> type of bean to validate + * @return the new instanciated {@link SimpleBeanValidator}. + * @throws NullPointerException if type is {@code null} + * @see NuitonValidatorFactory#getProvider(String) + */ + public static <O> SwingValidator<O> newValidator( + String providerName, + Class<O> type, + String context, + NuitonValidatorScope... scopes) throws NullPointerException { + + Preconditions.checkNotNull(type, + "type parameter can not be null."); + + // get delegate validator provider + NuitonValidatorProvider provider = + NuitonValidatorFactory.getProvider(providerName); + + Preconditions.checkState( + provider != null, + "Could not find provider with name " + providerName); + + // create the new instance of bean validator + + return new SwingValidator<O>( + provider, type, context, scopes); + } + + /** + * permet de faire le lien en un champs du bean et l'objet qui permet de + * l'editer + */ + protected final Map<String, JComponent> fieldRepresentation; + + /** Object servant a contenir la liste des erreurs */ + protected SwingValidatorMessageListModel errorListModel; + + /** Object servant a contenir la liste des erreurs */ + protected SwingValidatorMessageTableModel errorTableModel; + + /** ui renderer class */ + protected Class<? extends AbstractBeanValidatorUI> uiClass; + + public SwingValidator(NuitonValidatorProvider provider, + Class<B> beanClass, + String contextName, + NuitonValidatorScope... filterScopes) { + super(provider, beanClass, contextName, filterScopes); + fieldRepresentation = new HashMap<String, JComponent>(); + } + + public SwingValidator(Class<B> beanClass, + String contextName, + NuitonValidatorScope... filterScopes) { + super(NuitonValidatorFactory.getDefaultProvider(), + beanClass, + contextName, + filterScopes + ); + fieldRepresentation = new HashMap<String, JComponent>(); + } + + public SwingValidator(Class<B> beanClass, String contextName) { + this(beanClass, contextName, NuitonValidatorScope.values()); + } + + /** + * To reload a bean in the validator. + * + * This method is used to reload ui, since some editors could not exist when + * validator is init, so some messages should not be attached to an editor. + */ + public void reloadBean() { + B b = getBean(); + if (log.isInfoEnabled()) { + log.info("Will reload bean : " + b); + } + if (b != null) { + setBean(null); + setBean(b); + } + } + + public JComponent getFieldRepresentation(String fieldname) { + return fieldRepresentation.get(fieldname); + } + + public Class<? extends AbstractBeanValidatorUI> getUiClass() { + return uiClass; + } + + public void setErrorListModel( + SwingValidatorMessageListModel errorListModel) { + this.errorListModel = errorListModel; + if (errorListModel != null) { + // register the validator in the model list + errorListModel.registerValidator(this); + } + } + + public void setErrorTableModel( + SwingValidatorMessageTableModel errorTableModel) { + this.errorTableModel = errorTableModel; + if (errorTableModel != null) { + // register the validator in the model table + errorTableModel.registerValidator(this); + } + } + + public void setUiClass(Class<? extends AbstractBeanValidatorUI> uiClass) { + this.uiClass = uiClass; + } + + @Override + public void setContext(String context) { + String oldContext = getContext(); + + super.setContext(context); + + if (context == null && oldContext == null || + context != null && context.equals(oldContext)) { + + // same context do nothing + return; + } + if (fieldRepresentation != null) { + + // must reinstall ui + installUIs(); + } + } + + /** + * Permet d'indiquer le composant graphique responsable de l'affichage d'un + * attribut du bean + * + * @param fieldname the field name in the bean + * @param c the editor component for the field + */ + public void setFieldRepresentation(String fieldname, JComponent c) { + boolean fieldFound = getDelegate().getEffectiveFields().contains(fieldname); + + if (!fieldFound) { + // no field registred in the validator + if (log.isWarnEnabled()) { + log.warn("the field '" + fieldname + + "' is not defined in validator (no rules on it)"); + } + } else { + if (log.isInfoEnabled()) { + log.info("register field [" + fieldname + "] with component : " + + c.getName() + ); + } + fieldRepresentation.put(fieldname, c); + } + } + + public void setFieldRepresentation( + Map<String, JComponent> fieldRepresentation) { + for (Map.Entry<String, JComponent> e : fieldRepresentation.entrySet()) { + setFieldRepresentation(e.getKey(), e.getValue()); + } + } + + @Override + public SwingValidator<?> getParentValidator() { + return (SwingValidator<?>) super.getParentValidator(); + } + + public void setParentValidator(SwingValidator<?> parentValidator) { + super.setParentValidator(parentValidator); + } + + /** install ui on required components */ + public void installUIs() { + if (fieldRepresentation == null) { + throw new NullPointerException( + "fieldRepresentation is null, must init before " + + "invoking installUIs method..."); + } + + if (uiClass == null) { + // use the default one + uiClass = DEFAULT_UI_CLASS; + } + + // compute reverse map of fieldRepresentation : a same editor can + // reference more than one field + Multimap<JComponent, String> fieldsByEditor = + ArrayListMultimap.create(); + for (Entry<String, JComponent> entry : + fieldRepresentation.entrySet()) { + fieldsByEditor.put(entry.getValue(), entry.getKey()); + } + + for (JComponent editor : fieldsByEditor.keySet()) { + Collection<String> fields = fieldsByEditor.get(editor); + try { + setMessageRepresentation( + editor, + fields, + uiClass + ); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +// for (Entry<String, JComponent> entry : +// fieldRepresentation.entrySet()) { +// try { +// setMessageRepresentation( +// entry.getKey(), +// null, +// entry.getValue(), +// uiClass +// ); +// } catch (Exception e) { +// throw new RuntimeException(e); +// } +// } + } + + protected void setMessageRepresentation( + JComponent c, + Collection<String> fieldnames, + Class<? extends AbstractBeanValidatorUI> uiClass) + throws InvocationTargetException, + IllegalAccessException, + InstantiationException, + NoSuchMethodException { + + Preconditions.checkNotNull(c, "No editor"); + + // ajout du jxlayer sous ce composant + Container container = c.getParent(); + if (container instanceof JXLayer<?>) { + JXLayer jx = (JXLayer<?>) container; + Object oldUI = jx.getUI(); + if (oldUI != null && oldUI instanceof AbstractBeanValidatorUI) { + + // supression de l'ancien layer + removeSimpleBeanValidatorListener((AbstractBeanValidatorUI) oldUI); + } + Constructor<? extends AbstractBeanValidatorUI> cons = + uiClass.getConstructor(Collection.class); + AbstractBeanValidatorUI ui = cons.newInstance(fieldnames); + +// ui.setEnabled(true); + addSimpleBeanValidatorListener(ui); + jx.setUI(ui); + } + } + + @Deprecated + protected void setMessageRepresentation( + String fieldname, + JComponent old, + JComponent c, + Class<? extends AbstractBeanValidatorUI> uiClass) + throws InvocationTargetException, + IllegalAccessException, + InstantiationException, + NoSuchMethodException { + if (old == c) { + // same component, nothing to do + return; + } + + boolean fieldFound = getDelegate().getEffectiveFields().contains(fieldname); + + if (!fieldFound) { + // this case should not appear since fieldName has already been + // check in method addFieldRepresentation + return; + } + if (old != null) { + // suppression du jxlayer sous l'ancien composant + Container container = old.getParent(); + if (container instanceof JXLayer<?>) { + JXLayer<?> jx = (JXLayer<?>) container; + Object ui = jx.getUI(); + if (ui != null && ui instanceof AbstractBeanValidatorUI) { + removeSimpleBeanValidatorListener((AbstractBeanValidatorUI) ui); + } + + jx.setUI(null); + } + } + if (c != null) { + // ajout du jxlayer sous ce composant + Container container = c.getParent(); + if (container instanceof JXLayer<?>) { + JXLayer jx = (JXLayer<?>) container; + Object oldUI = jx.getUI(); + if (oldUI != null && oldUI instanceof AbstractBeanValidatorUI) { + + // supression de l'ancien layer + removeSimpleBeanValidatorListener((AbstractBeanValidatorUI) oldUI); + } + Constructor<? extends AbstractBeanValidatorUI> cons = + uiClass.getConstructor(String.class); + AbstractBeanValidatorUI ui = cons.newInstance(fieldname); + +// ui.setEnabled(true); + addSimpleBeanValidatorListener(ui); + jx.setUI(ui); + } + } + } + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessage.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessage.java new file mode 100644 index 0000000..a1bf0bb --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessage.java @@ -0,0 +1,65 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing; + +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorMessage; + +import javax.swing.JComponent; + +/** + * The object to box a validation message within an swing ui. + * + * @author Tony Chemit - chemit@codelutin.com + * @see SimpleBeanValidatorMessage + * @since 1.3 + */ +public class SwingValidatorMessage extends SimpleBeanValidatorMessage<SwingValidatorMessage> { + + private static final long serialVersionUID = 1L; + + /** the optional field's editor */ + protected JComponent editor; + + public SwingValidatorMessage(SwingValidator<?> validator, + String fieldName, + String message, + NuitonValidatorScope scope, + JComponent editor) { + super(validator, fieldName, message, scope); + this.editor = editor; + } + + public JComponent getEditor() { + return editor; + } + + @Override + public String toString() { + String s = scope + " - " + + (field == null ? message : field + " - " + message); + if (editor != null) { + s = editor.getName() + " : " + s; + } + return s; + } +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageListModel.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageListModel.java new file mode 100644 index 0000000..aad5b55 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageListModel.java @@ -0,0 +1,191 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorEvent; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorListener; + +import javax.swing.AbstractListModel; +import javax.swing.JComponent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * The model of the list of validation's messages + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class SwingValidatorMessageListModel + extends AbstractListModel + implements SimpleBeanValidatorListener { + + private static final long serialVersionUID = 1L; + + /** Logger */ + private static Log log = LogFactory.getLog(SwingValidatorMessageListModel.class); + + /** list of registred validators */ + protected transient List<SwingValidator<?>> validators; + + /** list of messages actual displayed */ + protected List<SwingValidatorMessage> data; + + public SwingValidatorMessageListModel() { + validators = new ArrayList<SwingValidator<?>>(); + data = new ArrayList<SwingValidatorMessage>(); + } + + public boolean isEmpty() { + return getSize() == 0; + } + + public void registerValidator(SwingValidator<?> validator) { + if (validators.contains(validator)) { + throw new IllegalArgumentException( + "the validator " + validator + " is already registred in " + + this); + } + validators.add(validator); + validator.addSimpleBeanValidatorListener(this); + } + + public void clear() { + int i = data.size(); + if (i > 0) { + data.clear(); + fireIntervalRemoved(this, 0, i - 1); + } + } + + @Override + public int getSize() { + return data.size(); + } + + @Override + public Object getElementAt(int index) { + ensureRowIndex(index); + return data.get(index); + } + + @Override + public void onFieldChanged(SimpleBeanValidatorEvent event) { + String[] toDelete = event.getMessagesToDelete(); + String[] toAdd = event.getMessagesToAdd(); + String field = event.getField(); + NuitonValidatorScope scope = event.getScope(); + boolean mustAdd = toAdd != null && toAdd.length > 0; + boolean mustDel = toDelete != null && toDelete.length > 0; + + if (log.isTraceEnabled()) { + log.trace("----------------------------------------------------------"); + log.trace(field + " - (" + getSize() + ") toAdd " + mustAdd); + log.trace(field + " - (" + getSize() + ") toDelete " + mustDel); + } + + SwingValidator<?> validator = (SwingValidator<?>) event.getSource(); + + if (mustDel) { + + // removes datas and notify if no messages to add + removeMessages(validator, field, scope, !mustAdd, toDelete); + } + + if (mustAdd) { + + // add new messages, sort datas and notify + addMessages(validator, field, scope, true, toAdd); + } + } + + protected void ensureRowIndex(int index) throws ArrayIndexOutOfBoundsException { + if (index < -1 || index >= getSize()) { + throw new ArrayIndexOutOfBoundsException( + "the rowIndex was " + index + ", but should be int [0," + + (getSize() - 1) + "]"); + } + } + + protected void addMessages(SwingValidator<?> validator, + String field, + NuitonValidatorScope scope, + boolean sort, + String... messages) { + + JComponent editor = validator.getFieldRepresentation(field); + // add new errors + for (String error : messages) { + SwingValidatorMessage row = new SwingValidatorMessage( + validator, + field, + error, + scope, + editor + ); + data.add(row); + if (!sort) { + fireIntervalAdded(this, data.size() - 1, data.size() - 1); + } + } + + if (sort) { + + // resort datas + Collections.sort(data); + + // notify + fireContentsChanged(this, 0, getSize() - 1); + } + } + + protected void removeMessages(SwingValidator<?> validator, + String field, + NuitonValidatorScope scope, + boolean notify, + String... messages) { + + List<String> messagesToDel = + new ArrayList<String>(Arrays.asList(messages)); + + // do it in reverse mode (only one pass in that way since index + // will stay coherent while removing them) + + for (int i = getSize() - 1; i > -1; i--) { + SwingValidatorMessage error = data.get(i); + if (error.getValidator().equals(validator) && + error.getScope() == scope && + error.getField().equals(field) && + messagesToDel.contains(error.getMessage())) { + // remove the message + data.remove(i); + if (notify) { + fireIntervalRemoved(this, i, i); + } + } + } + } +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageListMouseListener.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageListMouseListener.java new file mode 100644 index 0000000..4548da5 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageListMouseListener.java @@ -0,0 +1,90 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JComponent; +import javax.swing.JList; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * A mouse listener to put on a {@link JList} with a {@link + * SwingValidatorMessageListModel} as a model. + * + * When a double click occurs, find the selected error in model and then focus + * to the associated component of error. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class SwingValidatorMessageListMouseListener extends MouseAdapter { + + /** Logger */ + static private Log log = + LogFactory.getLog(SwingValidatorMessageListMouseListener.class); + + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + if (e.getClickCount() == 2) { + + SwingValidatorMessage entry = getSelectedMessage(e); + if (entry == null) { + // no entry found + return; + } + JComponent component = entry.getEditor(); + if (component != null) { + component.requestFocus(); + } + } + } + + protected SwingValidatorMessage getSelectedMessage(MouseEvent e) { + JList list = (JList) e.getSource(); + if (!(list.getModel() instanceof SwingValidatorMessageListModel)) { + if (log.isWarnEnabled()) { + log.warn("model must be a " + + SwingValidatorMessageListModel.class + ", but was " + + list.getModel()); + } + return null; + } + + SwingValidatorMessageListModel model = + (SwingValidatorMessageListModel) list.getModel(); + int index = list.getSelectionModel().getMinSelectionIndex(); + if (index == -1) { + // nothing is selected + return null; + } + SwingValidatorMessage entry = + (SwingValidatorMessage) model.getElementAt(index); + if (log.isDebugEnabled()) { + log.debug("selected index: " + index + " : error: " + entry); + } + return entry; + } + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageListRenderer.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageListRenderer.java new file mode 100644 index 0000000..2e3f6e5 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageListRenderer.java @@ -0,0 +1,128 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing; + +import org.nuiton.validator.NuitonValidatorScope; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JList; +import java.awt.Component; + +import static org.nuiton.i18n.I18n.t; + +/** + * A simple render of a table of validator's messages, says a table that use a + * {@link SwingValidatorMessageTableModel} model. + * + * @author Tony Chemit - chemit@codelutin.com + * @see SwingValidatorMessageTableModel + * @since 1.3 + */ +public class SwingValidatorMessageListRenderer extends DefaultListCellRenderer { + + private static final long serialVersionUID = 1L; + + protected String format = "%1$-20s - %2$s"; + + protected String formatTip = "%1$-20s - %2$-20s : %3$s"; + + public SwingValidatorMessageListRenderer() { + } + + public SwingValidatorMessageListRenderer(String format) { + this.format = format; + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + @Override + public Component getListCellRendererComponent(JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) { + + JLabel rendererComponent = (JLabel) + super.getListCellRendererComponent( + list, + value, + index, + isSelected, + cellHasFocus + ); + + SwingValidatorMessage model = (SwingValidatorMessage) value; + + // scope + ImageIcon icon = SwingValidatorUtil.getIcon(model.getScope()); + + // field name + String fieldName = getFieldName( + list, + model.getField(), + index + ); + + // message + String message = getMessage(model); + + // text to display + String text = String.format(format, fieldName, message); + + String label = t(model.getScope().getLabel()); + String tmp = t("validator.scope.tip", label); + String tmp2 = t("validator.field.tip", fieldName); + + String tooltTipText = String.format(formatTip, tmp, tmp2, message); + + + rendererComponent.setText(text); + rendererComponent.setToolTipText(tooltTipText); + rendererComponent.setIcon(icon); + + return rendererComponent; + } + + public ImageIcon getIcon(NuitonValidatorScope scope) { + return SwingValidatorUtil.getIcon(scope); + } + + public String getMessage(SwingValidatorMessage model) { + return SwingValidatorUtil.getMessage(model); + } + + public String getFieldName(JList list, String value, int row) { + SwingValidatorMessageListModel tableModel = + (SwingValidatorMessageListModel) list.getModel(); + SwingValidatorMessage model = + (SwingValidatorMessage) tableModel.getElementAt(row); + return SwingValidatorUtil.getFieldName(model, value); + } +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageTableModel.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageTableModel.java new file mode 100644 index 0000000..8341a84 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageTableModel.java @@ -0,0 +1,360 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing; + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorEvent; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorListener; + +import javax.swing.JComponent; +import javax.swing.table.AbstractTableModel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * The model of the table of errors. + * + * The model listens validators messages and update his internal model from it. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.3 + */ +public class SwingValidatorMessageTableModel + extends AbstractTableModel + implements SimpleBeanValidatorListener { + + private static final long serialVersionUID = 1L; + + /** Logger */ + private static Log log = + LogFactory.getLog(SwingValidatorMessageTableModel.class); + + public static final String[] columnNames = + {"validator.scope", "validator.field", "validator.message"}; + + public static final Class<?>[] columnClasses = + {NuitonValidatorScope.class, String.class, String.class}; + + /** list of registred validators */ + protected transient List<SwingValidator<?>> validators; + + /** list of messages actual displayed */ + protected List<SwingValidatorMessage> data; + + public SwingValidatorMessageTableModel() { + validators = new ArrayList<SwingValidator<?>>(); + data = new ArrayList<SwingValidatorMessage>(); + } + + /** + * Register a validator for this model. + * + * + * Note: a validator can not be register twice in the same model. + * + * @param validator the validator to register + */ + public void registerValidator(SwingValidator<?> validator) { + if (validators.contains(validator)) { + throw new IllegalArgumentException( + "the validator " + validator + " is already registred in " + + this); + } + validators.add(validator); + validator.addSimpleBeanValidatorListener(this); + } + + public void addMessages(SwingValidator<?> validator, + String fieldName, + NuitonValidatorScope scope, + String... messages) { + addMessages(validator, fieldName, scope, true, messages); + } + + public void addMessages(JComponent editor, + String fieldName, + NuitonValidatorScope scope, + String... messages) { + addMessages(editor, fieldName, scope, true, messages); + } + + public void removeMessages(JComponent editor, NuitonValidatorScope scope) { + + if (editor == null) { + // no editor, so nothing to do + return; + } + // do it in reverse mode (only one pass in that way since index + // will stay coherent while removing them) + + for (int i = getRowCount() - 1; i > -1; i--) { + SwingValidatorMessage error = data.get(i); + if (editor.equals(error.getEditor()) && + (scope == null || error.getScope() == scope)) { + // remove the message + data.remove(i); + fireTableRowsDeleted(i, i); + } + } + } + + public void removeMessages(SwingValidator<?> validator, + String fieldName, + NuitonValidatorScope scope, + String... messages) { + removeMessages(validator, fieldName, scope, true, messages); + } + + public void removeMessages(JComponent editor, + String fieldName, + NuitonValidatorScope scope) { + removeMessages(editor, fieldName, scope, true); + } + + public void clear() { + int i = data.size(); + if (i > 0) { + data.clear(); + fireTableRowsDeleted(0, i - 1); + } + } + + public void clearValidators() { + for (SwingValidator<?> v : validators) { + v.removeSimpleBeanValidatorListener(this); + } + validators.clear(); + } + + /** + * Obtain the message for a given row. + * + * @param rowIndex the row index + * @return the message for the given row index + */ + public SwingValidatorMessage getRow(int rowIndex) { + SwingUtil.ensureRowIndex(this, rowIndex); + return data.get(rowIndex); + } + + @Override + public boolean isCellEditable(int row, int column) { + // cells are never editable in this model + return false; + } + + @Override + public Class<?> getColumnClass(int columnIndex) { + SwingUtil.ensureColumnIndex(this, columnIndex); + return columnClasses[columnIndex]; + } + + @Override + public String getColumnName(int column) { + SwingUtil.ensureColumnIndex(this, column); + return columnNames[column]; + } + + @Override + public void onFieldChanged(SimpleBeanValidatorEvent event) { + String[] toDelete = event.getMessagesToDelete(); + String[] toAdd = event.getMessagesToAdd(); + String field = event.getField(); + NuitonValidatorScope scope = event.getScope(); + boolean mustAdd = toAdd != null && toAdd.length > 0; + boolean mustDel = toDelete != null && toDelete.length > 0; + + if (log.isTraceEnabled()) { + log.trace("----------------------------------------------------------"); + log.trace(field + " - (" + getRowCount() + ") toAdd " + mustAdd); + log.trace(field + " - (" + getRowCount() + ") toDelete " + mustDel); + } + + SwingValidator<?> validator = (SwingValidator<?>) event.getSource(); + + if (mustDel) { + + // removes datas and notify if no messages to add + removeMessages(validator, field, scope, !mustAdd, toDelete); + } + + if (mustAdd) { + + // add new messages, sort datas and notify + addMessages(validator, field, scope, true, toAdd); + } + } + + @Override + public int getRowCount() { + return data.size(); + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + SwingUtil.ensureColumnIndex(this, columnIndex); + SwingUtil.ensureRowIndex(this, rowIndex); + + SwingValidatorMessage row = data.get(rowIndex); + if (columnIndex == 0) { + // the icon + return row.getScope(); + } + if (columnIndex == 1) { + // the field + return row.getField(); + } + if (columnIndex == 2) { + // the message + return row.getMessage(); + } + + // should never come here + return null; + } + + protected void addMessages(SwingValidator<?> validator, + String fieldName, + NuitonValidatorScope scope, + boolean sort, + String... messages) { + + JComponent editor = validator == null ? + null : + validator.getFieldRepresentation(fieldName); + // add new errors + for (String error : messages) { + SwingValidatorMessage row = + new SwingValidatorMessage( + validator, + fieldName, + error, + scope, + editor + ); + data.add(row); + if (!sort) { + fireTableRowsInserted(data.size() - 1, data.size() - 1); + } + } + + if (sort) { + + // resort datas + Collections.sort(data); + + // notify + fireTableDataChanged(); + } + } + + protected void addMessages(JComponent editor, + String fieldName, + NuitonValidatorScope scope, + boolean sort, + String... messages) { + + // add new errors + for (String error : messages) { + SwingValidatorMessage row = + new SwingValidatorMessage( + null, + fieldName, + error, + scope, + editor + ); + data.add(row); + if (!sort) { + fireTableRowsInserted(data.size() - 1, data.size() - 1); + } + } + + if (sort) { + + // resort datas + Collections.sort(data); + + // notify + fireTableDataChanged(); + } + } + + protected void removeMessages(SwingValidator<?> validator, + String fieldName, + NuitonValidatorScope scope, + boolean notify, + String... messages) { + + List<String> messagesToDel = + new ArrayList<String>(Arrays.asList(messages)); + + // do it in reverse mode (only one pass in that way since index + // will stay coherent while removing them) + + for (int i = getRowCount() - 1; i > -1; i--) { + SwingValidatorMessage error = data.get(i); + if (validator.equals(error.getValidator()) && + error.getScope() == scope && + error.getField().equals(fieldName) && + messagesToDel.contains(error.getMessage())) { + // remove the message + data.remove(i); + if (notify) { + fireTableRowsDeleted(i, i); + } + } + } + } + + protected void removeMessages(JComponent editor, + String fieldName, + NuitonValidatorScope scope, + boolean notify) { + + // do it in reverse mode (only one pass in that way since index + // will stay coherent while removing them) + + for (int i = getRowCount() - 1; i > -1; i--) { + SwingValidatorMessage error = data.get(i); + if (editor.equals(error.getEditor()) && + (scope == null || error.getScope() == scope) && + error.getField().equals(fieldName)) { + // remove the message + data.remove(i); + if (notify) { + fireTableRowsDeleted(i, i); + } + } + } + } +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageTableMouseListener.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageTableMouseListener.java new file mode 100644 index 0000000..4ad921c --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageTableMouseListener.java @@ -0,0 +1,126 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JTable; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +/** + * A mouse listener to put on a {@link JList} with a {@link + * SwingValidatorMessageTableModel} as a model. + * + * When a double click occurs, find the selected error in model and then focus + * to the associated component of error. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class SwingValidatorMessageTableMouseListener extends MouseAdapter { + + /** Logger */ + private static Log log = + LogFactory.getLog(SwingValidatorMessageTableMouseListener.class); + + public static final String HIGHLIGHT_ERROR_PROPERTY = "highlightError"; + + /** delgate property change support */ + protected PropertyChangeSupport pcs; + + public SwingValidatorMessageTableMouseListener() { + pcs = new PropertyChangeSupport(this); + } + + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + if (e.getClickCount() == 2) { + + SwingValidatorMessage entry = getSelectedMessage(e); + if (entry == null) { + // no entry found + return; + } + JComponent component = entry.getEditor(); + if (component != null) { + pcs.firePropertyChange(HIGHLIGHT_ERROR_PROPERTY, null, entry); + if (component.isVisible()) { + component.requestFocus(); + } + } + } + } + + + protected SwingValidatorMessage getSelectedMessage(MouseEvent e) { + JTable table = (JTable) e.getSource(); + if (!(table.getModel() instanceof SwingValidatorMessageTableModel)) { + if (log.isWarnEnabled()) { + log.warn("model must be a " + + SwingValidatorMessageTableModel.class + + ", but was " + table.getModel()); + } + return null; + } + + SwingValidatorMessageTableModel model = + (SwingValidatorMessageTableModel) table.getModel(); + int index = table.getSelectionModel().getMinSelectionIndex(); + if (index == -1) { + // nothing is selected + return null; + } + if (table.getRowSorter() != null) { + index = table.getRowSorter().convertRowIndexToModel(index); + } + SwingValidatorMessage entry = model.getRow(index); + if (log.isDebugEnabled()) { + log.debug("selected index: " + index + " : error: " + entry); + } + return entry; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageTableRenderer.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageTableRenderer.java new file mode 100644 index 0000000..41572b6 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageTableRenderer.java @@ -0,0 +1,117 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing; + +import org.nuiton.validator.NuitonValidatorScope; + +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import java.awt.Component; + +import static org.nuiton.i18n.I18n.t; + +/** + * A simple render of a table of validator's messages, says a table that use + * a {@link SwingValidatorMessageTableModel} model. + * + * @author Tony Chemit - chemit@codelutin.com + * @see SwingValidatorMessageTableModel + * @since 1.3 + */ +public class SwingValidatorMessageTableRenderer extends DefaultTableCellRenderer { + + private static final long serialVersionUID = 1L; + + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, + int column) { + JLabel rendererComponent = (JLabel) + super.getTableCellRendererComponent( + table, + value, + isSelected, + hasFocus, + row, + column + ); + + ImageIcon icon = null; + String text = null; + String toolTipText = null; + +// column = table.convertColumnIndexToModel(column); +// if (table.getRowSorter() != null) { +// row = table.getRowSorter().convertRowIndexToModel(row); +// } + + switch (column) { + case 0: + // scope + NuitonValidatorScope scope = (NuitonValidatorScope) value; + icon = SwingValidatorUtil.getIcon(scope); + String label = t(scope.getLabel()); + toolTipText = t("validator.scope.tip", label); + break; + + case 1: + // field name + text = getFieldName(table, (String) value, row); + toolTipText = t("validator.field.tip", text); + break; + + case 2: + // message + text = getMessage(table, (String) value, row); + toolTipText = t("validator.message.tip", text); + break; + } + + rendererComponent.setText(text); + rendererComponent.setToolTipText(toolTipText); + rendererComponent.setIcon(icon); + return rendererComponent; + } + + public ImageIcon getIcon(NuitonValidatorScope scope) { + return SwingValidatorUtil.getIcon(scope); + } + + public String getMessage(JTable table, String value, int row) { + SwingValidatorMessageTableModel tableModel = + (SwingValidatorMessageTableModel) table.getModel(); + SwingValidatorMessage model = tableModel.getRow(row); + return SwingValidatorUtil.getMessage(model); + } + + public String getFieldName(JTable table, String value, int row) { + SwingValidatorMessageTableModel tableModel = + (SwingValidatorMessageTableModel) table.getModel(); + SwingValidatorMessage model = tableModel.getRow(row); + return SwingValidatorUtil.getFieldName(model, value); + } +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageWidget.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageWidget.java new file mode 100644 index 0000000..3344961 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorMessageWidget.java @@ -0,0 +1,279 @@ + +package org.nuiton.jaxx.validator.swing; + +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.swing.ComponentMover; +import org.nuiton.jaxx.runtime.swing.ComponentResizer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTitledPanel; +import org.nuiton.validator.NuitonValidatorScope; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JRootPane; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import javax.swing.KeyStroke; +import javax.swing.ListSelectionModel; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import java.awt.Component; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.HierarchyBoundsAdapter; +import java.awt.event.HierarchyEvent; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import static org.nuiton.i18n.I18n.t; +import static org.nuiton.i18n.I18n.n; + +/** + * Button which opens a popup containing a table with the errors found + * by registered validators. + * + * @author Kevin Morin - morin@codelutin.com + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.10 + */ +public class SwingValidatorMessageWidget extends JToggleButton { + + private static final Log log = + LogFactory.getLog(SwingValidatorMessageWidget.class); + + private static final long serialVersionUID = 1L; + + public static final String CLOSE_DIALOG_ACTION = "closeDialog"; + + protected SwingValidatorMessageTableModel errorTableModel = new SwingValidatorMessageTableModel(); + + protected JDialog popup = new JDialog(); + + protected JTable errorTable = new JTable(); + + protected Point popupPosition = null; + + public SwingValidatorMessageWidget() { + super(SwingUtil.createActionIcon("alert-none")); + setToolTipText(t("validator.messageWidget.alert.none")); + + errorTableModel.addTableModelListener(new TableModelListener() { + + public void tableChanged(TableModelEvent e) { + int alerts = errorTableModel.getRowCount(); + String label; + switch (alerts) { + case 0: + label = n("validator.messageWidget.alert.none"); + break; + case 1: + label = n("validator.messageWidget.alert.one"); + break; + default: + label = n("validator.messageWidget.alert.several"); + } + + NuitonValidatorScope maxScope; + String icon; + if (alerts == 0) { + icon = "alert-none"; + + } else { + maxScope = NuitonValidatorScope.INFO; + for (int i = 0; i < alerts; i++) { + NuitonValidatorScope scope = errorTableModel.getRow(i).getScope(); + int diff = scope.compareTo(maxScope); + if (diff < 0) { + maxScope = scope; + } + } + switch (maxScope) { + case INFO: + icon = "alert-info"; + break; + case WARNING: + icon = "alert-warning"; + break; + default: + icon = "alert-error"; + + } + } + + setToolTipText(t(label, alerts)); + setIcon(SwingUtil.createActionIcon(icon)); + } + }); + + errorTable.setModel(errorTableModel); + errorTable.setRowSelectionAllowed(true); + errorTable.setAutoCreateRowSorter(true); + errorTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); + errorTable.setCellSelectionEnabled(false); + errorTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + errorTable.setFillsViewportHeight(true); + + SwingValidatorUtil.installUI(errorTable, + new SwingValidatorMessageTableRenderer()); + + JScrollPane scrollPanel = new JScrollPane(errorTable); + scrollPanel.setColumnHeaderView(errorTable.getTableHeader()); + + JXTitledPanel titledPanel = new JXTitledPanel(t("validator.messageWidget.title"), scrollPanel); + popup.add(titledPanel); + popup.setTitle(t("validator.messageWidget.title")); + popup.setSize(800, 300); + popup.setAlwaysOnTop(true); + popup.setUndecorated(true); + + ComponentResizer cr = new ComponentResizer(); + cr.registerComponent(popup); + ComponentMover cm = new ComponentMover(); + cm.setDragInsets(cr.getDragInsets()); + cm.registerComponent(popup); + + popup.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + setSelected(false); + } + + }); + + popup.addComponentListener(new ComponentAdapter() { + + @Override + public void componentMoved(ComponentEvent e) { + Component component = e.getComponent(); + if (component.isShowing()) { + popupPosition = component.getLocationOnScreen(); + } + } + + }); + + addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + if (isSelected()) { + popup.setVisible(true); + } else { + popup.dispose(); + } + } + }); + + addHierarchyBoundsListener(new HierarchyBoundsAdapter() { + + @Override + public void ancestorMoved(HierarchyEvent e) { + if (popupPosition == null && isShowing()) { + Point point = new Point(getLocationOnScreen()); + point.translate(-popup.getWidth() + getWidth(), -popup.getHeight()); + popup.setLocation(point); + } + } + }); + + // add a auto-close action + JRootPane rootPane = popup.getRootPane(); + + KeyStroke shortcutClosePopup = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); + + rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( + shortcutClosePopup, CLOSE_DIALOG_ACTION); + + Action closeAction = new AbstractAction() { + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + popup.dispose(); + setSelected(false); + } + }; + + ImageIcon actionIcon = SwingUtil.createActionIcon("close-dialog"); + closeAction.putValue(Action.SMALL_ICON, actionIcon); + closeAction.putValue(Action.LARGE_ICON_KEY, actionIcon); + closeAction.putValue(Action.ACTION_COMMAND_KEY, "close"); + closeAction.putValue(Action.NAME, "close"); + closeAction.putValue(Action.SHORT_DESCRIPTION, t("validator.messageWidget.closeDialog.tip")); + + rootPane.getActionMap().put(CLOSE_DIALOG_ACTION, closeAction); + + JButton closeButton = new JButton(closeAction); + closeButton.setText(null); + closeButton.setFocusPainted(false); + closeButton.setRequestFocusEnabled(false); + closeButton.setFocusable(false); + + JToolBar jToolBar = new JToolBar(); + jToolBar.setOpaque(false); + jToolBar.add(closeAction); + jToolBar.setBorderPainted(false); + jToolBar.setFloatable(false); + titledPanel.setRightDecoration(jToolBar); + + } + + public void addTableModelListener(TableModelListener listener) { + errorTableModel.addTableModelListener(listener); + } + + public void removeTableModelListener(TableModelListener listener) { + errorTableModel.removeTableModelListener(listener); + } + + /** + * Registers a validator. + * + * @param validator + */ + public void registerValidator(SwingValidator validator) { + errorTableModel.registerValidator(validator); + validator.reloadBean(); + } + + /** Clears all the validators. */ + public void clearValidators() { + errorTableModel.clearValidators(); + errorTableModel.clear(); + } + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorUtil.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorUtil.java new file mode 100644 index 0000000..197042e --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/SwingValidatorUtil.java @@ -0,0 +1,762 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import org.nuiton.jaxx.runtime.JAXXObject; +import org.nuiton.jaxx.validator.JAXXValidator; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.validator.swing.meta.Validator; +import org.nuiton.jaxx.validator.swing.meta.ValidatorField; +import org.nuiton.jaxx.validator.swing.unified.UnifiedValidatorMessage; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTable; +import org.jdesktop.swingx.decorator.ColorHighlighter; +import org.nuiton.util.ReflectUtil; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.list.BeanListValidator; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorMessage; +import org.nuiton.validator.bean.simple.SimpleBeanValidators; + +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JTable; +import javax.swing.RowSorter; +import javax.swing.SortOrder; +import java.awt.Color; +import java.awt.event.MouseListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +import static org.nuiton.i18n.I18n.n; + +/** + * The helper class for swing validation module. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class SwingValidatorUtil extends SimpleBeanValidators { + + /** Logger */ + static private final Log log = LogFactory.getLog(SwingValidatorUtil.class); + + protected static EnumMap<NuitonValidatorScope, ImageIcon> icons; + + protected static EnumMap<NuitonValidatorScope, Color> colors; + + public static EnumMap<NuitonValidatorScope, ImageIcon> getIcons() { + if (icons == null) { + icons = new EnumMap<NuitonValidatorScope, ImageIcon>(NuitonValidatorScope.class); + icons.put(NuitonValidatorScope.FATAL, SwingUtil.createImageIcon("fatal.png")); + icons.put(NuitonValidatorScope.ERROR, SwingUtil.createImageIcon("error.png")); + icons.put(NuitonValidatorScope.WARNING, SwingUtil.createImageIcon("warning.png")); + icons.put(NuitonValidatorScope.INFO, SwingUtil.createImageIcon("info.png")); + } + return icons; + } + + public static EnumMap<NuitonValidatorScope, Color> getColors() { + if (colors == null) { + colors = new EnumMap<NuitonValidatorScope, Color>(NuitonValidatorScope.class); + colors.put(NuitonValidatorScope.FATAL, Color.MAGENTA); + colors.put(NuitonValidatorScope.ERROR, Color.RED); + colors.put(NuitonValidatorScope.WARNING, Color.YELLOW); + colors.put(NuitonValidatorScope.INFO, Color.GREEN); + } + return colors; + } + + public static Color getColor(NuitonValidatorScope scope) { + return scope == null ? null : getColors().get(scope); + } + + public static ImageIcon getIcon(NuitonValidatorScope scope) { + return scope == null ? null : getIcons().get(scope); + } + + public static ImageIcon getFatalIcon() { + return getIcons().get(NuitonValidatorScope.FATAL); + } + + public static ImageIcon getErrorIcon() { + return getIcons().get(NuitonValidatorScope.ERROR); + } + + public static ImageIcon getWarningIcon() { + return getIcons().get(NuitonValidatorScope.WARNING); + } + + public static ImageIcon getInfoIcon() { + return getIcons().get(NuitonValidatorScope.INFO); + } + + protected SwingValidatorUtil() { + // no instance + } + + public static <O> SwingValidator<O> newValidator(Class<O> type, + String context) { + +// if (BeanValidatorFactory.isDefaultCreator()) { +// +// // set the swing bean validator creator +// BeanValidatorFactory.setCreator(new DefaultSwingValidatorCreator()); +// } + return SwingValidator.newValidator(type, context); + } + + /** + * To install all the stuff for validation on a {@link JAXXValidator} ui. + * + * This method is called after validators has beeen detected in the ui (via + * the method {@link #detectValidators(JAXXValidator)}).. + * + * It will first find and register all validator field via the method + * {@link JAXXValidator#registerValidatorFields()}, then for each + * validators it will install ui for it (says connect validator to ui via layers) + * and will reload attached bean to make visible bean validation state on ui. + * + * This method is always inovked by a generated jaxx-validator file at the + * end of the {@code $completeSetup} method. + * + * @param ui the validator ui to init. + */ + public static void installUI(JAXXValidator ui) { + + // first install fields with validation + ui.registerValidatorFields(); + +// detectValidatorFields(ui); + + // for each validator install uis + reload bean + + List<String> validatorIds = ui.getValidatorIds(); + for (String validatorId : validatorIds) { + SwingValidator<?> validator = ui.getValidator(validatorId); + + // install uis + validator.installUIs(); + + // reload attached bean (to see validation on uis) + validator.reloadBean(); + } + } + + /** + * Given a {@link JAXXValidator} ui, detects on it all the validators it + * contains. + * + * A validator is detected from the annotation {@link Validator} placed on + * his field. + * + * This method is always inovked by a generated jaxx-validator file at the + * end of the {@code $completeSetup} method. + * + * @param ui the ui where to seek for validators. + * @return the list of ids of validators found on the given ui + */ + public static List<String> detectValidators(JAXXValidator ui) { + List<String> validatorIds = new ArrayList<String>(); + Map<Field, Validator> validators = ReflectUtil.getFieldAnnotation( + ui.getClass(), + Validator.class, + true + ); + + for (Map.Entry<Field, Validator> entry : validators.entrySet()) { + Field field = entry.getKey(); + Validator annotation = entry.getValue(); + String validatorId = annotation.validatorId(); + validatorIds.add(validatorId); + if (log.isInfoEnabled()) { + log.info("Detect validator [" + annotation.validatorId() + + "] on field " + field.getName()); + } + } + return Collections.unmodifiableList(validatorIds); + } + + /** + * Detects on a {@link JAXXValidator} ui all the validator fields it + * contains. + * + * A validator field is detected via the annotation placed on his field or + * his getter (in cas of inheritance). + * + * Each field found will be registred to his corresponding validator via + * the method {@link SwingValidator#setFieldRepresentation(String, JComponent)}. + * + * By default, this method is invoked in the generated method + * {@link JAXXValidator#registerValidatorFields()} by a generated + * jaxx-validator file. + * + * @param ui the ui to seek + */ + public static void detectValidatorFields(JAXXValidator ui) { + + Multimap<JComponent, ValidatorField> editors = getValidatorEditors(ui); + + try { + + for (String validatorId : ui.getValidatorIds()) { + SwingValidator<?> validator = ui.getValidator(validatorId); + + for (Map.Entry<JComponent, ValidatorField> entry : + editors.entries()) { + ValidatorField fieldAnnotation = entry.getValue(); + JComponent editor = entry.getKey(); + if (!validatorId.equals(fieldAnnotation.validatorId())) { + + // not good validator, skip this field + continue; + } + String[] propertyNames = fieldAnnotation.propertyName(); + for (String propertyName : propertyNames) { + if (log.isInfoEnabled()) { + log.info("Detects for validator [" + validatorId + + "] property " + propertyName + + " for editor " + fieldAnnotation.editorName()); + } + validator.setFieldRepresentation(propertyName, editor); + } + } + } + + } finally { + + editors.clear(); + } + } + + /** + * Prepare the ui where to display the validators messages. + * + * @param errorTable the table where to display validators messages + * @param render renderer to use + */ + public static void installUI(JTable errorTable, + SwingValidatorMessageTableRenderer render) { + errorTable.setDefaultRenderer(Object.class, render); + errorTable.getRowSorter().setSortKeys( + Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); + SwingUtil.setI18nTableHeaderRenderer( + errorTable, + n("validator.scope.header"), + n("validator.scope.header.tip"), + n("validator.field.header"), + n("validator.field.header.tip"), + n("validator.message.header"), + n("validator.message.header.tip")); + // register a single 'goto widget error' mouse listener on errorTable + registerErrorTableMouseListener(errorTable); + SwingUtil.fixTableColumnWidth(errorTable, 0, 25); + } + + /** + * Prepare the ui where to display the validators messages. + * + * @param errorTable the table where to display simpleBean validators messages + * @param render renderer to use + * @since 2.6.23 + */ + public static void installUI(JTable errorTable, + SimpleBeanValidatorMessageTableRenderer render) { + errorTable.setDefaultRenderer(Object.class, render); + errorTable.getRowSorter().setSortKeys( + Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); + SwingUtil.setI18nTableHeaderRenderer( + errorTable, + n("validator.scope.header"), + n("validator.scope.header.tip"), + n("validator.field.header"), + n("validator.field.header.tip"), + n("validator.message.header"), + n("validator.message.header.tip")); + SwingUtil.fixTableColumnWidth(errorTable, 0, 25); + } + + /** + * Prepare the ui where to display the validators messages. + * + * @param errorTable the table where to display validators messages + * @param render renderer to use + * @since 2.5.3 + */ + public static void installUI(JTable errorTable, + SwingListValidatorMessageTableRenderer render) { + + errorTable.setDefaultRenderer(Object.class, render); + errorTable.getRowSorter().setSortKeys( + Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); + SwingUtil.setI18nTableHeaderRenderer( + errorTable, + n("validator.scope.header"), + n("validator.scope.header.tip"), + n("validator.bean.header"), + n("validator.bean.header.tip"), + n("validator.field.header"), + n("validator.field.header.tip"), + n("validator.message.header"), + n("validator.message.header.tip")); + SwingUtil.fixTableColumnWidth(errorTable, 0, 25); + + } + + /** + * Prepare the ui where to display the validators messages. + * + * @param errorTableModel + * @param errorTable the table where to display validators messages + * @since 2.5.3 + */ + public static <O> void registerListValidator(BeanListValidator<O> validator, + SwingListValidatorMessageTableModel errorTableModel, + JTable dataTable, + JTable errorTable, + SwingListValidatorDataLocator<O> dataLocator) { + + // register the validator to the error table model + errorTableModel.registerValidator(validator); + + + // add click listener to go to cell + errorTable.addMouseListener(new SwingListValidatorMessageTableMouseListener( + dataTable, + dataLocator + )); + + // listen on editor model to add / remove bean into validator + dataTable.getModel().addTableModelListener( + new SwingListValidatorTableEditorModelListener<O>(validator, dataLocator)); + } + + /** + * Add hightlighters on the editor of beans. + * + * @param validator the validator where to find bean states + * @param editor the editor of beans + * @param dataLocator the data locator + * @param scopes scopes to hightlight + * @param <O> type of bean to validate + * @since 2.5.3 + */ + public static <O> void addHightLighterOnEditor(BeanListValidator<O> validator, + JXTable editor, + SwingListValidatorDataLocator<O> dataLocator, + NuitonValidatorScope... scopes) { + + for (NuitonValidatorScope scope : scopes) { + + SwingListValidatorHighlightPredicate<O> predicate = SwingListValidatorHighlightPredicate.newPredicate( + scope, + validator, dataLocator + ); + + ColorHighlighter highlighter = new ColorHighlighter(predicate); + highlighter.setBackground(SwingValidatorUtil.getColor(scope)); + editor.addHighlighter(highlighter); + } + } + + /** + * Register for a given validator list ui a validator mouse listener. + * + * Note: there is only one listener registred for a given list model, so + * invoking this method tiwce or more will have no effect. + * + * @param list the validation ui list + * @return the listener instanciate or found + * @see SwingValidatorMessageListMouseListener + */ + public static SwingValidatorMessageListMouseListener registerErrorListMouseListener(JList list) { + SwingValidatorMessageListMouseListener listener = + getErrorListMouseListener(list); + + if (listener != null) { + return listener; + } + listener = new SwingValidatorMessageListMouseListener(); + if (log.isDebugEnabled()) { + log.debug(listener.toString()); + } + list.addMouseListener(listener); + return listener; + } + + /** + * Register for a given validator table ui a validator mouse listener + * + * Note: there is onlt one listener registred for a givne table model, so + * invokin this method twice or more will have no effect. + * + * @param table the validator table ui + * @return the listener instanciate or found + * @see SwingValidatorMessageTableMouseListener + */ + public static SwingValidatorMessageTableMouseListener registerErrorTableMouseListener(JTable table) { + SwingValidatorMessageTableMouseListener listener = + getErrorTableMouseListener(table); + + if (listener != null) { + return listener; + } + listener = new SwingValidatorMessageTableMouseListener(); + if (log.isDebugEnabled()) { + log.debug(listener.toString()); + } + table.addMouseListener(listener); + return listener; + } + + /** + * @param list the validator list ui + * @return the validator list mouse listener, or <code>null</code> if not + * found + * @see SwingValidatorMessageListMouseListener + */ + public static SwingValidatorMessageListMouseListener getErrorListMouseListener(JList list) { + if (list != null) { + for (MouseListener listener : list.getMouseListeners()) { + if (listener instanceof SwingValidatorMessageListMouseListener) { + return (SwingValidatorMessageListMouseListener) listener; + } + } + } + return null; + } + + /** + * @param table the validator table ui + * @return the validator table mouse listener, or <code>null</code> if not + * found + * @see SwingValidatorMessageTableMouseListener + */ + public static SwingValidatorMessageTableMouseListener getErrorTableMouseListener(JTable table) { + if (table != null) { + for (MouseListener listener : table.getMouseListeners()) { + if (listener instanceof SwingValidatorMessageTableMouseListener) { + return (SwingValidatorMessageTableMouseListener) listener; + } + } + } + return null; + } + + /** + * @param table the validator table ui + * @return the validator table mouse listener, or <code>null</code> if not + * found + * @see SwingValidatorMessageTableMouseListener + */ + public static SwingValidatorMessageTableMouseListener getListErrorTableMouseListener(JTable table) { + if (table != null) { + for (MouseListener listener : table.getMouseListeners()) { + if (listener instanceof SwingValidatorMessageTableMouseListener) { + return (SwingValidatorMessageTableMouseListener) listener; + } + } + } + return null; + } + + public static String getMessage(SwingValidatorMessage model) { + String text = model.getMessage(); + if (model.getField() != null) { + text = model.getI18nError(text); + } + return text; + } + + public static String getMessage(SimpleBeanValidatorMessage model) { + String text = model.getMessage(); + if (model.getField() != null) { + text = model.getI18nError(text); + } + return text; + } + + public static String getMessage(SwingListValidatorMessage model) { + String text = model.getMessage(); + if (model.getField() != null) { + text = model.getI18nError(text); + } + return text; + } + + public static String getMessage(UnifiedValidatorMessage model) { + String text = model.getMessage(); + if (model.getField() != null) { + text = model.getI18nError(text); + } + return text; + } + + public static String getFieldName(SwingValidatorMessage model, String value) { + String text = null; + JComponent editor = model.getEditor(); + if (editor != null) { + text = (String) editor.getClientProperty("validatorLabel"); + /*if (l != null) { + text = I18n.t(l); + } else { + // TODO should try the text + }*/ + } + if (text == null) { + text = value; + } + return text; + } + + public static String getFieldName(SwingListValidatorMessage model, String value) { + String text = null; + JComponent editor = model.getEditor(); + if (editor != null) { + text = (String) editor.getClientProperty("validatorLabel"); + /*if (l != null) { + text = I18n.t(l); + } else { + // TODO should try the text + }*/ + } + if (text == null) { + text = value; + } + return text; + } + + public static String getFieldName(UnifiedValidatorMessage model, String value) { + return getFieldName(model, value, null); + } + + public static String getFieldName(UnifiedValidatorMessage model, String value, String valueFallBack) { + String text = null; + JComponent editor = model.getEditor(); + Object validatorLabel = null; + if (editor != null) { + + validatorLabel = editor.getClientProperty("validatorLabel"); + + } + + if (validatorLabel != null) { + + if (model.isSimpleValidator()) { + + text = (String) validatorLabel; + + } else { + + Map<String, String> validatorLabelMap = (Map<String, String>) validatorLabel; + + String field = model.getField(); + text = validatorLabelMap.get(field); + + } + } + + if (text == null && valueFallBack != null) { + text = valueFallBack; + } + + if (text == null) { + text = value; + } + + return text; + } + + /** + * Method to listen the modification of the context name and at each time + * reload fields of the ui. + * + * @param validator validator to listen + * @param ui ui to refresh when context name has changed + * @since 2.2.1 + */ + public static void listenValidatorContextNameAndRefreshFields( + SwingValidator<?> validator, + final JAXXValidator ui) { + + PropertyChangeListener listener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + SwingValidator<?> validator = (SwingValidator<?>) evt.getSource(); + if (log.isInfoEnabled()) { + log.info("Context name changed to [" + evt.getNewValue() + + "] for validator " + validator.getType()); + } + ui.registerValidatorFields(); + } + }; + validator.addPropertyChangeListener( + SwingValidator.CONTEXT_PROPERTY, + listener + ); + } + +// /** +// * Default bean validator creator to use in the {@link BeanValidatorFactory}. +// * +// * @author Tony Chemit - chemit@codelutin.com +// * @since 2.1 +// */ +// public static class DefaultSwingValidatorCreator implements BeanValidatorFactory.BeanValidatorCreator { +// +// @Override +// public <O> BeanValidator<O> newBeanValidator(NuitonValidatorProvider provider, Class<O> type, String context, NuitonValidatorScope... scopes) { +// BeanValidator<O> beanValidator = new SwingValidator<O>(provider, +// type, +// context, +// scopes +// ); +// return beanValidator; +// } +// } + + /** + * Convinient method to attach a bean to all validators of an JAXXObject. + * + * It is possible to exclude some validator to be treated. + * + * @param ui the ui containing the validatros to treate + * @param bean the bean to attach in validators (can be null) + * @param excludeIds the list of validator id to exclude + */ + @SuppressWarnings({"unchecked"}) + public static void setValidatorBean(JAXXObject ui, + Object bean, + String... excludeIds) { + if (!JAXXValidator.class.isAssignableFrom(ui.getClass())) { + return; + } + JAXXValidator jaxxValidator = (JAXXValidator) ui; + List<String> validatorIds = jaxxValidator.getValidatorIds(); + if (excludeIds.length > 0) { + validatorIds = new ArrayList<String>(validatorIds); + for (String excludeId : excludeIds) { + validatorIds.remove(excludeId); + } + } + for (String validatorId : validatorIds) { + SwingValidator beanValidator = + jaxxValidator.getValidator(validatorId); + if (bean == null || beanValidator.getType().isAssignableFrom( + bean.getClass())) { + // touch validator, only if fits the bean type (or bean is null) + beanValidator.setBean(bean); + } + } + } + + /** + * Convinient method to set the changed property to all validators of an + * JAXXObject. + * + * It is possible to exclude some validator to be treated. + * + * @param ui the ui containing the validatros to treate + * @param newValue the new value to set in changed validator property + * @param excludeIds the list of validator id to exclude + */ + @SuppressWarnings({"unchecked"}) + public static void setValidatorChanged(JAXXObject ui, + boolean newValue, + String... excludeIds) { + if (!JAXXValidator.class.isAssignableFrom(ui.getClass())) { + return; + } + JAXXValidator jaxxValidator = (JAXXValidator) ui; + List<String> validatorIds = jaxxValidator.getValidatorIds(); + if (excludeIds.length > 0) { + validatorIds = new ArrayList<String>(validatorIds); + for (String excludeId : excludeIds) { + validatorIds.remove(excludeId); + } + } + for (String validatorId : validatorIds) { + SwingValidator<?> beanValidator = + jaxxValidator.getValidator(validatorId); + beanValidator.setChanged(newValue); + } + } + + protected static Multimap<JComponent, ValidatorField> getValidatorEditors(JAXXValidator ui) { + + Multimap<JComponent, ValidatorField> editors = ArrayListMultimap.create(); + + Map<Field, ValidatorField> validatorFields = null; + Map<Method, ValidatorField> validatorMethods = null; + try { + + validatorFields = ReflectUtil.getFieldAnnotation( + ui.getClass(), + ValidatorField.class, + true + ); + + validatorMethods = ReflectUtil.getMethodAnnotation( + ui.getClass(), + ValidatorField.class, + true + ); + for (Map.Entry<Field, ValidatorField> fieldEntry : validatorFields.entrySet()) { + Field field = fieldEntry.getKey(); + field.setAccessible(true); + ValidatorField fieldAnnotation = fieldEntry.getValue(); + JComponent editor = (JComponent) field.get(ui); + editors.put(editor, fieldAnnotation); + } + + for (Map.Entry<Method, ValidatorField> fieldEntry : validatorMethods.entrySet()) { + Method method = fieldEntry.getKey(); + method.setAccessible(true); + ValidatorField fieldAnnotation = fieldEntry.getValue(); + JComponent editor = (JComponent) method.invoke(ui); + editors.put(editor, fieldAnnotation); + } + + } catch (Exception e) { + throw new IllegalStateException("Could not init validators on ui " + ui, e); + } finally { + if (validatorFields != null) { + validatorFields.clear(); + } + if (validatorMethods != null) { + validatorMethods.clear(); + } + } + return editors; + } + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/meta/Validator.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/meta/Validator.java new file mode 100644 index 0000000..47d75c5 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/meta/Validator.java @@ -0,0 +1,45 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing.meta; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to put on each field validator. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.3 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Validator { + + /** + * Obtain the id of the validator. + * + * @return the id of the validator. + */ + String validatorId(); +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/meta/ValidatorField.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/meta/ValidatorField.java new file mode 100644 index 0000000..a9a342c --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/meta/ValidatorField.java @@ -0,0 +1,60 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing.meta; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to put on each field or method linked to a validator. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.3 + */ +@Target(value = {ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ValidatorField { + /** + * Obtain the id of the validator used for the field. + * + * @return the id of the validator used for the field. + */ + String validatorId(); + + /** + * Obtain the name of the bean property(ies) to validate. + * + * @return the name of the property(ies) to validate + */ + String[] propertyName(); + + /** + * Obtain the name of the property editor. + * + * If empty, then use the {@link #propertyName()}. + * + * @return the name of the property editor + */ + String editorName() default ""; +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/ui/AbstractBeanValidatorUI.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/ui/AbstractBeanValidatorUI.java new file mode 100644 index 0000000..eda8725 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/ui/AbstractBeanValidatorUI.java @@ -0,0 +1,102 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing.ui; + +import com.google.common.collect.Ordering; +import com.google.common.collect.Sets; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.jxlayer.plaf.AbstractLayerUI; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.simple.SimpleBeanValidator; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorEvent; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorListener; + +import javax.swing.JComponent; +import java.util.Collection; +import java.util.Set; + +/** + * Abstract renderer + * + * @author Tony Chemit - chemit@codelutin.com + */ +public abstract class AbstractBeanValidatorUI extends AbstractLayerUI<JComponent> implements SimpleBeanValidatorListener { + + /** Logger */ + private static final Log log = LogFactory.getLog(AbstractBeanValidatorUI.class); + + private static final long serialVersionUID = 1L; + + /** + * Actual scope to display in the layer. + * + * This field will be recomputed each time a new event arrived on this + * field. + */ + protected NuitonValidatorScope scope; + + /** Field name in validator. */ + protected final Set<String> fields; + + protected AbstractBeanValidatorUI(String field) { + this(Sets.newHashSet(field)); + } + + protected AbstractBeanValidatorUI(Collection<String> fields) { + this.fields = Sets.newHashSet(fields); + if (log.isDebugEnabled()) { + log.debug("install " + this + "<fields:" + this.fields + ">"); + } + } + + public NuitonValidatorScope getScope() { + return scope; + } + + @Override + public void onFieldChanged(SimpleBeanValidatorEvent event) { + if (fields.contains(event.getField())) { + + scope = getHighestScope(event); + if (log.isDebugEnabled()) { + log.debug("set new scope : " + scope + " to field " + fields); + } + // ask to repaint the layer + setDirty(true); + } + } + + protected NuitonValidatorScope getHighestScope(SimpleBeanValidatorEvent event) { + SimpleBeanValidator<?> source = event.getSource(); + Set<NuitonValidatorScope> scopes = Sets.newHashSet(); + for (String field : fields) { + NuitonValidatorScope scope = source.getHighestScope(field); + if (scope != null) { + scopes.add(scope); + } + } + return scopes.isEmpty() ? null : Ordering.natural().max(scopes); + } + + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/ui/IconValidationUI.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/ui/IconValidationUI.java new file mode 100644 index 0000000..db468c5 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/ui/IconValidationUI.java @@ -0,0 +1,108 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing.ui; + +import com.google.common.collect.Sets; +import org.nuiton.jaxx.validator.swing.SwingValidatorUtil; +import org.jdesktop.jxlayer.JXLayer; +import org.nuiton.validator.NuitonValidatorScope; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.util.Collection; +import java.util.EnumMap; + + +/** + * An implementation of {@link AbstractBeanValidatorUI} which paints a icon on + * top right corner. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class IconValidationUI extends AbstractBeanValidatorUI { + + private static final long serialVersionUID = 1L; + + // The icon to be shown at the layer's corner + + protected EnumMap<NuitonValidatorScope, BufferedImage> icons; + + public IconValidationUI(String field) { + this(Sets.newHashSet(field)); + } + + public IconValidationUI(Collection<String> fields) { + super(fields); + icons = new EnumMap<NuitonValidatorScope, BufferedImage>(NuitonValidatorScope.class); + + for (NuitonValidatorScope scope : NuitonValidatorScope.values()) { + + BufferedImage image = prepareIcon(SwingValidatorUtil.getColor(scope)); + icons.put(scope, image); + } + } + + @Override + public void installUI(JComponent c) { + super.installUI(c); + c.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 3)); + } + + @Override + public void uninstallUI(JComponent c) { + super.uninstallUI(c); + c.setBorder(null); + } + + @Override + protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { + super.paintLayer(g2, l); + // There is no need to take insets into account for this painter + NuitonValidatorScope scope = getScope(); + if (scope != null) { + BufferedImage icon = icons.get(scope); + g2.drawImage(icon, l.getWidth() - icon.getWidth() - 1, 0, null); + } + } + + protected static BufferedImage prepareIcon(Color color) { + int width = 7; + int height = 8; + BufferedImage icon = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = (Graphics2D) icon.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g2.setColor(color); + g2.fillRect(0, 0, width, height); + g2.setColor(Color.WHITE); + g2.drawLine(0, 0, width, height); + g2.drawLine(0, height, width, 0); + g2.dispose(); + return icon; + } + + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/ui/ImageValidationUI.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/ui/ImageValidationUI.java new file mode 100644 index 0000000..9c97491 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/ui/ImageValidationUI.java @@ -0,0 +1,97 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing.ui; + +import com.google.common.collect.Sets; +import org.nuiton.jaxx.validator.swing.SwingValidatorUtil; +import org.jdesktop.jxlayer.JXLayer; +import org.nuiton.validator.NuitonValidatorScope; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.util.Collection; +import java.util.EnumMap; + + +/** + * An implementation of {@link AbstractBeanValidatorUI} which paints a icon on + * top right corner. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class ImageValidationUI extends AbstractBeanValidatorUI { + + private static final long serialVersionUID = 1L; + + protected EnumMap<NuitonValidatorScope, BufferedImage> icons; + + public ImageValidationUI(String fields) { + this(Sets.newHashSet(fields)); + } + + public ImageValidationUI(Collection<String> fields) { + super(fields); + icons = new EnumMap<NuitonValidatorScope, BufferedImage>(NuitonValidatorScope.class); + + for (NuitonValidatorScope scope : NuitonValidatorScope.values()) { + + BufferedImage image = prepareIcon(SwingValidatorUtil.getIcon(scope)); + icons.put(scope, image); + } + } + + protected static BufferedImage prepareIcon(ImageIcon image) { + BufferedImage icon = new BufferedImage(image.getIconWidth(), image.getIconHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = (Graphics2D) icon.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g2.drawImage(image.getImage(), 0, 0, null); + g2.dispose(); + return icon; + } + + @Override + public void installUI(JComponent c) { + super.installUI(c); + c.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 3)); + } + + @Override + public void uninstallUI(JComponent c) { + super.uninstallUI(c); + c.setBorder(null); + } + + @Override + protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { + super.paintLayer(g2, l); + NuitonValidatorScope scope = getScope(); + if (scope != null) { + BufferedImage icon = icons.get(scope); + g2.drawImage(icon, l.getWidth() - icon.getWidth() - 1, 0, null); + } + } +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/ui/TranslucentValidationUI.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/ui/TranslucentValidationUI.java new file mode 100644 index 0000000..565ecfd --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/ui/TranslucentValidationUI.java @@ -0,0 +1,78 @@ +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.validator.swing.ui; + +import org.nuiton.jaxx.validator.swing.SwingValidatorUtil; +import org.jdesktop.jxlayer.JXLayer; +import org.nuiton.validator.NuitonValidatorScope; + +import javax.swing.JComponent; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.util.Collection; + +/** + * An implementation of {@link AbstractBeanValidatorUI} which paints a + * translucent backgroud color (green for ok, red for error, yellow for + * warning). + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class TranslucentValidationUI extends AbstractBeanValidatorUI { + + private static final long serialVersionUID = 1L; + + public TranslucentValidationUI(String field) { + super(field); + } + + public TranslucentValidationUI(Collection<String> fields) { + super(fields); + } + + @Override + protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { + // paints the layer as is + super.paintLayer(g2, l); + + // to be in sync with the view if the layer has a border + Insets layerInsets = l.getInsets(); + g2.translate(layerInsets.left, layerInsets.top); + + JComponent view = l.getView(); + // To prevent painting on view's border + Insets insets = view.getInsets(); + g2.clip(new Rectangle(insets.left, insets.top, + view.getWidth() - insets.left - insets.right, + view.getHeight() - insets.top - insets.bottom)); + + NuitonValidatorScope scope = getScope(); + + Color c = scope == null ? Color.WHITE : SwingValidatorUtil.getColor(scope); + g2.setColor(c); + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .2f)); + g2.fillRect(0, 0, l.getWidth(), l.getHeight()); + } +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessage.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessage.java new file mode 100644 index 0000000..097619d --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessage.java @@ -0,0 +1,198 @@ +package org.nuiton.jaxx.validator.swing.unified; + +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.validator.swing.SwingValidator; +import org.apache.commons.lang3.ObjectUtils; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.AbstractValidator; + +import javax.swing.JComponent; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import static org.nuiton.i18n.I18n.t; + +/** + * Created on 8/15/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.10 + */ +public class UnifiedValidatorMessage implements Comparable<UnifiedValidatorMessage>, Serializable { + + private static final long serialVersionUID = 1L; + + /** the validator that produce the message */ + protected final AbstractValidator<?> validator; + + /** the bean on which event occurs. */ + protected final Object bean; + + /** the field that produce the message */ + protected final String field; + + /** the label of the message (to be displayed somewhere) */ + protected final String message; + + /** the scope of the message */ + protected final NuitonValidatorScope scope; + + /** the optional field's editor */ + protected JComponent editor; + + protected final boolean simpleValidator; + + public UnifiedValidatorMessage(AbstractValidator<?> validator, + Object bean, + String field, + String message, + NuitonValidatorScope scope, + JComponent editor) { + this.field = field; + this.bean = bean; + this.validator = validator; + this.message = message == null ? null : message.trim(); + this.scope = scope; + this.simpleValidator = validator instanceof SwingValidator<?>; + this.editor = editor; + } + + public AbstractValidator<?> getValidator() { + return validator; + } + + public String getField() { + return field; + } + + public NuitonValidatorScope getScope() { + return scope; + } + + public String getMessage() { + return message; + } + + public Object getBean() { + return bean; + } + + public JComponent getEditor() { + return editor; + } + + public boolean isSimpleValidator() { + return simpleValidator; + } + + @Override + public int compareTo(UnifiedValidatorMessage o) { + // sort on scope + int result = getScope().compareTo(o.getScope()); + if (result == 0) { + + // sort on bean + + if (simpleValidator) { + + if (o.simpleValidator) { + result = 0; + } else { + // this message must go up (simple message) + result = -1; + } + } else { + if (o.simpleValidator) { + // that message must go up (simple message) + result = 1; + } + } + if (result == 0) { + + // sort on field name + result = field.compareTo(o.field); + if (result == 0) { + // sort on message + result = message.compareTo(o.message); + } + } + } + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof UnifiedValidatorMessage)) { + return false; + } + + UnifiedValidatorMessage that = (UnifiedValidatorMessage) o; + + return field.equals(that.field) && + ObjectUtils.equals(bean, that.bean) && + ObjectUtils.equals(message, that.message) && + scope == that.scope; + } + + @Override + public int hashCode() { + int result = field.hashCode(); + result = 31 * result + (bean != null ? bean.hashCode() : 0); + result = 31 * result + (message != null ? message.hashCode() : 0); + result = 31 * result + (scope != null ? scope.hashCode() : 0); + return result; + } + + @Override + public String toString() { + String s = scope + " - " + + (field == null ? message : field + "[" + getBean() + + "] - " + message); + if (editor != null) { + s = editor.getName() + " : " + s; + } + return s; + } + + public String getI18nError(String error) { + String text; + if (!error.contains("##")) { + text = t(error); + } else { + StringTokenizer stk = new StringTokenizer(error, "##"); + String errorName = stk.nextToken(); + List<String> args = new ArrayList<String>(); + while (stk.hasMoreTokens()) { + args.add(stk.nextToken()); + } + text = t(errorName, args.toArray()); + } + return text; + } +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageTableModel.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageTableModel.java new file mode 100644 index 0000000..b00c7a3 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageTableModel.java @@ -0,0 +1,473 @@ +package org.nuiton.jaxx.validator.swing.unified; + +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.validator.swing.SwingListValidator; +import org.nuiton.jaxx.validator.swing.SwingValidator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.AbstractValidator; +import org.nuiton.validator.bean.list.BeanListValidator; +import org.nuiton.validator.bean.list.BeanListValidatorEvent; +import org.nuiton.validator.bean.list.BeanListValidatorListener; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorEvent; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorListener; + +import javax.swing.JComponent; +import javax.swing.table.AbstractTableModel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * Created on 8/15/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.10 + */ +public class UnifiedValidatorMessageTableModel extends AbstractTableModel { + + private static final long serialVersionUID = 1L; + + /** Logger */ + private static Log log = + LogFactory.getLog(UnifiedValidatorMessageTableModel.class); + + public static final String[] columnNames = + {"validator.scope", + "validator.bean", + "validator.field", + "validator.message"}; + + public static final Class<?>[] columnClasses = + {NuitonValidatorScope.class, Object.class, String.class, String.class}; + + /** list of registred validators */ + protected List<AbstractValidator<?>> validators; + + /** list of messages actual displayed */ + protected List<UnifiedValidatorMessage> data; + + protected transient BeanListValidatorListener listValidatorListener; + + protected transient SimpleBeanValidatorListener simpleValidatorListener; + + public UnifiedValidatorMessageTableModel() { + data = Lists.newArrayList(); + validators = Lists.newArrayList(); + } + + /** + * Register a validator for this model. + * + * + * Note: a validator can not be register twice in the same model. + * + * @param validator the validator to register + */ + public void registerValidator(SwingValidator<?> validator) { + if (validators.contains(validator)) { + throw new IllegalArgumentException( + "the validator " + validator + " is already registred in " + + this); + } + validators.add(validator); + validator.addSimpleBeanValidatorListener(getSimpleValidatorListener()); + } + + /** + * Register a validator for this model. + * + * + * Note: a validator can not be register twice in the same model. + * + * @param validator the validator to register + */ + public void registerValidator(BeanListValidator<?> validator) { + Preconditions.checkState( + !validators.contains(validator), + "Validator " + validator + " is already registred in " + + this); + validators.add(validator); + validator.addBeanListValidatorListener(getListValidatorListener()); + } + + public void clear() { + int i = data.size(); + if (i > 0) { + data.clear(); + fireTableRowsDeleted(0, i - 1); + } + } + + public void clearValidators() { + for (AbstractValidator<?> v : validators) { + if (v instanceof BeanListValidator) { + ((BeanListValidator) v).removeBeanListValidatorListener(getListValidatorListener()); + } else if (v instanceof SwingValidator) { + ((SwingValidator) v).removeSimpleBeanValidatorListener(getSimpleValidatorListener()); + } + } + validators.clear(); + } + + @Override + public boolean isCellEditable(int row, int column) { + // cells are never editable in this model + return false; + } + + @Override + public Class<?> getColumnClass(int columnIndex) { + SwingUtil.ensureColumnIndex(this, columnIndex); + return columnClasses[columnIndex]; + } + + @Override + public String getColumnName(int column) { + SwingUtil.ensureColumnIndex(this, column); + return columnNames[column]; + } + + @Override + public int getRowCount() { + return data.size(); + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + SwingUtil.ensureColumnIndex(this, columnIndex); + SwingUtil.ensureRowIndex(this, rowIndex); + + UnifiedValidatorMessage message = data.get(rowIndex); + + Object result; + + switch (columnIndex) { + case 0:// the icon + result = message.getScope(); + + break; + case 1: + // the bean + result = message.isSimpleValidator() ? "-" : message.getBean(); + break; + case 2: + // the field + result = message.getField(); + break; + case 3: + // the message + result = message.getMessage(); + break; + default: + throw new IllegalStateException("Can't come here"); + } + + return result; + } + + /** + * Obtain the message for a given row. + * + * @param rowIndex the row index + * @return the message for the given row index + */ + public UnifiedValidatorMessage getRow(int rowIndex) { + SwingUtil.ensureRowIndex(this, rowIndex); + return data.get(rowIndex); + } + + protected void addMessages(SwingValidator<?> validator, + String fieldName, + NuitonValidatorScope scope, + boolean sort, + String... messages) { + + JComponent editor = validator == null ? + null : + validator.getFieldRepresentation(fieldName); + // add new errors + for (String error : messages) { + UnifiedValidatorMessage row = + new UnifiedValidatorMessage( + validator, + null, + fieldName, + error, + scope, + editor + ); + data.add(row); + if (!sort) { + fireTableRowsInserted(data.size() - 1, data.size() - 1); + } + } + + if (sort) { + + // resort datas + Collections.sort(data); + + // notify + fireTableDataChanged(); + } + } + +// protected void addMessages(JComponent editor, +// String fieldName, +// NuitonValidatorScope scope, +// boolean sort, +// String... messages) { +// +// // add new errors +// for (String message : messages) { +// UnifiedValidatorMessage row = +// new UnifiedValidatorMessage( +// null, +// null, +// fieldName, +// message, +// scope, +// editor); +// data.add(row); +// if (!sort) { +// fireTableRowsInserted(data.size() - 1, data.size() - 1); +// } +// } +// +// if (sort) { +// +// // resort datas +// Collections.sort(data); +// +// // notify +// fireTableDataChanged(); +// } +// } + + protected void addMessages(BeanListValidator<?> validator, + Object bean, + String fieldName, + NuitonValidatorScope scope, + boolean sort, + String... messages) { + + JComponent editor = null; + + if (validator instanceof SwingListValidator<?>) { + editor = ((SwingListValidator) validator).getEditor(); + } + + // add new errors + for (String message : messages) { + UnifiedValidatorMessage row = + new UnifiedValidatorMessage( + validator, + bean, + fieldName, + message, + scope, + editor); + data.add(row); + if (!sort) { + fireTableRowsInserted(data.size() - 1, data.size() - 1); + } + } + + if (sort) { + + // resort datas + Collections.sort(data); + + // notify + fireTableDataChanged(); + } + } + + protected void removeMessages(SwingValidator<?> validator, + String fieldName, + NuitonValidatorScope scope, + boolean notify, + String... messages) { + + List<String> messagesToDel = + new ArrayList<String>(Arrays.asList(messages)); + + // do it in reverse mode (only one pass in that way since index + // will stay coherent while removing them) + + for (int i = getRowCount() - 1; i > -1; i--) { + UnifiedValidatorMessage message = data.get(i); + + if (validator.equals(message.getValidator()) + && message.getScope() == scope + && message.getField().equals(fieldName) + && messagesToDel.contains(message.getMessage())) { + // remove the message + data.remove(i); + if (notify) { + fireTableRowsDeleted(i, i); + } + } + + } + } + + protected void removeMessages(JComponent editor, + String fieldName, + NuitonValidatorScope scope, + boolean notify) { + + // do it in reverse mode (only one pass in that way since index + // will stay coherent while removing them) + + for (int i = getRowCount() - 1; i > -1; i--) { + UnifiedValidatorMessage message = data.get(i); + if (editor.equals(message.getEditor()) + && (scope == null || message.getScope() == scope) + && message.getField().equals(fieldName)) { + // remove the message + data.remove(i); + if (notify) { + fireTableRowsDeleted(i, i); + } + } + } + } + + protected void removeMessages(BeanListValidator<?> validator, + Object bean, + String fieldName, + NuitonValidatorScope scope, + boolean notify, + String... messages) { + + List<String> messagesToDel = + new ArrayList<String>(Arrays.asList(messages)); + + // do it in reverse mode (only one pass in that way since index + // will stay coherent while removing them) + + for (int i = getRowCount() - 1; i > -1; i--) { + UnifiedValidatorMessage message = data.get(i); + if (validator.equals(message.getValidator()) + && message.getScope() == scope + && message.getBean() == bean + && message.getField().equals(fieldName) + && messagesToDel.contains(message.getMessage())) { + // remove the message + data.remove(i); + if (notify) { + fireTableRowsDeleted(i, i); + } + } + } + } + + protected BeanListValidatorListener getListValidatorListener() { + if (listValidatorListener == null) { + listValidatorListener = new BeanListValidatorListener() { + @Override + public void onFieldChanged(BeanListValidatorEvent event) { + String[] toDelete = event.getMessagesToDelete(); + String[] toAdd = event.getMessagesToAdd(); + String field = event.getField(); + Object bean = event.getBean(); + NuitonValidatorScope scope = event.getScope(); + boolean mustAdd = toAdd != null && toAdd.length > 0; + boolean mustDel = toDelete != null && toDelete.length > 0; + + if (log.isTraceEnabled()) { + log.trace("----------------------------------------------------------"); + log.trace(field + " - (" + getRowCount() + ") toAdd " + mustAdd); + log.trace(field + " - (" + getRowCount() + ") toDelete " + mustDel); + } + + BeanListValidator<?> validator = event.getSource(); + + if (mustDel) { + + // removes datas and notify if no messages to add + removeMessages(validator, bean, field, scope, !mustAdd, toDelete); + } + + if (mustAdd) { + + // add new messages, sort datas and notify + addMessages(validator, bean, field, scope, true, toAdd); + } + } + }; + } + return listValidatorListener; + } + + protected SimpleBeanValidatorListener getSimpleValidatorListener() { + if (simpleValidatorListener == null) { + simpleValidatorListener = new SimpleBeanValidatorListener() { + @Override + public void onFieldChanged(SimpleBeanValidatorEvent event) { + String[] toDelete = event.getMessagesToDelete(); + String[] toAdd = event.getMessagesToAdd(); + String field = event.getField(); + NuitonValidatorScope scope = event.getScope(); + boolean mustAdd = toAdd != null && toAdd.length > 0; + boolean mustDel = toDelete != null && toDelete.length > 0; + + if (log.isTraceEnabled()) { + log.trace("----------------------------------------------------------"); + log.trace(field + " - (" + getRowCount() + ") toAdd " + mustAdd); + log.trace(field + " - (" + getRowCount() + ") toDelete " + mustDel); + } + + SwingValidator<?> validator = (SwingValidator<?>) event.getSource(); + + if (mustDel) { + + // removes datas and notify if no messages to add + removeMessages(validator, field, scope, !mustAdd, toDelete); + } + + if (mustAdd) { + + // add new messages, sort datas and notify + addMessages(validator, field, scope, true, toAdd); + } + } + }; + } + return simpleValidatorListener; + } + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageTableMouseListener.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageTableMouseListener.java new file mode 100644 index 0000000..84a304f --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageTableMouseListener.java @@ -0,0 +1,158 @@ +package org.nuiton.jaxx.validator.swing.unified; + +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.validator.swing.SwingListValidatorDataLocator; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JComponent; +import javax.swing.JTable; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +/** + * Created on 8/15/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.10 + */ +public class UnifiedValidatorMessageTableMouseListener extends MouseAdapter { + + /** Logger */ + private static Log log = + LogFactory.getLog(UnifiedValidatorMessageTableMouseListener.class); + + public static final String HIGHLIGHT_ERROR_PROPERTY = "highlightError"; + + /** + * Delegate property change support. + */ + protected final PropertyChangeSupport pcs; + + /** + * The editor of listened bean. + */ + protected final JTable editor; + + /** + * The cell data locator. + */ + protected final SwingListValidatorDataLocator<Object> dataLocator; + + public UnifiedValidatorMessageTableMouseListener(JTable editor, + SwingListValidatorDataLocator dataLocator) { + this.editor = editor; + this.dataLocator = dataLocator; + this.pcs = new PropertyChangeSupport(this); + } + + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + if (e.getClickCount() == 2) { + + UnifiedValidatorMessage entry = getSelectedMessage(e); + if (entry == null) { + // no entry found + return; + } + + if (entry.isSimpleValidator()) { + + JComponent component = entry.getEditor(); + if (component != null) { + pcs.firePropertyChange(HIGHLIGHT_ERROR_PROPERTY, null, entry); + if (component.isVisible()) { + component.requestFocus(); + } + } + + } else { + + if (dataLocator.acceptType(entry.getBean().getClass())) { + + Pair<Integer, Integer> cell = dataLocator.locateDataCell( + editor.getModel(), + entry.getBean(), + entry.getField()); + + SwingUtil.editCell(editor, cell.getLeft(), cell.getRight()); + } + + } + + } + } + + protected UnifiedValidatorMessage getSelectedMessage(MouseEvent e) { + JTable table = (JTable) e.getSource(); + if (!(table.getModel() instanceof UnifiedValidatorMessageTableModel)) { + if (log.isWarnEnabled()) { + log.warn("model must be a " + + UnifiedValidatorMessageTableModel.class + + ", but was " + table.getModel()); + } + return null; + } + + UnifiedValidatorMessageTableModel model = + (UnifiedValidatorMessageTableModel) table.getModel(); + int index = table.getSelectionModel().getMinSelectionIndex(); + if (index == -1) { + // nothing is selected + return null; + } + if (table.getRowSorter() != null) { + index = table.getRowSorter().convertRowIndexToModel(index); + } + UnifiedValidatorMessage entry = model.getRow(index); + if (log.isDebugEnabled()) { + log.debug("selected index: " + index + " : error: " + entry); + } + return entry; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + +} \ No newline at end of file diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageTableRenderer.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageTableRenderer.java new file mode 100644 index 0000000..bb36771 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageTableRenderer.java @@ -0,0 +1,187 @@ +package org.nuiton.jaxx.validator.swing.unified; + +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.Maps; +import org.nuiton.jaxx.validator.swing.SwingValidatorUtil; +import org.apache.commons.lang3.StringUtils; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.simple.SimpleBeanValidator; + +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import java.awt.Component; +import java.util.Map; + +import static org.nuiton.i18n.I18n.t; + +/** + * Created on 8/15/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.10 + */ +public class UnifiedValidatorMessageTableRenderer extends DefaultTableCellRenderer { + + private static final long serialVersionUID = 1L; + + protected final Map<String, String> fieldNameMap = Maps.newHashMap(); + + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, + int column) { + JLabel rendererComponent = (JLabel) + super.getTableCellRendererComponent( + table, + value, + isSelected, + hasFocus, + row, + column + ); + + ImageIcon icon = null; + String text = null; + String toolTipText = null; + + column = table.convertColumnIndexToModel(column); + if (table.getRowSorter() != null) { + row = table.getRowSorter().convertRowIndexToModel(row); + } + + if (column == 0) { + + // scope + NuitonValidatorScope scope = (NuitonValidatorScope) value; + icon = getIcon(row, scope); + toolTipText = getIconTip(row, scope); + + } else { + + UnifiedValidatorMessageTableModel tableModel = + (UnifiedValidatorMessageTableModel) table.getModel(); + UnifiedValidatorMessage validatorMessage = tableModel.getRow(row); + + switch (column) { + + case 1: + + // row bean + + if (validatorMessage.isSimpleValidator()) { + + text = getSimpleBeanValidatorValue(row, validatorMessage); + toolTipText = getSimpleBeanValidatorValueTip(row, text); + + } else { + + text = getListBeanValidatorValue(row, validatorMessage); + toolTipText = getListBeanValidatorValueTip(row, text); + + } + break; + + case 2: + + // field name + text = getFieldName(row, validatorMessage, (String) value); + toolTipText = getFieldNameTip(row, text); + break; + + case 3: + + // message + text = getMessage(row, validatorMessage); + toolTipText = getMessageTip(row, text); + break; + + } + + } + + rendererComponent.setText(text); + rendererComponent.setToolTipText(toolTipText); + rendererComponent.setIcon(icon); + return rendererComponent; + } + + public ImageIcon getIcon(int row, NuitonValidatorScope scope) { + return SwingValidatorUtil.getIcon(scope); + } + + public String getIconTip(int row, NuitonValidatorScope scope) { + String label = t(scope.getLabel()); + return t("validator.scope.tip", label); + } + + public String getMessage(int row, UnifiedValidatorMessage model) { + return SwingValidatorUtil.getMessage(model); + } + + public String getMessageTip(int row, String message) { + return t("validator.message.tip", message); + } + + public String getFieldName(int row, UnifiedValidatorMessage model, String value) { + return SwingValidatorUtil.getFieldName(model, value, fieldNameMap.get(value)); + } + + public String getFieldNameTip(int row, String fieldName) { + return t("validator.field.tip", fieldName); + } + + public String getListBeanValidatorValue(int row, UnifiedValidatorMessage model) { + return decorateBean(model.getBean()); + } + + public String getListBeanValidatorValueTip(int row, String beanValue) { + return StringUtils.isEmpty(beanValue) ? null : t("validator.bean.tip", row, beanValue); + } + + public String getSimpleBeanValidatorValue(int row, UnifiedValidatorMessage model) { + return decorateBean(((SimpleBeanValidator) model.getValidator()).getBean()); + } + + public String getSimpleBeanValidatorValueTip(int row, String simpleBeanValue) { + return null; + } + + protected String decorateBean(Object bean) { + return bean == null ? "" : bean.toString(); + } + + public void clearFieldNameMap() { + fieldNameMap.clear(); + } + + public void addFieldName(String field, String name) { + fieldNameMap.put(field, name); + } + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageUtil.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageUtil.java new file mode 100644 index 0000000..19cdd58 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageUtil.java @@ -0,0 +1,187 @@ +package org.nuiton.jaxx.validator.swing.unified; + +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.validator.swing.SwingListValidatorDataLocator; +import org.nuiton.jaxx.validator.swing.SwingListValidatorTableEditorModelListener; +import org.nuiton.jaxx.validator.swing.SwingValidator; +import org.nuiton.jaxx.validator.swing.SwingValidatorMessageTableMouseListener; +import org.nuiton.validator.bean.list.BeanListValidator; + +import javax.swing.JTable; +import javax.swing.RowSorter; +import javax.swing.SortOrder; +import javax.swing.table.TableModel; +import java.awt.event.MouseListener; +import java.util.Arrays; + +import static org.nuiton.i18n.I18n.n; + +/** + * Created on 8/15/14. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.10 + */ +public class UnifiedValidatorMessageUtil { + + /** + * Prepare the ui where to display the validators messages. + * + * @param errorTable the table where to display validators messages + * @param render renderer to use + */ + public static void installUI(JTable errorTable, + UnifiedValidatorMessageTableRenderer render) { + + errorTable.setDefaultRenderer(Object.class, render); + errorTable.getRowSorter().setSortKeys( + Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); + + SwingUtil.setI18nTableHeaderRenderer( + errorTable, + n("validator.scope.header"), + n("validator.scope.header.tip"), + n("validator.bean.header"), + n("validator.bean.header.tip"), + n("validator.field.header"), + n("validator.field.header.tip"), + n("validator.message.header"), + n("validator.message.header.tip")); + SwingUtil.fixTableColumnWidth(errorTable, 0, 25); + + } + + /** + * Prepare the ui where to display the validators messages. + * + * @param messageTable the table where to display validators messages + */ + public static <O> void registerValidator(SwingValidator<O> validator, + JTable messageTable) { + + UnifiedValidatorMessageTableModel messageTableModel = getModel(messageTable); + + // register the validator to the error table model + messageTableModel.registerValidator(validator); + + // add the mouse listener + UnifiedValidatorMessageTableMouseListener listener = getUnifiedValidatorMessageTableMouseListener(messageTable); + + if (listener == null) { + registerErrorTableMouseListener(messageTable, null, null); + } + + } + + /** + * Prepare the ui where to display the validators messages. + * + * @param validator validator to register + * @param messageTable the table where to display validators messages + * @param dataTable table with data to validate by the validator + * @param dataLocator tool to find data in the data table from the validator messages + */ + public static <O> void registerValidator(BeanListValidator<O> validator, + JTable messageTable, + JTable dataTable, + SwingListValidatorDataLocator<O> dataLocator) { + + UnifiedValidatorMessageTableModel messageTableModel = getModel(messageTable); + + // register the validator to the error table model + messageTableModel.registerValidator(validator); + + // add the mouse listener + registerErrorTableMouseListener(messageTable, dataTable, dataLocator); + + // listen on editor model to add / remove bean into validator + dataTable.getModel().addTableModelListener( + new SwingListValidatorTableEditorModelListener<O>(validator, dataLocator)); + } + + /** + * Register for a given validator table ui a validator mouse listener. + * + * If a previous such listener was registered, then we will remove it and register a new one. + * + * @param messageTable the validator table ui + * @param dataTable table with data to validate by the validator + * @param dataLocator tool to find data in the data table from the validator messages + * @see UnifiedValidatorMessageTableMouseListener + */ + public static <O> void registerErrorTableMouseListener(JTable messageTable, + JTable dataTable, + SwingListValidatorDataLocator<O> dataLocator) { + UnifiedValidatorMessageTableMouseListener listener = + getUnifiedValidatorMessageTableMouseListener(messageTable); + + if (listener != null) { + + // remove existing listener + messageTable.removeMouseListener(listener); + + } + + listener = new UnifiedValidatorMessageTableMouseListener(dataTable, dataLocator); + messageTable.addMouseListener(listener); + + } + + /** + * @param table the validator table ui + * @return the validator table mouse listener, or <code>null</code> if not found + * @see SwingValidatorMessageTableMouseListener + */ + public static UnifiedValidatorMessageTableMouseListener getUnifiedValidatorMessageTableMouseListener(JTable table) { + + UnifiedValidatorMessageTableMouseListener result = null; + + for (MouseListener listener : table.getMouseListeners()) { + + if (listener instanceof UnifiedValidatorMessageTableMouseListener) { + + result = (UnifiedValidatorMessageTableMouseListener) listener; + break; + + } + } + + return result; + + } + + protected static UnifiedValidatorMessageTableModel getModel(JTable messageTable) { + + TableModel model = messageTable.getModel(); + + if (!(model instanceof UnifiedValidatorMessageTableModel)) { + throw new IllegalStateException("messageTable is not using a UnifiedValidatorMessageTableModel model: " + model); + } + + return (UnifiedValidatorMessageTableModel) model; + + } + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageWidget.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageWidget.java new file mode 100644 index 0000000..5ab7db4 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/UnifiedValidatorMessageWidget.java @@ -0,0 +1,319 @@ +package org.nuiton.jaxx.validator.swing.unified; + +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.swing.ComponentMover; +import org.nuiton.jaxx.runtime.swing.ComponentResizer; +import org.nuiton.jaxx.validator.swing.SwingListValidatorDataLocator; +import org.nuiton.jaxx.validator.swing.SwingListValidatorMessageTableRenderer; +import org.nuiton.jaxx.validator.swing.SwingValidator; +import org.nuiton.jaxx.validator.swing.SwingValidatorUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTitledPanel; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.list.BeanListValidator; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JRootPane; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import javax.swing.KeyStroke; +import javax.swing.ListSelectionModel; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.HierarchyBoundsAdapter; +import java.awt.event.HierarchyEvent; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import static org.nuiton.i18n.I18n.n; +import static org.nuiton.i18n.I18n.t; + +/** + * @author Tony Chemit - chemit@codelutin.com + * @since 2.10 + */ +public class UnifiedValidatorMessageWidget extends JToggleButton { + + private static final Log log = + LogFactory.getLog(UnifiedValidatorMessageWidget.class); + + private static final long serialVersionUID = 1L; + + public static final String CLOSE_DIALOG_ACTION = "closeDialog"; + + protected UnifiedValidatorMessageTableModel messageTableModel = new UnifiedValidatorMessageTableModel(); + + protected JDialog popup = new JDialog(); + + protected JTable messageTable = new JTable(); + + protected Point popupPosition = null; + + public UnifiedValidatorMessageWidget() { + super(SwingUtil.createActionIcon("alert-none")); + setToolTipText(t("validator.messageWidget.alert.none")); + + messageTableModel.addTableModelListener(new TableModelListener() { + + public void tableChanged(TableModelEvent e) { + int alerts = messageTableModel.getRowCount(); + String label; + switch (alerts) { + case 0: + label = n("validator.messageWidget.alert.none"); + break; + case 1: + label = n("validator.messageWidget.alert.one"); + break; + default: + label = n("validator.messageWidget.alert.several"); + } + + NuitonValidatorScope maxScope; + String icon; + if (alerts == 0) { + icon = "alert-none"; + + } else { + maxScope = NuitonValidatorScope.INFO; + for (int i = 0; i < alerts; i++) { + NuitonValidatorScope scope = messageTableModel.getRow(i).getScope(); + int diff = scope.compareTo(maxScope); + if (diff < 0) { + maxScope = scope; + } + } + switch (maxScope) { + case INFO: + icon = "alert-info"; + break; + case WARNING: + icon = "alert-warning"; + break; + default: + icon = "alert-error"; + + } + } + + setToolTipText(t(label, alerts)); + setIcon(SwingUtil.createActionIcon(icon)); + } + }); + + messageTable.setModel(messageTableModel); + messageTable.setRowSelectionAllowed(true); + messageTable.setAutoCreateRowSorter(true); + messageTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); + messageTable.setCellSelectionEnabled(false); + messageTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + messageTable.setFillsViewportHeight(true); + + SwingValidatorUtil.installUI(messageTable, + new SwingListValidatorMessageTableRenderer()); + + JScrollPane scrollPanel = new JScrollPane(messageTable); + scrollPanel.setColumnHeaderView(messageTable.getTableHeader()); + + JXTitledPanel titledPanel = new JXTitledPanel(t("validator.messageWidget.title"), scrollPanel); + popup.add(titledPanel); + popup.setTitle(t("validator.messageWidget.title")); + popup.setSize(800, 300); + popup.setAlwaysOnTop(true); + popup.setUndecorated(true); + + ComponentResizer cr = new ComponentResizer(); + cr.registerComponent(popup); + ComponentMover cm = new ComponentMover(); + cm.setDragInsets(cr.getDragInsets()); + cm.registerComponent(popup); + + popup.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + setSelected(false); + } + + }); + + popup.addComponentListener(new ComponentAdapter() { + + @Override + public void componentMoved(ComponentEvent e) { + Component component = e.getComponent(); + if (component.isShowing()) { + popupPosition = component.getLocationOnScreen(); + } + } + + }); + + addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + if (isSelected()) { + popup.setVisible(true); + } else { + popup.dispose(); + } + } + }); + + addHierarchyBoundsListener(new HierarchyBoundsAdapter() { + + @Override + public void ancestorMoved(HierarchyEvent e) { + if (popupPosition == null && isShowing()) { + Point point = new Point(getLocationOnScreen()); + point.translate(-popup.getWidth() + getWidth(), -popup.getHeight()); + popup.setLocation(point); + } + } + }); + + // add a auto-close action + JRootPane rootPane = popup.getRootPane(); + + KeyStroke shortcutClosePopup = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); + + rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( + shortcutClosePopup, CLOSE_DIALOG_ACTION); + + Action closeAction = new AbstractAction() { + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + popup.dispose(); + setSelected(false); + } + }; + + ImageIcon actionIcon = SwingUtil.createActionIcon("close-dialog"); + closeAction.putValue(Action.SMALL_ICON, actionIcon); + closeAction.putValue(Action.LARGE_ICON_KEY, actionIcon); + closeAction.putValue(Action.ACTION_COMMAND_KEY, "close"); + closeAction.putValue(Action.NAME, "close"); + closeAction.putValue(Action.SHORT_DESCRIPTION, t("validator.messageWidget.closeDialog.tip")); + + rootPane.getActionMap().put(CLOSE_DIALOG_ACTION, closeAction); + + JButton closeButton = new JButton(closeAction); + closeButton.setText(null); + closeButton.setFocusPainted(false); + closeButton.setRequestFocusEnabled(false); + closeButton.setFocusable(false); + + JToolBar jToolBar = new JToolBar(); + jToolBar.setOpaque(false); + jToolBar.add(closeAction); + jToolBar.setBorderPainted(false); + jToolBar.setFloatable(false); + titledPanel.setRightDecoration(jToolBar); + + } + + public void addTableModelListener(TableModelListener listener) { + messageTableModel.addTableModelListener(listener); + } + + public void removeTableModelListener(TableModelListener listener) { + messageTableModel.removeTableModelListener(listener); + } + + public void setDefaultRenderer(TableCellRenderer renderer) { + messageTable.setDefaultRenderer(Object.class, renderer); + } + + public TableCellRenderer getDefaultRenderer() { + return messageTable.getDefaultRenderer(Object.class); + } + + /** + * Register a simple validator. + * + * @param validator validator to register + */ + public void registerValidator(SwingValidator validator) { + + if (log.isInfoEnabled()) { + log.info("Register validator: " + validator); + } + + UnifiedValidatorMessageUtil.registerValidator( + validator, + messageTable); + + validator.doValidate(); + } + + /** + * Register a list validator. + * + * @param validator validator to register + * @param dataTable table with data to validate by the validator + * @param dataLocator tool to find data in the data table from the validator messages + */ + public void registerValidator(BeanListValidator validator, + JTable dataTable, + SwingListValidatorDataLocator dataLocator) { + + if (log.isInfoEnabled()) { + log.info("Register validator: " + validator); + } + UnifiedValidatorMessageUtil.registerValidator( + validator, + messageTable, + dataTable, + dataLocator); + + validator.doValidate(); + } + + /** Clear all the validators. */ + public void clearValidators() { + messageTableModel.clearValidators(); + messageTableModel.clear(); + } + +} diff --git a/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/package-info.java b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/package-info.java new file mode 100644 index 0000000..bcf72f5 --- /dev/null +++ b/jaxx-validator/src/main/java/org/nuiton/jaxx/validator/swing/unified/package-info.java @@ -0,0 +1,30 @@ +/** + * To unify Simple and List validators. + * + * Created on 8/15/14. + * @author Tony Chemit - chemit@codelutin.com + * @since 2.10 + */ +package org.nuiton.jaxx.validator.swing.unified; + +/* + * #%L + * JAXX :: Validator + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ diff --git a/jaxx-widgets-about/src/main/java/org/nuiton/jaxx/widgets/about/AboutUIBuilder.java b/jaxx-widgets-about/src/main/java/org/nuiton/jaxx/widgets/about/AboutUIBuilder.java index ed7de5e..fc4db51 100644 --- a/jaxx-widgets-about/src/main/java/org/nuiton/jaxx/widgets/about/AboutUIBuilder.java +++ b/jaxx-widgets-about/src/main/java/org/nuiton/jaxx/widgets/about/AboutUIBuilder.java @@ -25,7 +25,7 @@ package org.nuiton.jaxx.widgets.about; import com.google.common.base.Charsets; import com.google.common.base.Preconditions; import com.google.common.io.Resources; -import jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.SwingUtil; import org.nuiton.util.Resource; import javax.swing.AbstractAction; diff --git a/jaxx-widgets-common/src/main/java/org/nuiton/jaxx/widgets/DecoratorPopupHandler.java b/jaxx-widgets-common/src/main/java/org/nuiton/jaxx/widgets/DecoratorPopupHandler.java index 3a07fc5..de2ba38 100644 --- a/jaxx-widgets-common/src/main/java/org/nuiton/jaxx/widgets/DecoratorPopupHandler.java +++ b/jaxx-widgets-common/src/main/java/org/nuiton/jaxx/widgets/DecoratorPopupHandler.java @@ -22,7 +22,7 @@ package org.nuiton.jaxx.widgets; * #L% */ -import jaxx.runtime.swing.JAXXButtonGroup; +import org.nuiton.jaxx.runtime.swing.JAXXButtonGroup; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.decorator.MultiJXPathDecorator; diff --git a/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/DateTimeEditor.jaxx b/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/DateTimeEditor.jaxx index 7584599..44c1507 100644 --- a/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/DateTimeEditor.jaxx +++ b/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/DateTimeEditor.jaxx @@ -28,7 +28,7 @@ java.io.Serializable java.awt.BorderLayout - jaxx.runtime.swing.HidorButton + org.nuiton.jaxx.runtime.swing.HidorButton javax.swing.DefaultBoundedRangeModel org.jdesktop.swingx.JXDatePicker diff --git a/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/DateTimeEditorHandler.java b/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/DateTimeEditorHandler.java index 97a2f29..2ab50b8 100644 --- a/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/DateTimeEditorHandler.java +++ b/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/DateTimeEditorHandler.java @@ -24,7 +24,7 @@ package org.nuiton.jaxx.widgets.datetime; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; -import jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.spi.UIHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.jaxx.widgets.MutateOnConditionalPropertyChangeListener; diff --git a/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/TimeEditor.jaxx b/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/TimeEditor.jaxx index 70cd67d..ef3f99e 100644 --- a/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/TimeEditor.jaxx +++ b/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/TimeEditor.jaxx @@ -28,7 +28,7 @@ java.io.Serializable java.awt.BorderLayout - jaxx.runtime.swing.HidorButton + org.nuiton.jaxx.runtime.swing.HidorButton javax.swing.DefaultBoundedRangeModel </import> diff --git a/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/TimeEditorHandler.java b/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/TimeEditorHandler.java index f215103..1fab880 100644 --- a/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/TimeEditorHandler.java +++ b/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/TimeEditorHandler.java @@ -24,7 +24,7 @@ package org.nuiton.jaxx.widgets.datetime; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; -import jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.spi.UIHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.jaxx.widgets.MutateOnConditionalPropertyChangeListener; diff --git a/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/session/DateTimeEditorState.java b/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/session/DateTimeEditorState.java index 104e8dd..f8848b5 100644 --- a/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/session/DateTimeEditorState.java +++ b/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/session/DateTimeEditorState.java @@ -22,7 +22,7 @@ package org.nuiton.jaxx.widgets.datetime.session; * #L% */ -import jaxx.runtime.swing.session.State; +import org.nuiton.jaxx.runtime.swing.session.State; import org.nuiton.jaxx.widgets.datetime.DateTimeEditor; /** diff --git a/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/session/TimeEditorState.java b/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/session/TimeEditorState.java index 25a87a7..c32f9fc 100644 --- a/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/session/TimeEditorState.java +++ b/jaxx-widgets-datetime/src/main/java/org/nuiton/jaxx/widgets/datetime/session/TimeEditorState.java @@ -22,7 +22,7 @@ package org.nuiton.jaxx.widgets.datetime.session; * #L% */ -import jaxx.runtime.swing.session.State; +import org.nuiton.jaxx.runtime.swing.session.State; import org.nuiton.jaxx.widgets.datetime.TimeEditor; /** diff --git a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDdCoordinateEditorHandler.java b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDdCoordinateEditorHandler.java index 1cd53a1..17dbeaf 100644 --- a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDdCoordinateEditorHandler.java +++ b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDdCoordinateEditorHandler.java @@ -23,7 +23,7 @@ package org.nuiton.jaxx.widgets.gis.absolute; */ import com.google.common.base.Preconditions; -import jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.spi.UIHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.jaxx.widgets.gis.DdCoordinate; diff --git a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDmdCoordinateEditorHandler.java b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDmdCoordinateEditorHandler.java index 3a5710b..0eeb66e 100644 --- a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDmdCoordinateEditorHandler.java +++ b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDmdCoordinateEditorHandler.java @@ -23,7 +23,7 @@ package org.nuiton.jaxx.widgets.gis.absolute; */ import com.google.common.base.Preconditions; -import jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.spi.UIHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.jaxx.widgets.gis.DmdCoordinate; diff --git a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDmsCoordinateEditorHandler.java b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDmsCoordinateEditorHandler.java index 433277f..89799eb 100644 --- a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDmsCoordinateEditorHandler.java +++ b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDmsCoordinateEditorHandler.java @@ -23,7 +23,7 @@ package org.nuiton.jaxx.widgets.gis.absolute; */ import com.google.common.base.Preconditions; -import jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.spi.UIHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.jaxx.widgets.gis.DmsCoordinate; diff --git a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/CoordinatesEditor.jaxx b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/CoordinatesEditor.jaxx index e690d53..73198d1 100644 --- a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/CoordinatesEditor.jaxx +++ b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/CoordinatesEditor.jaxx @@ -22,7 +22,7 @@ <Table id="coordinateEditorTopPanel" insets="0"> <import> - jaxx.runtime.swing.CardLayout2Ext + org.nuiton.jaxx.runtime.swing.CardLayout2Ext org.nuiton.jaxx.widgets.gis.CoordinateFormat java.io.Serializable </import> diff --git a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/CoordinatesEditorHandler.java b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/CoordinatesEditorHandler.java index a29bde4..26755f3 100644 --- a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/CoordinatesEditorHandler.java +++ b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/absolute/CoordinatesEditorHandler.java @@ -23,8 +23,8 @@ package org.nuiton.jaxx.widgets.gis.absolute; */ import com.google.common.base.Preconditions; -import jaxx.runtime.spi.UIHandler; -import jaxx.runtime.swing.JAXXButtonGroup; +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.swing.JAXXButtonGroup; import org.nuiton.jaxx.widgets.gis.CoordinateFormat; import org.nuiton.util.beans.BeanUtil; diff --git a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/signed/SignedDdCoordinateEditorHandler.java b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/signed/SignedDdCoordinateEditorHandler.java index 6673dc5..8a14477 100644 --- a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/signed/SignedDdCoordinateEditorHandler.java +++ b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/signed/SignedDdCoordinateEditorHandler.java @@ -23,7 +23,7 @@ package org.nuiton.jaxx.widgets.gis.signed; */ import com.google.common.base.Preconditions; -import jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.spi.UIHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.jaxx.widgets.gis.DdCoordinate; diff --git a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/signed/SignedDmdCoordinateEditorHandler.java b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/signed/SignedDmdCoordinateEditorHandler.java index 8c668c0..e3c3d23 100644 --- a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/signed/SignedDmdCoordinateEditorHandler.java +++ b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/signed/SignedDmdCoordinateEditorHandler.java @@ -23,7 +23,7 @@ package org.nuiton.jaxx.widgets.gis.signed; */ import com.google.common.base.Preconditions; -import jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.spi.UIHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.jaxx.widgets.gis.DmdCoordinate; diff --git a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/signed/SignedDmsCoordinateEditorHandler.java b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/signed/SignedDmsCoordinateEditorHandler.java index 4bc13b9..3eed7bd 100644 --- a/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/signed/SignedDmsCoordinateEditorHandler.java +++ b/jaxx-widgets-gis/src/main/java/org/nuiton/jaxx/widgets/gis/signed/SignedDmsCoordinateEditorHandler.java @@ -23,7 +23,7 @@ package org.nuiton.jaxx.widgets.gis.signed; */ import com.google.common.base.Preconditions; -import jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.spi.UIHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.jaxx.widgets.gis.DmsCoordinate; diff --git a/jaxx-widgets-gis/src/test/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDdCoordinateEditorTest.java b/jaxx-widgets-gis/src/test/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDdCoordinateEditorTest.java index fad29de..b629122 100644 --- a/jaxx-widgets-gis/src/test/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDdCoordinateEditorTest.java +++ b/jaxx-widgets-gis/src/test/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDdCoordinateEditorTest.java @@ -22,7 +22,7 @@ package org.nuiton.jaxx.widgets.gis.absolute; * #L% */ -import jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.SwingUtil; import org.nuiton.jaxx.widgets.gis.DdCoordinate; import javax.swing.JButton; diff --git a/jaxx-widgets-gis/src/test/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDmsCoordinateEditorTest.java b/jaxx-widgets-gis/src/test/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDmsCoordinateEditorTest.java index 8b38754..5e87dea 100644 --- a/jaxx-widgets-gis/src/test/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDmsCoordinateEditorTest.java +++ b/jaxx-widgets-gis/src/test/java/org/nuiton/jaxx/widgets/gis/absolute/AbsoluteDmsCoordinateEditorTest.java @@ -22,7 +22,7 @@ package org.nuiton.jaxx.widgets.gis.absolute; * #L% */ -import jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.SwingUtil; import org.nuiton.jaxx.widgets.gis.DmsCoordinate; import javax.swing.JButton; diff --git a/jaxx-widgets-number/src/main/java/org/nuiton/jaxx/widgets/number/NumberEditorHandler.java b/jaxx-widgets-number/src/main/java/org/nuiton/jaxx/widgets/number/NumberEditorHandler.java index 8da7d17..289ff96 100644 --- a/jaxx-widgets-number/src/main/java/org/nuiton/jaxx/widgets/number/NumberEditorHandler.java +++ b/jaxx-widgets-number/src/main/java/org/nuiton/jaxx/widgets/number/NumberEditorHandler.java @@ -25,7 +25,7 @@ package org.nuiton.jaxx.widgets.number; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; -import jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.spi.UIHandler; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/FilterableDoubleList.jaxx b/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/FilterableDoubleList.jaxx index 8a3f7a5..b9c670e 100644 --- a/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/FilterableDoubleList.jaxx +++ b/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/FilterableDoubleList.jaxx @@ -19,7 +19,7 @@ <http://www.gnu.org/licenses/lgpl-3.0.html>. #L% --> -<Table genericType='O extends Serializable' implements='jaxx.runtime.bean.BeanTypeAware<O>'> +<Table genericType='O extends Serializable' implements='org.nuiton.jaxx.runtime.bean.BeanTypeAware<O>'> <import> org.nuiton.decorator.JXPathDecorator diff --git a/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/FilterableDoubleListHandler.java b/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/FilterableDoubleListHandler.java index c7880dc..7472463 100644 --- a/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/FilterableDoubleListHandler.java +++ b/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/FilterableDoubleListHandler.java @@ -26,12 +26,12 @@ import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Lists; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.spi.UIHandler; -import jaxx.runtime.swing.JAXXButtonGroup; -import jaxx.runtime.swing.model.JaxxFilterableListModel; -import jaxx.runtime.swing.renderer.DecoratorListCellRenderer; -import jaxx.runtime.swing.renderer.FilteredDecoratorListCellRenderer; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.nuiton.jaxx.runtime.swing.JAXXButtonGroup; +import org.nuiton.jaxx.runtime.swing.model.JaxxFilterableListModel; +import org.nuiton.jaxx.runtime.swing.renderer.DecoratorListCellRenderer; +import org.nuiton.jaxx.runtime.swing.renderer.FilteredDecoratorListCellRenderer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.decorator.DecoratorUtil; diff --git a/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/FilterableDoubleListModel.java b/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/FilterableDoubleListModel.java index e434c3d..1aa2465 100644 --- a/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/FilterableDoubleListModel.java +++ b/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/FilterableDoubleListModel.java @@ -22,8 +22,8 @@ package org.nuiton.jaxx.widgets.select; * #L% */ -import jaxx.runtime.swing.model.JaxxDefaultListModel; -import jaxx.runtime.swing.model.JaxxFilterableListModel; +import org.nuiton.jaxx.runtime.swing.model.JaxxDefaultListModel; +import org.nuiton.jaxx.runtime.swing.model.JaxxFilterableListModel; import org.jdesktop.beans.AbstractSerializableBean; import org.nuiton.jaxx.widgets.ModelToBean; diff --git a/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/session/FilterableDoubleListState.java b/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/session/FilterableDoubleListState.java index 12d5ac7..0c3ebbf 100644 --- a/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/session/FilterableDoubleListState.java +++ b/jaxx-widgets-select/src/main/java/org/nuiton/jaxx/widgets/select/session/FilterableDoubleListState.java @@ -22,7 +22,7 @@ package org.nuiton.jaxx.widgets.select.session; * #L% */ -import jaxx.runtime.swing.session.State; +import org.nuiton.jaxx.runtime.swing.session.State; import org.nuiton.jaxx.widgets.select.FilterableDoubleList; /** diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/AboutPanelHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/AboutPanelHandler.java deleted file mode 100644 index 9cb6675..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/AboutPanelHandler.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.SwingUtil; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.util.Resource; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JRootPane; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; -import java.awt.Component; -import java.awt.Frame; -import java.awt.event.ActionEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.IOException; -import java.io.InputStream; - -import static org.nuiton.i18n.I18n.t; - -/** - * Handler of the ui {@link AboutPanel}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.4 - * @deprecated please use now jaxx-widgets-about module instead. - */ -@Deprecated -public class AboutPanelHandler { - - private static final Log log = LogFactory.getLog(AboutPanelHandler.class); - - protected final AboutPanel ui; - - public AboutPanelHandler(AboutPanel ui) { - this.ui = ui; - } - - final protected Action closeAction = new AbstractAction("close") { - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent e) { - JDialog container = ui.getParentContainer(JDialog.class); - if (container != null) { - container.dispose(); - } else { - ui.setVisible(false); - } - } - }; - - public void setLicenseFile(String filename) { - String load = load(filename); - ui.setLicenseText(load); - } - - public void setThirdpartyFile(String filename) { - String load = load(filename); - ui.setThirdpartyText(load); - } - - public void buildTopPanel() { - // image - JLabel labelIcon; - if (ui.iconPath != null) { - Icon logoIcon = Resource.getIcon(ui.iconPath); - labelIcon = new JLabel(logoIcon); - } else { - labelIcon = new JLabel(); - } - ui.topPanel.add(labelIcon); - } - - public void init() { - if (ui.getAboutText() == null) { - ui.tabs.remove(ui.aboutContent); - } - if (ui.getLicenseText() == null) { - ui.tabs.remove(ui.licenseContent); - } else { - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - ui.licenseTextArea.setCaretPosition(0); - } - }); - - } - if (ui.getThirdpartyText() == null) { - ui.tabs.remove(ui.thirdpartyContent); - } else { - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - ui.thirdpartyTextArea.setCaretPosition(0); - } - }); - } - } - - public void showInDialog(Frame ui, boolean undecorated) { - JDialog f = new JDialog(ui, true); - f.add(this.ui); - if (this.ui.iconPath != null) { - f.setIconImage(SwingUtil.createIcon(this.ui.iconPath).getImage()); - } - f.setResizable(false); - f.setSize(550, 450); - f.setUndecorated(undecorated); - JRootPane rootPane = f.getRootPane(); - rootPane.setDefaultButton(this.ui.close); - rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ESCAPE"), "close"); - rootPane.getActionMap().put("close", closeAction); - f.addWindowListener(new WindowAdapter() { - @Override - public void windowClosed(WindowEvent e) { - Component ui = (Component) e.getSource(); - if (log.isInfoEnabled()) { - log.info("destroy ui " + ui); - } - JAXXUtil.destroy(ui); - JAXXUtil.destroy(AboutPanelHandler.this.ui); - } - }); - SwingUtil.center(ui, f); - f.setVisible(true); - } - - protected String load(String filename) { - InputStream licenseStream = getClass().getResourceAsStream("/" + filename); - String result = null; - try { - if (licenseStream != null) { - result = IOUtils.toString(licenseStream); - } - } catch (IOException ex) { - // ignore it - } finally { - if (licenseStream != null) { - try { - licenseStream.close(); - } catch (IOException ex) { - log.error("could not close file " + filename); - } - } - } - if (result == null) { - result = "resource " + filename + " not found"; - } - return result; - } - - void $afterCompleteSetup() { - buildTopPanel(); - ui.close.setText(t("aboutframe.ok")); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/BaseActionPanel.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/BaseActionPanel.java deleted file mode 100644 index 27425f5..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/BaseActionPanel.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import javax.swing.JPanel; - -/** - * TODO sletellier 15/06/2012 : find a better way to add onActionPerform on custom components - * - * @author Sylvain Lletellier - */ -public abstract class BaseActionPanel extends JPanel { - - /** - * Notifies all listeners that have registered interest for - * notification on this event type. - * - * @see javax.swing.event.EventListenerList - */ - protected void fireActionEvent() { - ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "actionPerformed"); - - // Guaranteed to return a non-null array - Object[] listeners = listenerList.getListenerList(); - // Process the listeners last to first, notifying - // those that are interested in this event - for (Object listener : listeners) { - if (ActionListener.class.isInstance(listener)) { - ((ActionListener)listener).actionPerformed(e); - } - } - } - - /** - * Adds an <code>ActionListener</code>. - * <p> - * The <code>ActionListener</code> will receive an <code>ActionEvent</code> - * when a selection has been made. If the combo box is editable, then - * an <code>ActionEvent</code> will be fired when editing has stopped. - * - * @param l the <code>ActionListener</code> that is to be notified - */ - public void addActionListener(ActionListener l) { - listenerList.add(ActionListener.class,l); - } - - /** Removes an <code>ActionListener</code>. - * - * @param l the <code>ActionListener</code> to remove - */ - public void removeActionListener(ActionListener l) { - listenerList.remove(ActionListener.class, l); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/CompoundIcon.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/CompoundIcon.java deleted file mode 100644 index b2f072c..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/CompoundIcon.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ -package jaxx.runtime.swing; - -import java.awt.*; -import javax.swing.*; - -/** - * The CompoundIcon will paint two, or more, Icons as a single Icon. The Icons - * are painted in the order in which they are added. - * - * The Icons can be laid out - * <ul> - * <li>Horizontally - * <li>Vertically - * <li>Stacked - * </ul> - * - */ -public class CompoundIcon implements Icon { - public enum Layout { - HORIZONTAL, VERTICAL, STACKED; - } - - public final static float TOP = 0.0f; - public final static float LEFT = 0.0f; - public final static float CENTER = 0.5f; - public final static float BOTTOM = 1.0f; - public final static float RIGHT = 1.0f; - - private Icon[] icons; - - private Layout layout; - - private int gap; - - private float alignmentX = CENTER; - private float alignmentY = CENTER; - - /** - * Convenience constructor for creating a CompoundIcon where the icons are - * laid out horizontally, the gap is 0 and the X/Y alignments will default - * to CENTER. - * - * @param icons - * the Icons to be painted as part of the CompoundIcon - */ - public CompoundIcon(Icon... icons) { - this(Layout.HORIZONTAL, icons); - } - - /** - * Convenience constructor for creating a CompoundIcon where the gap is 0 - * and the X/Y alignments will default to CENTER. - * - * @param layout - * the layout used to lay out the icons for painting. - * @param icons - * the Icons to be painted as part of the CompoundIcon - */ - public CompoundIcon(Layout layout, Icon... icons) { - this(layout, 0, icons); - } - - /** - * Convenience constructor for creating a CompoundIcon where the X/Y - * alignments will default to CENTER. - * - * @param layout - * the layout used to lay out the icons for painting - * @param gap - * the gap between the icons - * @param icons - * the Icons to be painted as part of the CompoundIcon - */ - public CompoundIcon(Layout layout, int gap, Icon... icons) { - this(layout, gap, CENTER, CENTER, icons); - } - - /** - * Create a CompoundIcon specifying all the properties. - * - * @param layout - * the layout used to lay out the icons for painting - * @param gap - * the gap between the icons - * @param alignmentX - * the X alignment of the icons. Common values are LEFT, CENTER, - * RIGHT. Can be any value between 0.0 and 1.0 - * @param alignmentY - * the Y alignment of the icons. Common values are TOP, CENTER, - * BOTTOM. Can be any value between 0.0 and 1.0 - * @param icons - * the Icons to be painted as part of the CompoundIcon - */ - public CompoundIcon(Layout layout, int gap, float alignmentX, - float alignmentY, Icon... icons) { - this.layout = layout; - this.gap = gap; - this.alignmentX = alignmentX > 1.0f ? 1.0f : alignmentX < 0.0f ? 0.0f - : alignmentX; - this.alignmentY = alignmentY > 1.0f ? 1.0f : alignmentY < 0.0f ? 0.0f - : alignmentY; - - for (int i = 0; i < icons.length; i++) { - if (icons[i] == null) { - throw new IllegalArgumentException("Icon (" + i - + ") cannot be null"); - } - } - - this.icons = icons; - } - - /** - * Get the layout along which each icon is painted. - * - * @return the layout - */ - public Layout getLayout() { - return layout; - } - - /** - * Get the gap between each icon - * - * @return the gap in pixels - */ - public int getGap() { - return gap; - } - - /** - * Get the alignment of the icon on the x-layout - * - * @return the alignment - */ - public float getAlignmentX() { - return alignmentX; - } - - /** - * Get the alignment of the icon on the y-layout - * - * @return the alignment - */ - public float getAlignmentY() { - return alignmentY; - } - - /** - * Get the number of Icons contained in this CompoundIcon. - * - * @return the total number of Icons - */ - public int getIconCount() { - return icons.length; - } - - /** - * Get the Icon at the specified index. - * - * @param index - * the index of the Icon to be returned - * @return the Icon at the specified index - * @exception IndexOutOfBoundsException - * if the index is out of range - */ - public Icon getIcon(int index) { - return icons[index]; - } - - // ///// Icon Interface ///////////////////////////// - - /** - * Gets the width of this icon. - * - * @return the width of the icon in pixels. - */ - @Override - public int getIconWidth() { - int width = 0; - - // Add the width of all Icons while also including the gap - if (layout == Layout.HORIZONTAL) { - width += (icons.length - 1) * gap; - for (Icon icon : icons) - width += icon.getIconWidth(); - } else { // Just find the maximum width - for (Icon icon : icons) - width = Math.max(width, icon.getIconWidth()); - } - - return width; - } - - /** - * Gets the height of this icon. - * - * @return the height of the icon in pixels. - */ - @Override - public int getIconHeight() { - int height = 0; - - // Add the height of all Icons while also including the gap - if (layout == Layout.VERTICAL) { - height += (icons.length - 1) * gap; - - for (Icon icon : icons) - height += icon.getIconHeight(); - } else // Just find the maximum height - { - for (Icon icon : icons) - height = Math.max(height, icon.getIconHeight()); - } - - return height; - } - - /** - * Paint the icons of this compound icon at the specified location - * - * @param c The component on which the icon is painted - * - * @param g the graphics context - * - * @param x the X coordinate of the icon's top-left corner - * - * @param y the Y coordinate of the icon's top-left corner - * - */ - @Override - public void paintIcon(Component c, Graphics g, int x, int y) { - if (layout == Layout.HORIZONTAL) { - int height = getIconHeight(); - - for (Icon icon : icons) { - int iconY = getOffset(height, icon.getIconHeight(), alignmentY); - icon.paintIcon(c, g, x, y + iconY); - x += icon.getIconWidth() + gap; - } - } else if (layout == Layout.VERTICAL) { - int width = getIconWidth(); - - for (Icon icon : icons) { - int iconX = getOffset(width, icon.getIconWidth(), alignmentX); - icon.paintIcon(c, g, x + iconX, y); - y += icon.getIconHeight() + gap; - } - } else {// must be Z_layout - - int width = getIconWidth(); - int height = getIconHeight(); - - for (Icon icon : icons) { - int iconX = getOffset(width, icon.getIconWidth(), alignmentX); - int iconY = getOffset(height, icon.getIconHeight(), alignmentY); - icon.paintIcon(c, g, x + iconX, y + iconY); - } - } - } - - /* - * When the icon value is smaller than the maximum value of all icons the - * icon needs to be aligned appropriately. Calculate the offset to be used - * when painting the icon to achieve the proper alignment. - */ - private int getOffset(int maxValue, int iconValue, float alignment) { - float offset = (maxValue - iconValue) * alignment; - return Math.round(offset); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/ErrorDialogUIHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/ErrorDialogUIHandler.java deleted file mode 100644 index 5bc7c88..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/ErrorDialogUIHandler.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.SwingUtil; - -import javax.swing.InputMap; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JRootPane; -import javax.swing.KeyStroke; -import java.awt.Dialog; -import java.awt.Frame; -import java.io.PrintWriter; -import java.io.StringWriter; - -/** - * Handler of ui {@link ErrorDialogUI}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0 - */ -public class ErrorDialogUIHandler { - - protected final ErrorDialogUI ui; - - public ErrorDialogUIHandler(ErrorDialogUI ui) { - this.ui = ui; - } - - public static void init(Frame frame) { - disposeUI(); - ErrorDialogUI.instance = new ErrorDialogUI(frame); - ErrorDialogUI.instance.setModalityType(Dialog.ModalityType.TOOLKIT_MODAL); - } - - public static void showError(Exception e) { - ErrorDialogUI instance = ErrorDialogUI.instance; - if (instance == null) { - instance = new ErrorDialogUI(); - } - instance.getErrorMessage().setText(e.getMessage()); - StringWriter w = new StringWriter(); - PrintWriter writer = new PrintWriter(w); - try { - e.printStackTrace(writer); - instance.getErrorStack().setText(w.toString()); - } finally { - writer.close(); - } - instance.getErrorStack().setCaretPosition(0); - instance.pack(); - SwingUtil.center(instance.getContextValue(JFrame.class, "parent"), instance); - instance.setVisible(true); - } - - public static void disposeUI() { - ErrorDialogUI instance = ErrorDialogUI.instance; - if (instance != null) { - JAXXUtil.destroy(instance); - } - ErrorDialogUI.instance = null; - } - - void $afterCompleteSetup() { - JRootPane rootPane = ui.getRootPane(); - - JButton close = ui.close; - rootPane.setDefaultButton(close); - InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); - inputMap.put(KeyStroke.getKeyStroke("ESCAPE"), "close"); - rootPane.getActionMap().put("close", close.getAction()); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/FontSizorHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/FontSizorHandler.java deleted file mode 100644 index a0c85a6..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/FontSizorHandler.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import jaxx.runtime.binding.SimpleJAXXObjectBinding; - -/** - * Handler of ui {@link FontSizor}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0 - */ -public class FontSizorHandler { - - protected final FontSizor ui; - - public FontSizorHandler(FontSizor ui) { - this.ui = ui; - } - - public static final String BINDING_FONT_SIZE_CALL_BACK = "fontSize.callBack"; - - public static final String BINDING_DEFAULT_FONT_SIZE_CALL_BACK = "defaultFontSize.callBack"; - - public void init() { - if (ui.fontSize == null) { - ui.setFontSize(ui.defaultFontSize); - } - } - - boolean updateDefaultSizeEnabled(Float fontSize, - Float defaultFontSize, - boolean enabled) { - if (fontSize == null || defaultFontSize == null) { - return false; - } - return !fontSize.equals(defaultFontSize) && enabled; - } - - public void setCallBack(final Runnable action) { - ui.removeDataBinding(BINDING_FONT_SIZE_CALL_BACK); - ui.registerDataBinding(new SimpleJAXXObjectBinding(ui, BINDING_FONT_SIZE_CALL_BACK, true, "fontSize") { - - @Override - public void processDataBinding() { - action.run(); - } - }); - ui.applyDataBinding(BINDING_FONT_SIZE_CALL_BACK); - } - - void $afterCompleteSetup() { - ui.registerDataBinding(new SimpleJAXXObjectBinding(ui, BINDING_DEFAULT_FONT_SIZE_CALL_BACK, true, "defaultFontSize") { - - @Override - public void processDataBinding() { - ui.setFontSize(ui.defaultFontSize); - } - }); - //applyDataBinding(BINDING_DEFAULT_FONT_SIZE_CALL_BACK); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/HidorButtonHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/HidorButtonHandler.java deleted file mode 100644 index 2f93ab1..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/HidorButtonHandler.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.Icon; -import javax.swing.JComponent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -/** - * Handler of ui {@link HidorButton}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0 - */ -public class HidorButtonHandler { - - private static final Log log = - LogFactory.getLog(HidorButtonHandler.class); - - protected final HidorButton ui; - - public HidorButtonHandler(HidorButton ui) { - this.ui = ui; - } - - void $afterCompleteSetup() { - - ui.addPropertyChangeListener("targetVisible", new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (log.isDebugEnabled()) { - log.debug("target visible changed <" + evt.getOldValue() + ":" + evt.getNewValue() + ">"); - } - boolean newValue = (Boolean) evt.getNewValue(); - if (ui.target != null) { - ui.target.setVisible(newValue); - } - } - }); - } - - public void setTarget(JComponent target) { - JComponent oldValue = ui.target; - ui.target = target; - ui.firePropertyChange("target", oldValue, target); - } - - public void setExpandIcon(Icon icon) { - ui.putClientProperty("expandIcon", icon); - } - - public void setHideIcon(Icon icon) { - ui.putClientProperty("hideIcon", icon); - } - - protected String updateToolTipText(boolean c) { - return c ? ui.hideTip : ui.showTip; - } - - protected String updateText(boolean c) { - return c ? ui.hideText : ui.showText; - } - - protected Icon updateIcon(boolean c) { - String key = c ? "hideIcon" : "showIcon"; - return (Icon) ui.getClientProperty(key); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/JAXXRuntimeException.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/JAXXRuntimeException.java deleted file mode 100644 index a8df576..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/JAXXRuntimeException.java +++ /dev/null @@ -1,48 +0,0 @@ -package jaxx.runtime.swing; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -/** - * A special runtime exception to catch special errors fro - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.5.19 - */ -public class JAXXRuntimeException extends RuntimeException { - private static final long serialVersionUID = -2963740979386945340L; - - public JAXXRuntimeException() { - } - - public JAXXRuntimeException(String message) { - super(message); - } - - public JAXXRuntimeException(String message, Throwable cause) { - super(message, cause); - } - - public JAXXRuntimeException(Throwable cause) { - super(cause); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/JAXXWidgetUtil.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/JAXXWidgetUtil.java deleted file mode 100644 index 7fbc7b8..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/JAXXWidgetUtil.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableCellRenderer; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.swing.editor.cell.DateCellEditor; -import jaxx.runtime.swing.editor.cell.FileCellEditor; -import jaxx.runtime.swing.editor.cell.KeyStrokeCellEditor; -import jaxx.runtime.swing.editor.cell.NumberCellEditor; -import jaxx.runtime.swing.renderer.DateCellRenderer; - -/** - * @author Sylvain Lletellier - */ -public class JAXXWidgetUtil extends SwingUtil { - - public static TableCellRenderer newDateTableCellRenderer(TableCellRenderer renderer) { - return newDateTableCellRenderer(renderer, null); - } - - public static TableCellRenderer newDateTableCellRenderer(TableCellRenderer renderer, String datePattern) { - return new DateCellRenderer(renderer, datePattern); - } - - public static TableCellEditor newDateTableCellEditor() { - return new DateCellEditor(); - } - - public static TableCellEditor newFileTableCellEditor() { - return new FileCellEditor(); - } - - public static TableCellEditor newKeyStrokeTableCellEditor() { - return new KeyStrokeCellEditor(); - } - - public static <E extends Number> NumberCellEditor<E> newNumberTableCellEditor(Class<E> type, boolean useSign) { - return new NumberCellEditor<E>(type, useSign); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/JSearchTextField.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/JSearchTextField.java deleted file mode 100644 index 67ec343..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/JSearchTextField.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ -package jaxx.runtime.swing; - -import jaxx.runtime.swing.JAXXWidgetUtil; - -import java.awt.Graphics; -import java.awt.Image; - -import javax.swing.ImageIcon; -import javax.swing.JTextField; - -/** - * A text field with search symbol painted to indicate - * that it is used as search field - * - * @author Eugene Ryzhikov - * @since 2.13 - * - */ -public class JSearchTextField extends JTextField { - - private static final String ICON_NAME = "search.png"; - private static final long serialVersionUID = 1L; - - private static ImageIcon icon; - - private static Image getScaledImage( int size ) { - - if (icon == null) { - icon = JAXXWidgetUtil.createImageIcon(ICON_NAME); - } - return new ImageIcon(icon.getImage().getScaledInstance( size, size, Image.SCALE_SMOOTH )).getImage(); - } - - private static int PAD = 4; - private static int PAD2 = PAD*2; - - @Override - public void paint(Graphics g) { - super.paint(g); - int size = getHeight()-PAD2; - g.drawImage( getScaledImage(size), getWidth()-size-PAD, PAD, null); - } - -} - diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListSelector.jaxx b/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListSelector.jaxx deleted file mode 100644 index c3cd011..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListSelector.jaxx +++ /dev/null @@ -1,77 +0,0 @@ -<!-- - #%L - JAXX :: Widgets - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<Table insets='0' genericType='B' abstract='true'> - - <import> - com.google.common.collect.Lists - java.util.List - javax.swing.DefaultComboBoxModel - javax.swing.DefaultListModel - javax.swing.DefaultListCellRenderer - java.beans.PropertyChangeEvent - java.beans.PropertyChangeListener - javax.swing.event.ListDataListener - jaxx.runtime.swing.model.GenericListModel - jaxx.runtime.swing.model.GenericListListener - java.util.Collection - java.util.Set - </import> - - <String id='addToolTip' javaBean='"+"'/> - - <String id='removeToolTip' javaBean='"-"'/> - - <ListSelectorModel id='model' - genericType='B' - javaBean='null'/> - - <ListCellRenderer id='renderer' javaBean='new DefaultListCellRenderer()'/> - - <script><![CDATA[ - -public void setValues(Collection<B> values) { - model.setValues(values); -} - -public Collection<B> getValues() { - return model.getValues(); -} - -public void setSelectedValues(Collection<B> selectedValues) { - model.setSelectedValues(selectedValues); -} - -public Collection<B> getSelectedValues() { - return model.getSelectedValues(); -} - -public void addGenericListListener(GenericListListener l) { - model.addGenericListListener(l); -} - -public void removeGenericListListener(GenericListListener l) { - model.removeGenericListListener(l); -} -]]> - </script> - -</Table> diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListSelectorModel.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListSelectorModel.java deleted file mode 100644 index 581356e..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListSelectorModel.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import com.google.common.collect.Lists; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.util.Collection; -import jaxx.runtime.swing.model.GenericListListener; -import jaxx.runtime.swing.model.GenericListModel; - -/** - * @author Sylvain Lletellier - */ -public class ListSelectorModel<B> { - - protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this); - - public static final String PROPERTY_ADD_ENABLED = "addEnabled"; - public static final String PROPERTY_REMOVE_ENABLED = "removeEnabled"; - - public static final String PROPERTY_SELECTED_VALUES = "selectedValues"; - public static final String PROPERTY_VALUES = "values"; - - protected boolean addEnabled; - protected boolean removeEnabled; - - protected GenericListModel<B> fromModel; - protected GenericListModel<B> toModel; - - protected ListSelectorModel() { - - fromModel = new GenericListModel<B>(); - fromModel.addPropertyChangeListener(GenericListModel.PROPERTY_SELECTED_VALUE, new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - setAddEnabled(fromModel.hasSelectedIndex()); - } - }); - - toModel = new GenericListModel<B>(); - toModel.addPropertyChangeListener(GenericListModel.PROPERTY_SELECTED_VALUE, new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - setRemoveEnabled(toModel.hasSelectedIndex()); - } - }); - } - - public boolean isAddEnabled() { - return addEnabled; - } - - public void setAddEnabled(boolean addEnabled) { - boolean oldValue = isAddEnabled(); - this.addEnabled = addEnabled; - firePropertyChange(PROPERTY_ADD_ENABLED, oldValue, addEnabled); - } - - public boolean isRemoveEnabled() { - return removeEnabled; - } - - public void setRemoveEnabled(boolean removeEnabled) { - boolean oldValue = isRemoveEnabled(); - this.removeEnabled = removeEnabled; - firePropertyChange(PROPERTY_REMOVE_ENABLED, oldValue, removeEnabled); - } - - public GenericListModel<B> getFromModel() { - return fromModel; - } - - public GenericListModel<B> getToModel() { - return toModel; - } - - public Collection<B> getValues() { - return fromModel.getElements(); - } - - public void setValues(Collection<B> values) { - Collection<B> oldValues = getValues(); - toModel.clearElements(); - fromModel.setElements(values); - firePropertyChange(PROPERTY_VALUES, oldValues, values); - } - - public void addValues(Collection<B> values) { - Collection<B> oldValues = getValues(); - toModel.removeElements(values); - fromModel.removeElements(values); - fromModel.addElements(values); - firePropertyChange(PROPERTY_VALUES, oldValues, values); - } - - public void removeValues(Collection<B> values) { - Collection<B> oldValues = getValues(); - toModel.removeElements(values); - fromModel.removeElements(values); - firePropertyChange(PROPERTY_VALUES, oldValues, values); - } - - public Collection<B> getSelectedValues() { - return toModel.getElements(); - } - - public void setSelectedValues(Collection<B> selectedValues) { - Collection<B> oldValue = getSelectedValues(); - fromModel.removeElements(selectedValues); - toModel.removeElements(selectedValues); - toModel.setElements(selectedValues); - firePropertyChange(PROPERTY_SELECTED_VALUES, oldValue, selectedValues); - } - - public void add() { - Collection<B> oldValues = getValues(); - Collection<B> oldSelectedValue = getSelectedValues(); - moveSelect(fromModel, toModel); - firePropertyChange(PROPERTY_VALUES, oldValues, getValues()); - firePropertyChange(PROPERTY_SELECTED_VALUES, oldSelectedValue, getSelectedValues()); - } - - public void remove() { - moveSelect(toModel, fromModel); - } - - protected void moveSelect(GenericListModel<B> from, GenericListModel<B> to) { - Collection<B> selectedValues = Lists.newArrayList(from.getSelectedValues()); - from.removeElements(selectedValues); - to.addElements(selectedValues); - } - - public void addGenericListListener(GenericListListener l) { - toModel.addGenericListListener(l); - } - - public void removeGenericListListener(GenericListListener l) { - toModel.removeGenericListListener(l); - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - pcs.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { - pcs.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - pcs.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { - pcs.removePropertyChangeListener(propertyName, listener); - } - - protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { - pcs.firePropertyChange(propertyName, oldValue, newValue); - } - - protected void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) { - pcs.fireIndexedPropertyChange(propertyName, index, oldValue, newValue); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/MemoryStatusWidgetHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/MemoryStatusWidgetHandler.java deleted file mode 100644 index 38cede6..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/MemoryStatusWidgetHandler.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing; - -import javax.swing.JLabel; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Insets; -import java.awt.font.FontRenderContext; -import java.awt.font.LineMetrics; -import java.awt.geom.Rectangle2D; - -import static org.nuiton.i18n.I18n.t; - -/** - * Handler of ui {@link MemoryStatusWidget}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0 - */ -public class MemoryStatusWidgetHandler { - - private final static String memoryTestStr = "99999/99999Mb"; - - private FontRenderContext frc = new FontRenderContext(null, false, false); - - private LineMetrics lm = new JLabel().getFont().getLineMetrics(memoryTestStr, frc); - - protected final MemoryStatusWidget ui; - - public MemoryStatusWidgetHandler(MemoryStatusWidget ui) { - this.ui = ui; - } - - public void paintComponent(Graphics g) { - Insets insets = new Insets(0, 0, 0, 0); - Runtime runtime = Runtime.getRuntime(); - int freeMemory = (int) (runtime.freeMemory() / 1024L); - int totalMemory = (int) (runtime.totalMemory() / 1024L); - int usedMemory = totalMemory - freeMemory; - int width = ui.getWidth() - insets.left - insets.right; - int height = ui.getHeight() - insets.top - insets.bottom - 1; - float fraction = (float) usedMemory / (float) totalMemory; - g.setColor(ui.progressBackground); - g.fillRect(insets.left, insets.top, (int) ((float) width * fraction), height); - // No i18n string was : - // String str = usedMemory / 1024 + "/" + totalMemory / 1024 + "Mb"; - String str = t("memorywidget.memory", usedMemory / 1024, totalMemory / 1024); - //FontRenderContext frc = new FontRenderContext(null, false, false); - Rectangle2D bounds = g.getFont().getStringBounds(str, frc); - Graphics g2 = g.create(); - g2.setClip(insets.left, insets.top, - (int) ((float) width * fraction), height); - g2.setColor(ui.progressForeground); - g2.drawString(str, insets.left - + (int) ((double) width - bounds.getWidth()) / 2, - (int) ((float) insets.top + lm.getAscent())); - g2.dispose(); - g2 = g.create(); - g2.setClip(insets.left + (int) ((float) width * fraction), - insets.top, ui.getWidth() - insets.left - - (int) ((float) width * fraction), height); - g2.setColor(ui.getForeground()); - g2.drawString(str, insets.left - + (int) ((double) width - bounds.getWidth()) / 2, - (int) ((float) insets.top + lm.getAscent())); - g2.dispose(); - } - - - void $afterCompleteSetup() { - ui.setFont(new JLabel().getFont()); - Rectangle2D bounds = ui.getFont().getStringBounds(memoryTestStr, frc); - Dimension dim = new Dimension((int) bounds.getWidth(), (int) bounds.getHeight()); - ui.setPreferredSize(dim); - ui.setMaximumSize(dim); - } - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/StatusMessagePanelHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/StatusMessagePanelHandler.java deleted file mode 100644 index 14df7f9..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/StatusMessagePanelHandler.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.runtime.swing; - -import javax.swing.Timer; -import java.awt.Color; -import java.awt.Dimension; - -/** - * @author Tony Chemit - chemit@codelutin.com - * @since 1.6.0 - */ -public class StatusMessagePanelHandler { - - protected final StatusMessagePanel ui; - - protected Color statusForeground; - - protected String statusReferenceContent; - - protected Timer timer; - - public StatusMessagePanelHandler(StatusMessagePanel ui) { - this.ui = ui; - } - - void $afterCompleteSetup() { - init(); - } - - public void init() { - if (ui.isShowBusy()) { - Dimension dim = new Dimension(30, 15); - //Dimension dim = new Dimension(30, (int) statusLabel.getPreferredSize().getHeight()); - //log.info("dimension of busy = "+ dim); - //busyWidget.setPreferredSize(dim); - ui.busyWidget.setMaximumSize(dim); - ui.busyWidget.setMinimumSize(dim); - } - } - - public void clearStatus() { - stopStatusFader(ui); - ui.getStatusLabel().setText(StatusMessagePanel.EMPTY_STATUS); - //getStatusLabel().setString(EMPTY_STATUS); - } - - public void setStatus(String status) { - if (status != null) { - stopStatusFader(ui); - ui.getStatusLabel().setText(status); - //getStatusLabel().setString(status); - } - - if (!ui.isBusy()) { - startStatusFader(ui); - } - } - - protected void fadeStatus(StatusMessagePanel ui) { - for (int i = 0; i < 8; i++) { - // synchronized (this) { - if (!statusReferenceContent.equals(ui.getStatusLabel().getText())) { -// if (!statusReferenceContent.equals(ui.getStatusLabel().getString())) { - return; - } - Color currentForeground = ui.getStatusLabel().getForeground(); - Color newColor = new Color(currentForeground.getRed(), - currentForeground.getGreen(), - currentForeground.getBlue(), - currentForeground.getAlpha() - 25); - ui.getStatusLabel().setForeground(newColor); - ui.getStatusLabel().repaint(); - // } - // TC-2000311 je comprends pas a quoi ca sert, a part frizzer les ui ? - // si on utilise un Timer, pourquoi utiliser ça ? - /*try { - Thread.sleep(200); - } catch (InterruptedException eee) { - eee.printStackTrace(); - }*/ - } - } - - protected void startStatusFader(StatusMessagePanel ui) { - statusReferenceContent = ui.getStatusLabel().getText(); -// statusReferenceContent = ui.getStatusLabel().getString(); - - int millisecondsPerMinute = 5000; - timer = new Timer(millisecondsPerMinute, ui); - timer.setRepeats(false); - timer.setInitialDelay((int) ((long) millisecondsPerMinute - - System.currentTimeMillis() % - (long) millisecondsPerMinute) + 500); - timer.start(); - } - - protected void stopStatusFader(StatusMessagePanel ui) { - if (timer != null) { - timer.stop(); - ui.getStatusLabel().setForeground(statusForeground); - } - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/FileEditor.jaxx b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/FileEditor.jaxx deleted file mode 100644 index e63cc0d..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/FileEditor.jaxx +++ /dev/null @@ -1,111 +0,0 @@ -<!-- - #%L - JAXX :: Widgets - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<BaseActionPanel layout='{new BorderLayout()}'> - <import> - jaxx.runtime.swing.BaseActionPanel - - org.apache.commons.lang3.StringUtils - - javax.swing.JDialog - java.io.File - </import> - - <FileEditorHandler id='handler' constructorParams='this'/> - - <Boolean id='acceptAllFileFilterUsed' javaBean='Boolean.TRUE'/> - - <Boolean id='directoryEnabled' javaBean='Boolean.TRUE'/> - - <Boolean id='fileEnabled' javaBean='Boolean.TRUE'/> - - <String id='startPath' javaBean='null'/> - - <String id='title' javaBean='null'/> - - <String id='exts' javaBean='null'/> - - <String id='extsDescription' javaBean='null'/> - - <!-- show reset property --> - <Boolean id='showReset' javaBean='false'/> - - <script><![CDATA[ -protected File selectedFile; - -public void setSelectedFile(File selectedFile) { - this.selectedFile = selectedFile; - setStartPath(selectedFile == null ? null : selectedFile.getAbsolutePath()); - fireActionEvent(); -} - -public void setSelectedFilePath(String startPath) { - setSelectedFile(startPath == null ? null : new File(startPath)); -} - -/**public void setSelectedFile(String startPath) { - this.selectedFile = null; - setStartPath(startPath); - fireActionEvent(); -}*/ - -public File getSelectedFile() { - if (selectedFile == null) { - if (StringUtils.isNotEmpty(startPath)) { - selectedFile = new File(startPath); - } - } - return selectedFile; -} - -public void setDialogOwner(JDialog dialogOwner) { - handler.setDialogOwner(dialogOwner); -} - - ]]></script> - - <JToolBar id='toolbar' - floatable='false' - borderPainted='false' - visible='{isShowReset()}' - constraints='BorderLayout.WEST'> - <JButton id='resetButton' - actionIcon='fileeditor-reset' - toolTipText='fileeditor.action.reset.tip' - focusable='false' - focusPainted='false' - enabled='{isEnabled()}' - onActionPerformed='setSelectedFile(null)'/> - </JToolBar> - - - <JTextField id='pathField' - constraints='BorderLayout.CENTER' - enabled='{isEnabled()}' - text='{getStartPath()}' - onKeyReleased='setSelectedFilePath(pathField.getText())'/> - - <JButton id='boutonXslLocation' - constraints='BorderLayout.EAST' - enabled='{isEnabled()}' - actionIcon='open' - onActionPerformed='handler.openLocation()'/> -</BaseActionPanel> diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/FileEditorHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/FileEditorHandler.java deleted file mode 100644 index d6173ea..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/FileEditorHandler.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.editor; - -import com.google.common.io.Files; -import org.apache.commons.lang3.StringUtils; - -import javax.swing.JDialog; -import javax.swing.JFileChooser; -import javax.swing.filechooser.FileFilter; -import java.io.File; - -/** @author Sylvain Lletellier */ -public class FileEditorHandler { - - public static final String SEPARATOR_REGEX = "\\s*,\\s*"; - - public static File lastSelectedPath; - - protected FileEditor view; - - /** - * To set the dialog (see https://forge.nuiton.org/issues/2578). - * - * @since 2.5.12 - */ - protected JDialog dialogOwner; - - public FileEditorHandler(FileEditor view) { - this.view = view; - if (lastSelectedPath == null) { - lastSelectedPath = new File(System.getProperty("user.home")); - } - } - - public void openLocation() { - - // use last selected file - File startFile = view.getSelectedFile(); - String startPath = view.getStartPath(); - if (startFile == null && StringUtils.isNotEmpty(startPath)) { - - // else filed start path - startFile = new File(startPath); - } else if (startFile == null) { - - // else start with user home - startFile = lastSelectedPath; - } - JFileChooser fc = new JFileChooser(startFile); - - fc.setDialogTitle(view.getTitle()); - fc.setAcceptAllFileFilterUsed(view.getAcceptAllFileFilterUsed()); - - // TODO sletellier 14/06/2012 : activate multi selection -// boolean multiSelectionEnabled = view.isMultiSelectionEnabled(); -// fc.setMultiSelectionEnabled(multiSelectionEnabled); - - // used to enable directory selection - boolean directoryEnabled = view.isDirectoryEnabled(); - if (directoryEnabled) { - fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - } - - // used to enable file selection - boolean fileEnabled = view.isFileEnabled(); - if (fileEnabled) { - - if (directoryEnabled) { - - // both - fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - } else { - fc.setFileSelectionMode(JFileChooser.FILES_ONLY); - } - String extsAsString = view.getExts(); - if (extsAsString != null) { - - // extentions can be separted by comma - String[] exts = extsAsString.split(SEPARATOR_REGEX); - String extsDescription = view.getExtsDescription(); - - String[] descs = new String[0]; - if (extsDescription != null) { - descs = extsDescription.split(SEPARATOR_REGEX); - } - for (int i = 0;i<exts.length;i++) { - - // use ext if no desc found - String ext = exts[i]; - String desc = ext; - if (descs.length > i) { - desc = descs[i]; - } - - fc.addChoosableFileFilter(new ExtentionFileFiler(ext, desc)); - } - } - } - - // directory or/and file must be enabled - if (!directoryEnabled && !fileEnabled) { - throw new IllegalArgumentException("You must enable at least file or directory to open dialog"); - } - - // show dialog - // see https://forge.nuiton.org/issues/2578 - boolean hackDialog = dialogOwner != null && dialogOwner.isAlwaysOnTop(); - if (hackDialog) { - dialogOwner.setAlwaysOnTop(false); - } - int returnVal = fc.showOpenDialog(view); - if (hackDialog) { - dialogOwner.setAlwaysOnTop(true); - } - if (returnVal == JFileChooser.APPROVE_OPTION) { - - // get selected to display in ui - File file = fc.getSelectedFile(); - - setSelectedFile(file); - } - } - - public void setSelectedFile(String path) { - setSelectedFile(new File(path)); - } - - public void setSelectedFile(File file) { - view.setSelectedFile(file); - view.setStartPath(file.getPath()); - File dir = file; - if (dir.exists()) { - if (!dir.isDirectory()) { - dir = dir.getParentFile(); - } - lastSelectedPath = dir; - } - } - - protected void setDialogOwner(JDialog dialogOwner) { - this.dialogOwner = dialogOwner; - } - - public static class ExtentionFileFiler extends FileFilter { - protected String ext; - protected String desciption; - - public ExtentionFileFiler(String ext, String desciption) { - this.ext = ext; - this.desciption = desciption; - } - - @Override - public boolean accept(File file) { - if (file.isDirectory()) { - return true; - } - String fileExtension = Files.getFileExtension(file.getName()); - return ext.equals(fileExtension); - } - - @Override - public String getDescription() { - return desciption; - } - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/I18nEditor.jaxx b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/I18nEditor.jaxx deleted file mode 100644 index 541f363..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/I18nEditor.jaxx +++ /dev/null @@ -1,144 +0,0 @@ -<!-- - #%L - JAXX :: Widgets - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - - -<JPanel implements='PropertyChangeListener, ActionListener' - id='content' - layout='{new BorderLayout()}' - onFocusGained='button.requestFocus()' - onFocusLost='setPopupVisible(false)'> - - <import> - - jaxx.runtime.SwingUtil - - java.awt.BorderLayout - java.awt.event.ItemEvent - java.awt.event.ActionEvent - java.awt.event.ActionListener - javax.swing.border.TitledBorder - - java.beans.PropertyChangeListener - java.beans.PropertyChangeEvent - java.util.Locale - - jaxx.runtime.swing.renderer.LocaleListCellRenderer - - static org.nuiton.i18n.I18n.n - </import> - - <I18nEditorHandler id='handler' constructorParams='this'/> - - <String id='selectedToolTipText' javaBean='null'/> - <String id='notSelectedToolTipText' javaBean='null'/> - - <Border id='popupBorder' - javaBean='new TitledBorder(t("i18neditor.popup.title"))'/> - - <Boolean id='showText' javaBean='Boolean.TRUE'/> - <Boolean id='showIcon' javaBean='Boolean.TRUE'/> - <Boolean id='showPopupText' javaBean='Boolean.TRUE'/> - <Boolean id='showPopupIcon' javaBean='Boolean.TRUE'/> - <Boolean id='popupVisible' javaBean='Boolean.FALSE'/> - - <java.util.List id='locales' javaBean='null' genericType='Locale'/> - - <Locale id='selectedLocale' javaBean='Locale.getDefault()'/> - - <LocaleListCellRenderer id='renderer' - showIcon='{isShowIcon()}' - showText='{isShowText()}' - javaBean='new LocaleListCellRenderer(showIcon , showText)'/> - - <!-- popup to change sorted property--> - <JPopupMenu id='popup' - border='{getPopupBorder()}' - onPopupMenuWillBecomeInvisible='button.setSelected(false)' - onPopupMenuCanceled='button.setSelected(false)'> - <JLabel id='popupLabel' enabled='false' text='i18neditor.empty.locales'/> - </JPopupMenu> - - <JToggleButton - id='button' - text='{SwingUtil.getStringValue(renderer.getText(getSelectedLocale()))}' - toolTipText='{getTip(getSelectedLocale())}' - icon='{renderer.getIcon(getSelectedLocale())}' - constraints='BorderLayout.CENTER' - selected='{popup.isVisible()}' - focusable='true' - focusPainted='false' - onItemStateChanged='if (event.getStateChange() == ItemEvent.SELECTED) { setPopupVisible(true); } else { popupVisible = false; }'/> - - <ButtonGroup id='indexes' - onStateChanged='log.info(indexes.getSelectedValue())'/> - - <script><![CDATA[ -public static final String DEFAULT_SELECTED_TOOLTIP = n("i18neditor.selected"); -public static final String DEFAULT_NOT_SELECTED_TOOLTIP = n("i18neditor.unselected"); - -public static final String LOCALES_PROPERTY = "locales"; -public static final String SELECTED_LOCALE_PROPERTY = "selectedLocale"; -public static final String SHOW_ICON_PROPERTY = "showIcon"; -public static final String SHOW_TEXT_PROPERTY = "showText"; -public static final String SHOW_POPUP_ICON_PROPERTY = "showPopupIcon"; -public static final String SHOW_POPUP_TEXT_PROPERTY = "showPopupText"; -public static final String POPUP_BORDER_PROPERTY = "popupBorder"; -public static final String POPUP_VISIBLE_PROPERTY = "popupVisible"; - - - -void $afterCompleteSetup() { - handler.$afterCompleteSetup(); -} - -@Override -public void propertyChange(PropertyChangeEvent evt) { - handler.propertyChange(evt); -} - -@Override -public void actionPerformed(ActionEvent event) { - handler.actionPerformed(event); -} - -public void loadI18nBundles() { - handler.loadI18nBundles(); -} - -protected void rebuildPopup() { - handler.rebuildPopup(); -} - -protected String getTip(Locale l) { - return handler.getTip(l); -} - -protected String getSelectedTip(Locale l) { - return handler.getSelectedTip(l); -} - -protected String getNotSelectedTip(Locale l) { - return handler.getNotSelectedTip(l); -} -]]> - </script> -</JPanel> diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/I18nEditorHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/I18nEditorHandler.java deleted file mode 100644 index d873aed..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/I18nEditorHandler.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.editor; - -import jaxx.runtime.swing.JAXXButtonGroup; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.i18n.I18n; - -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JRadioButtonMenuItem; -import javax.swing.JToggleButton; -import javax.swing.SwingUtilities; -import javax.swing.border.Border; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.Arrays; -import java.util.Collection; -import java.util.Locale; - -import static org.nuiton.i18n.I18n.t; -import static org.nuiton.i18n.I18n.n; - -/** - * Handler of ui {@link I18nEditor}. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.0 - */ -public class I18nEditorHandler implements PropertyChangeListener, ActionListener { - - private static final Log log = LogFactory.getLog(I18nEditorHandler.class); - - protected final I18nEditor ui; - - public I18nEditorHandler(I18nEditor ui) { - this.ui = ui; - } - - public static final String DEFAULT_SELECTED_TOOLTIP = n("i18neditor.selected"); - - public static final String DEFAULT_NOT_SELECTED_TOOLTIP = n("i18neditor.unselected"); - - public static final String LOCALES_PROPERTY = "locales"; - - public static final String SELECTED_LOCALE_PROPERTY = "selectedLocale"; - - public static final String SHOW_ICON_PROPERTY = "showIcon"; - - public static final String SHOW_TEXT_PROPERTY = "showText"; - - public static final String SHOW_POPUP_ICON_PROPERTY = "showPopupIcon"; - - public static final String SHOW_POPUP_TEXT_PROPERTY = "showPopupText"; - - public static final String POPUP_BORDER_PROPERTY = "popupBorder"; - - public static final String POPUP_VISIBLE_PROPERTY = "popupVisible"; - - @Override - public void propertyChange(PropertyChangeEvent evt) { - String name = evt.getPropertyName(); - if (log.isDebugEnabled()) { - log.debug(name + " <old:" + evt.getOldValue() + " - new:" + evt.getNewValue() + ">"); - } - log.info(name + " <old:" + evt.getOldValue() + " - new:" + evt.getNewValue() + ">"); - if (LOCALES_PROPERTY.equals(name)) { - Collection<?> newLocales = (Collection<?>) evt.getNewValue(); - // mise a jour de la popup - boolean oldShowText = ui.renderer.isShowText(); - try { - ui.renderer.setShowText(true); - ui.popup.removeAll(); - for (Object o : newLocales) { - Locale l = (Locale) o; - boolean selected = l.equals(ui.selectedLocale); - String text = ui.isShowPopupText() ? ui.renderer.getText(l) : null; - Icon icon = ui.isShowPopupIcon() ? ui.renderer.getIcon(l) : null; - JRadioButtonMenuItem b = new JRadioButtonMenuItem(text, icon, selected); - ui.popup.add(b); - b.addActionListener(ui); - b.putClientProperty("locale", l); - b.setToolTipText(getTip(l)); - b.putClientProperty(JAXXButtonGroup.BUTTON8GROUP_CLIENT_PROPERTY, ui.getIndexes()); - b.putClientProperty(JAXXButtonGroup.VALUE_CLIENT_PROPERTY, l); - } - } finally { - ui.renderer.setShowText(oldShowText); - ui.popup.invalidate(); - } - return; - } - if (SHOW_ICON_PROPERTY.equals(name)) { - ui.renderer.setShowIcon((Boolean) evt.getNewValue()); - ui.processDataBinding("button.icon"); - return; - } - if (SHOW_TEXT_PROPERTY.equals(name)) { - ui.renderer.setShowText((Boolean) evt.getNewValue()); - ui.processDataBinding("button.text"); - return; - } - if (SHOW_POPUP_ICON_PROPERTY.equals(name)) { - rebuildPopup(); - return; - } - if (SHOW_POPUP_TEXT_PROPERTY.equals(name)) { - rebuildPopup(); - return; - } - if (POPUP_BORDER_PROPERTY.equals(name)) { - ui.popup.setBorder((Border) evt.getNewValue()); - return; - } - if (POPUP_VISIBLE_PROPERTY.equals(name)) { - Boolean newValue = (Boolean) evt.getNewValue(); - if (newValue == null || !newValue) { - if (ui.getPopup() != null && ui.getPopup().isVisible()) { - ui.getPopup().setVisible(false); - } - return; - } - if (!ui.getPopup().isVisible()) { - SwingUtilities.invokeLater(showPopupRunnable); - } - return; - } - if (SELECTED_LOCALE_PROPERTY.equals(name)) { - Locale newLocale = (Locale) evt.getNewValue(); - // mise a jour de la popup - try { - for (Component c : ui.popup.getComponents()) { - if (c instanceof JRadioButtonMenuItem) { - JRadioButtonMenuItem b = (JRadioButtonMenuItem) c; - Locale l = (Locale) b.getClientProperty("locale"); - b.setSelected(newLocale.equals(l)); - } - } - } finally { - ui.popup.invalidate(); - } - } - } - - @Override - public void actionPerformed(ActionEvent event) { - Locale value = (Locale) - ((JComponent) event.getSource()).getClientProperty("locale"); - if (log.isDebugEnabled()) { - log.debug("new locale : " + value); - } - ui.setSelectedLocale(value); - } - - public void loadI18nBundles() { - Locale[] locales = I18n.getStore().getLocales(); - ui.setLocales(Arrays.asList(locales)); - } - - protected void rebuildPopup() { - log.debug("start rebuild"); - try { - for (Component c : ui.popup.getComponents()) { - if (c instanceof JRadioButtonMenuItem) { - JRadioButtonMenuItem b = (JRadioButtonMenuItem) c; - Locale l = (Locale) b.getClientProperty("locale"); - String text = ui.isShowPopupText() ? ui.renderer.getSafeText(l) : null; - Icon icon = ui.isShowPopupIcon() ? ui.renderer.getSafeIcon(l) : null; - b.setIcon(icon); - b.setText(text); - log.debug("text=" + text); - log.debug("icon=" + icon); - } - } - } finally { - ui.popup.invalidate(); - } - } - - protected String getTip(Locale l) { - boolean selected = l.equals(ui.selectedLocale); - return selected ? getSelectedTip(l) : getNotSelectedTip(l); - } - - protected String getSelectedTip(Locale l) { - String selectedTip = ui.getSelectedToolTipText(); - if (selectedTip == null) { - // use default selected tip text - selectedTip = DEFAULT_SELECTED_TOOLTIP; - } - String tip = ui.renderer.getToolTipText(l); - tip = t(selectedTip, tip); - return tip; - } - - protected String getNotSelectedTip(Locale l) { - String selectedTip = ui.getNotSelectedToolTipText(); - if (selectedTip == null) { - // use default not selected tip text - selectedTip = DEFAULT_NOT_SELECTED_TOOLTIP; - } - String tip = ui.renderer.getToolTipText(l); - tip = t(selectedTip, tip); - return tip; - } - - protected Runnable showPopupRunnable = new Runnable() { - @Override - public void run() { - ui.getPopup().pack(); - JToggleButton invoker = ui.getButton(); - Dimension dim = ui.getPopup().getPreferredSize(); - Dimension invokerDim = invoker.getSize(); - ui.getPopup().show(invoker, (int) (invokerDim.getWidth() - dim.getWidth()), invoker.getHeight()); -// getPopup().setVisible(true); - } - }; - - void $afterCompleteSetup() { - ui.addPropertyChangeListener(this); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/KeyStrokeEditor.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/KeyStrokeEditor.java deleted file mode 100644 index 4240691..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/KeyStrokeEditor.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.editor; - -import java.awt.event.KeyEvent; -import javax.swing.JTextField; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Custom text field to disable default key events - * - * @author Sylvain Lletellier - */ -public class KeyStrokeEditor extends JTextField { - - private static final Log log = LogFactory.getLog(KeyStrokeEditor.class); - - protected KeyStroke keyStroke; - - public KeyStrokeEditor() { - enableEvents(KeyEvent.KEY_EVENT_MASK); - setFocusTraversalKeysEnabled(false); - } - - @Override - protected void processKeyEvent(KeyEvent e) { - if (e.getID() == KeyEvent.KEY_PRESSED) { - int keyCode = e.getKeyCode(); - if (keyCode == KeyEvent.VK_SHIFT || - keyCode == KeyEvent.VK_ALT || - keyCode == KeyEvent.VK_CONTROL || - keyCode == KeyEvent.VK_ALT_GRAPH || - keyCode == KeyEvent.VK_META) { - - return; - } - - setKeyStroke(KeyStroke.getKeyStroke(keyCode, e.getModifiers())); - } - } - - public KeyStroke getKeyStroke() { - return keyStroke; - } - - public void setKeyStroke(KeyStroke keyStroke) { - KeyStroke oldValue = getKeyStroke(); - this.keyStroke = keyStroke; - firePropertyChange("keyStroke", oldValue, keyStroke); - fireActionPerformed(); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - setText(getKeyStroke().toString()); - } - }); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditorHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditorHandler.java deleted file mode 100644 index adeab17..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditorHandler.java +++ /dev/null @@ -1,623 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.runtime.swing.editor; - -import org.apache.commons.beanutils.PropertyUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.util.beans.BeanUtil; - -import javax.swing.JComponent; -import javax.swing.JTextField; -import javax.swing.SwingUtilities; -import javax.swing.text.BadLocationException; -import java.awt.Dimension; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyDescriptor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static jaxx.runtime.swing.editor.NumberEditor.PROPERTY_MODEL; -import static jaxx.runtime.swing.editor.NumberEditor.PROPERTY_POPUP_VISIBLE; - -/** - * Le handler de l'éditeur graphique de nombres. - * - * Note: Ce handler n'est pas staless, et chaque ui possède le sien. - * - * @author Tony Chemit - chemit@codelutin.com - * @see NumberEditor - */ -public class NumberEditorHandler { - /** Logger */ - public static final Log log = LogFactory.getLog(NumberEditorHandler.class); - - public static final String VALIDATE_PROPERTY = "validate"; - - /** editor ui */ - protected NumberEditor editor; - - /** the mutator method on the property of boxed bean in the editor */ - protected Method mutator; - - /** the getter method on the property */ - protected Method getter; - - /** a flag to known if mutator accept null value */ - protected Boolean acceptNull; - - protected Class<?> modelType; - - protected Pattern numberPattern; - - public NumberEditorHandler(NumberEditor ui) { - editor = ui; - } - - /** initialise l'ui et les listeners d'évènements. */ - public void init() { - try { -// if (editor.getBean() == null) { -// throw new NullPointerException("can not have a null bean in ui " + editor); -// } - - editor.addPropertyChangeListener(NumberEditor.PROPERTY_NUMBER_PATTERN, new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - String newPattern = (String) evt.getNewValue(); - if (log.isInfoEnabled()) { - log.info("set new numberPattern" + newPattern); - } - if (StringUtils.isEmpty(newPattern)) { - numberPattern = null; - } else { - numberPattern = Pattern.compile(newPattern); - } - } - }); - - editor.addPropertyChangeListener(NumberEditor.PROPERTY_SHOW_POPUP_BUTTON, new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (log.isDebugEnabled()) { - log.debug("set showPopupButton" + evt.getNewValue() + " for " + editor.getProperty()); - } - if (editor.getPopup().isVisible()) { - setPopupVisible(false); - } - } - }); - - editor.addPropertyChangeListener(NumberEditor.PROPERTY_AUTO_POPUP, new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (log.isDebugEnabled()) { - log.debug("set auto popup " + evt.getNewValue() + " for " + editor.getProperty()); - } - if (editor.getPopup().isVisible()) { - setPopupVisible(false); - } - } - }); - - editor.addPropertyChangeListener(PROPERTY_MODEL, new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (log.isDebugEnabled()) { - log.debug("set new model " + evt.getNewValue() + " for " + editor.getProperty()); - } - setModel((Number) evt.getOldValue(), (Number) evt.getNewValue()); - } - }); - editor.addPropertyChangeListener(PROPERTY_POPUP_VISIBLE, new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - setPopupVisible((Boolean) evt.getNewValue()); - } - }); - editor.getTextField().addMouseListener(new PopupListener()); - - // Initialise le number pattern - if (StringUtils.isNotEmpty(editor.getNumberPattern())) { - numberPattern = Pattern.compile(editor.getNumberPattern()); - } - - // Determine si c'est un float - Class<?> type = editor.getModelType(); - if (editor.getModelType() == null) { - if (editor.getBean() != null) { - type = getGetter().getReturnType(); - } - } - modelType = type; - if (log.isDebugEnabled()) { - log.debug("model type to use = " + modelType); - } - //FIXME le test n'est pas assez fort (on peut avoir un long, short,...) - editor.setUseFloat(!type.equals(Integer.class) && !type.equals(int.class)); - - // Initialise le model - if (editor.getModel() == null) { - if (editor.getBean() != null) { - Number num = (Number) getGetter().invoke(editor.getBean()); - editor.setModel(num); - } - } - - /*if (editor.getResetButton().getIcon() == null) { - editor.getResetButton().setIcon(SwingUtil.createActionIcon("numbereditor-reset")); - } - if (editor.getButton().getIcon() == null) { - editor.getButton().setIcon(SwingUtil.createActionIcon("numbereditor-calculator")); - }*/ - } catch (IllegalAccessException ex) { - log.error(ex); - } catch (IllegalArgumentException ex) { - log.error(ex); - } catch (InvocationTargetException ex) { - log.error(ex); - } - } - - /** - * Affiche ou cache la popup. - * - * @param newValue la nouvelle valeur de visibilité de la popup. - */ - public void setPopupVisible(Boolean newValue) { - - if (log.isTraceEnabled()) { - log.trace(newValue); - } - - if (newValue == null || !newValue) { - editor.getPopup().setVisible(false); - return; - } - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - JComponent invoker = - editor.isShowPopupButton() ? - editor.getShowPopUpButton() : - editor; - Dimension dim = editor.getPopup().getPreferredSize(); - int x = (int) (invoker.getPreferredSize().getWidth() - dim.getWidth()); - editor.getPopup().show(invoker, - x, invoker.getHeight()); - editor.getTextField().requestFocus(); - } - }); - } - - protected String lastValidText; - - /** - * Modifie le modèle de la donnée à éditer à partir d'un evenement clavier - * - * TODO utiliser une filtre sur les donnes en entrees pour ne pas a avoir - * faire les tests ici. - * - * @param s la nouvelle valeur du modèle - */ - public void setModel(String s) { - - String text = editor.getModelText(); - if (text.equals(s)) { - // le modeèle n'a pas changé, rien a faire sur le modèle - if (log.isDebugEnabled()) { - log.debug("modelText is the same, skip !"); - } - return; - } - - if (StringUtils.isNotEmpty(s) && numberPattern != null) { - - // use given number pattern - Matcher matcher = numberPattern.matcher(s); - if (!matcher.matches()) { - - // the current text is not accepted... - if (log.isInfoEnabled()) { - log.info("Does not accept the new number " + s + - ", will reapply lastValidText : " + lastValidText); - } - - String oldText; - if (lastValidText != null) { - - // push back last valid text - oldText = lastValidText; - } else { - oldText = ""; - } - editor.getTextField().setText(oldText); - return; - } - } - - boolean canApply = false; - - boolean endWithDot = false; - - boolean isLess = false; - - Number newValue = null; - - // allow using ',' char - s = s.replaceAll(",", "."); - - if (s.trim().isEmpty()) { - // le champ est vide donc c'est la valeur null a reaffecter - s = null; - canApply = true; - } else if (s.endsWith(".")) { - s += "0"; - endWithDot = true; - } else if (editor.isUseSign() && s.length() == 1 && s.startsWith("-")) { - s = "0"; - isLess = true; - } - - //FIXME tchemit-2014-03-25 Need to bring that bug to commons-lang team - if (s != null && (s.startsWith("0.") && NumberUtils.isNumber(s.substring(1)) || NumberUtils.isNumber(s))) { - - // on a un nombre valide - - try { - Double f = Double.parseDouble(s); - if (!editor.isUseSign() && s.startsWith("-")) { - if (log.isDebugEnabled()) { - log.debug("will skip since can not allow sign on this editor but was " + f); - } - } else { - - if (!editor.isUseFloat() && s.contains(".")) { - if (log.isDebugEnabled()) { - log.debug("will skip since can not allow float on this editor but was " + f); - } - } else { - // ok on peut utilise ce modele - newValue = getRealValue(f); -// if (editor.isUseFloat()) { -// if (getMutator().getParameterTypes()[0] == BigDecimal.class) { -// newValue = BigDecimal.valueOf(f); -// } else { -// newValue = f; -// } -// } else { -// newValue = f.intValue(); -// } - canApply = true; - } - } - - } catch (NumberFormatException e) { - // rien a faire - log.debug(e); - } - } - JTextField field = editor.getTextField(); - - int oldPosition = field.getCaretPosition(); - - if (canApply) { - - if (log.isDebugEnabled()) { - log.debug("can apply new model value : " + newValue); - } - if (isLess) { - editor.setModelText("-"); - return; - } - // on peut mettre a jour le model - editor.setModel(newValue); - if (endWithDot) { - editor.setModelText(s.substring(0, s.length() - 1)); - field.setCaretPosition(oldPosition); - } - - lastValidText = editor.getModelText(); - return; - } - - // on ne peut pas appliquer, on repositionne l'ancien texte - // dans l'éditeur - - if (log.isDebugEnabled()) { - log.debug("invalid text " + s + " reput old text " + text); - } - - field.setText(text); - - lastValidText = text; - if (editor.isSelectAllTextOnError()) { - field.selectAll(); - } else { - if (oldPosition > 0) { - oldPosition--; - } - try { - field.setCaretPosition(oldPosition); - } catch (IllegalArgumentException ex) { - log.debug("CaretPosition is invalid for position : " + oldPosition, ex); - } - } - } - - private Number getRealValue(Double f) { - if (modelType == Integer.class) { - return f.intValue(); - } - if (modelType == Double.class) { - return f; - } - if (modelType == Long.class) { - return f.longValue(); - } - if (modelType == BigInteger.class) { - return new BigInteger(f.longValue() + ""); - } - if (modelType == BigDecimal.class) { - return new BigDecimal(f + ""); - } - if (modelType == Float.class || editor.isUseFloat()) { - return f.floatValue(); - } - return f.intValue(); - } - - /** - * Ajoute le caractère donné à l'endroit où est le curseur dans la zone de - * saisie et met à jour le modèle. - * - * @param s le caractère à ajouter. - */ - public void addChar(String s) { - char c = s.charAt(0); - try { - editor.getTextField().getDocument().insertString(editor.getTextField().getCaretPosition(), c + "", null); - setModel(editor.getTextField().getText()); - //setModel(editor.getModelText() + c); - - } catch (BadLocationException e) { - log.warn(e); - } - } - - /** - * Supprime le caractère juste avant le curseur du modèle (textuel) et - * met à jour la zone de saisie. - */ - public void removeChar() { - String s = editor.getModelText(); - int position = editor.getTextField().getCaretPosition(); - if (position < 1 || s.isEmpty()) { - if (log.isDebugEnabled()) { - log.debug("cannot remove when caret on first position or text empty"); - } - // on est au debut du doc, donc rien a faire - return; - } - try { - editor.getTextField().getDocument().remove(position - 1, 1); - } catch (BadLocationException ex) { - // ne devrait jamais arrive vu qu'on a fait le controle... - log.debug(ex); - return; - } - String newText = editor.getTextField().getText(); - if (log.isDebugEnabled()) { - log.debug("text updated : " + newText); - } - position--; - editor.getTextField().setCaretPosition(position); - setModel(newText); - } - - /** - * Permute le signe dans la zone de saisie et - * dans le modèle. - */ - public void toggleSign() { - String newValue = editor.getModelText(); - - if (newValue.startsWith("-")) { - setModel(newValue.substring(1)); - } else { - setModel("-" + newValue); - } - } - - /** @return l'éditeur au quel est rattaché le handler. */ - public NumberEditor getEditor() { - return editor; - } - - protected void setModel(Number oldValue, Number newValue) { - - if (log.isDebugEnabled()) { - log.debug(editor.getProperty() + " on " + editor.getBean().getClass() + " :: " + oldValue + " to " + newValue); - } - - String strValue; - if (newValue == null) { - strValue = ""; - } else { - strValue = newValue + ""; - if (editor.isUseFloat()) { - Float n = Float.parseFloat(strValue); - if ((float) n.intValue() == n) { - strValue = n.intValue() + ""; - } - } - } - - lastValidText = strValue; - editor.setModelText(strValue); - - if (editor.getBean() == null) { - return; - } - - try { - Method mutator = getMutator(); - if (newValue == null && !getAcceptNull()) { - // valeur nulle sur une propriete primitive - // on ne peut pas utiliser la valeur null, mais 0 à la place - newValue = getRealValue(0.0d); -// if (editor.isUseFloat()) { -// if (log.isInfoEnabled()) { -// log.info("use float, check mutator default type = " + mutator.getParameterTypes()[0]); -// } -// if (mutator.getParameterTypes()[0] == BigDecimal.class) { -// newValue = BigDecimal.valueOf(0); -// } else { -// newValue = 0.0f; -//// mutator.invoke(editor.getBean(), 0.0f); -// } -// } else { -// newValue = 0; -//// mutator.invoke(editor.getBean(), 0); -// } - - } //else { -// mutator.invoke(editor.getBean(), newValue); -// } - mutator.invoke(editor.getBean(), newValue); - - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - protected void validate() { - - setPopupVisible(false); - // fire validate property (to be able to notify listeners) - editor.firePropertyChange(VALIDATE_PROPERTY, null, true); - } - - protected class PopupListener extends MouseAdapter { - - @Override - public void mousePressed(MouseEvent e) { - maybeShowPopup(e); - } - - @Override - public void mouseReleased(MouseEvent e) { - maybeShowPopup(e); - } - - protected void maybeShowPopup(MouseEvent e) { - if (!e.isPopupTrigger()) { - return; - } - if (editor.isAutoPopup()) { - if (editor.isPopupVisible()) { - if (!editor.getPopup().isVisible()) { - setPopupVisible(true); - } - // popup already visible - - } else { - // set popup auto - editor.setPopupVisible(true); - - } - } else { - if (editor.isPopupVisible()) { - setPopupVisible(true); - } - } - } - } - - protected Method getMutator() { - if (mutator == null) { - mutator = BeanUtil.getMutator(editor.getBean(), editor.getProperty()); - } - return mutator; - } - - protected Method getGetter() { - if (getter == null) { - Object bean = editor.getBean(); - if (bean == null) { - throw new NullPointerException("could not find bean in " + editor); - } - String property = editor.getProperty(); - if (property == null) { - throw new NullPointerException("could not find property in " + editor); - } - if (log.isDebugEnabled()) { - log.debug("searching accessor for property " + property + " on bean of type " + bean.getClass()); - } - if (log.isTraceEnabled()) { - PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(bean); - for (PropertyDescriptor p : descriptors) { - log.trace("property discover " + p.getName() + " reader = " + p.getWriteMethod()); - } - } - try { - PropertyDescriptor descriptor = PropertyUtils.getPropertyDescriptor(bean, property); - getter = descriptor.getReadMethod(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - return getter; - } - - public Boolean getAcceptNull() { - if (acceptNull == null) { - Method m = getMutator(); - if (m == null) { - // should never happens - throw new IllegalStateException("could not find the mutator"); - } - Class<?> returnType = m.getParameterTypes()[0]; - acceptNull = !returnType.isPrimitive(); - if (log.isDebugEnabled()) { - log.debug(acceptNull + " for mutator " + m.getName() + " type : " + returnType); - } - } - return acceptNull; - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/SimpleTimeEditorHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/SimpleTimeEditorHandler.java deleted file mode 100644 index e679dc9..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/SimpleTimeEditorHandler.java +++ /dev/null @@ -1,292 +0,0 @@ -package jaxx.runtime.swing.editor; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.util.beans.BeanUtil; - -import javax.swing.JFormattedTextField; -import javax.swing.JSpinner; -import javax.swing.SpinnerDateModel; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.lang.reflect.Method; -import java.util.Calendar; -import java.util.Date; - -/** - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class SimpleTimeEditorHandler { - - /** Logger. */ - private static final Log log = - LogFactory.getLog(SimpleTimeEditorHandler.class); - - private static final KeyAdapter MOVE_TO_MINUTES_KEY_LISTENER = new KeyAdapter() { - - @Override - public void keyReleased(KeyEvent e) { - JFormattedTextField source = (JFormattedTextField) e.getSource(); - String text = source.getText(); - - // if the user typed 2 digits or if he typed an hour which cannot be the tens digit, - // then transfer the focus to the minute editor (cf #3833) - if (text.length() >= 2 || !text.equals("0") && !text.equals("1") && !text.equals("2")) { - source.transferFocus(); - } - } - - }; - - private final PropertyChangeListener propertyDateChanged; - - private final PropertyChangeListener propertyTimeChanged; - - private final SimpleTimeEditor editor; - - private final SimpleTimeEditorModel model; - - /** the mutator method on the property of boxed bean in the editor */ - protected Method mutator; - - protected final Calendar calendarMinute; - - protected final Calendar calendarHour; - - protected final Calendar calendarDate; - - public SimpleTimeEditorHandler(SimpleTimeEditor editor) { - this.editor = editor; - this.model = editor.getModel(); - this.calendarMinute = Calendar.getInstance(); - this.calendarHour = Calendar.getInstance(); - this.calendarDate = Calendar.getInstance(); - this.propertyDateChanged = new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - Date date = (Date) evt.getNewValue(); - - if (date != null) { - calendarDate.setTime(date); - int hours = calendarDate.get(Calendar.HOUR_OF_DAY); - int minutes = calendarDate.get(Calendar.MINUTE); - if (log.isDebugEnabled()) { - log.debug("date changed : new value " + hours + ":" + minutes); - } - model.setTimeModel(hours * 60 + minutes); - - } else { - model.setTimeModel(null); - } - - } - }; - this.propertyTimeChanged = new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - Integer time = (Integer) evt.getNewValue(); - - int hours = time / 60; - int minutes = time % 60; - - calendarDate.set(Calendar.HOUR_OF_DAY, hours); - calendarDate.set(Calendar.MINUTE, minutes); - - // push it back into the bean - - Date newValue = calendarDate.getTime(); - - if (log.isDebugEnabled()) { - log.debug(model.getProperty() + " on " + model.getBean().getClass() + " :: " + newValue); - } - - try { - getMutator().invoke(model.getBean(), newValue); - - } catch (Exception e) { - throw new RuntimeException(e); - } - } - }; - } - - public void init() { - - if (model.getBean() == null) { - throw new NullPointerException("can not have a null bean in ui " + editor); - } - - editor.getMinute().setEditor(new JSpinner.DateEditor(editor.getMinute(), "mm")); -// editor.getHour().setEditor(new JSpinner.DateEditor(editor.getHour(), "HH")); - - // listen to the typed text and automatically focus the minute when the user typed the hour - JSpinner.DefaultEditor hourEditor = (JSpinner.DefaultEditor) editor.getHour().getEditor(); - hourEditor.getTextField().addKeyListener(MOVE_TO_MINUTES_KEY_LISTENER); - -// TuttiUIUtil.autoSelectOnFocus(minuteEditor.getTextField()); -// JSpinner.NumberEditor hourEditor = (JSpinner.NumberEditor) editor.getHour().getEditor(); -// TuttiUIUtil.autoSelectOnFocus(hourEditor.getTextField()); - - // listen when date changes (should come from outside) - - model.addPropertyChangeListener(SimpleTimeEditorModel.PROPERTY_DATE, propertyDateChanged); - - // When time model change, let's push it back in bean - model.addPropertyChangeListener(SimpleTimeEditorModel.PROPERTY_TIME_MODEL, propertyTimeChanged); - } - - public SimpleTimeEditor getEditor() { - return editor; - } - - protected Date setMinuteModel(Date incomingDate) { - if (incomingDate == null) { - incomingDate = new Date(); - calendarMinute.setTime(incomingDate); - calendarMinute.set(Calendar.HOUR_OF_DAY, 0); - calendarMinute.set(Calendar.MINUTE, 0); - } else { - calendarMinute.setTime(incomingDate); - calendarMinute.set(Calendar.HOUR_OF_DAY, 0); - } - incomingDate = calendarMinute.getTime(); - return incomingDate; - } - - public void updateTimeModelFromHour(Integer hour) { - model.setTimeModel(hour * 60 + model.getMinute()); - } - - public void updateTimeModelFromMinute(Date minuteDate) { - - calendarMinute.setTime(minuteDate); - int newHour = calendarMinute.get(Calendar.HOUR_OF_DAY); - int newMinute = calendarMinute.get(Calendar.MINUTE); - - int oldHour = model.getHour(); - int oldMinute = model.getMinute(); - - if (oldHour == newHour && oldMinute == newMinute) { - - // do nothing, same data - if (log.isDebugEnabled()) { - log.debug("Do not update time model , stay on same time = " + oldHour + ":" + oldMinute); - } - return; - } - - // by default stay on same hour - int hour = oldHour; - - // by default, use the new minute data - - if (log.isDebugEnabled()) { - log.debug("hh:mm (old from dateModel) = " + oldHour + ":" + oldMinute); - log.debug("hh:mm (new from minuteModel) = " + newHour + ":" + newMinute); - } - - SpinnerDateModel minuteModel = editor.getMinuteModel(); - - if (newMinute == 0) { - - // minute pass to zero (check if a new hour is required) - if (newHour == 1) { - - if (oldHour == 23) { - - // can't pass from 23:59 to 0:00, stay on 23:59 - if (log.isDebugEnabled()) { - log.debug("Do not update time model , stay on hh:mm = " + oldHour + ":" + oldMinute); - } - minuteModel.setValue(minuteModel.getPreviousValue()); - return; - } - hour = (oldHour + 1) % 24; - } - } else if (newMinute == 59) { - - // minute pass to 59 (check if a new hour is required) - - if (newHour == 23) { - - if (oldHour == 0) { - - // can't pass from 0:00 to 23:59, stay on 0:00 - if (log.isDebugEnabled()) { - log.debug("Do not update time model , stay on hh:mm = " + oldHour + ":" + oldMinute); - } - minuteModel.setValue(minuteModel.getNextValue()); - return; - } - - // decrease hour - hour = (oldHour - 1) % 24; - } - } - - // date has changed - if (log.isDebugEnabled()) { - log.debug("Update time model to hh:mm = " + hour + ":" + newMinute); - } - model.setTimeModel(hour * 60 + newMinute); - } - - protected void setDate(Date oldValue, Date newValue) { - if (model.getBean() != null) { - - if (log.isDebugEnabled()) { - log.debug(model.getProperty() + " on " + model.getBean().getClass() + " :: " + oldValue + " to " + newValue); - } - - try { - getMutator().invoke(model.getBean(), newValue); - - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - protected Method getMutator() { - if (mutator == null) { - Object bean = model.getBean(); - if (bean == null) { - throw new NullPointerException("could not find bean in " + editor); - } - String property = model.getProperty(); - if (property == null) { - throw new NullPointerException("could not find property in " + editor); - } - - mutator = BeanUtil.getMutator(bean, property); - } - return mutator; - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/SimpleTimeEditorModel.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/SimpleTimeEditorModel.java deleted file mode 100644 index afee508..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/SimpleTimeEditorModel.java +++ /dev/null @@ -1,109 +0,0 @@ -package jaxx.runtime.swing.editor; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.jdesktop.beans.AbstractSerializableBean; - -import java.io.Serializable; -import java.util.Date; - -/** - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class SimpleTimeEditorModel extends AbstractSerializableBean { - - private static final long serialVersionUID = 1L; - - public static final String PROPERTY_DATE = "date"; - - public static final String PROPERTY_TIME_MODEL = "timeModel"; - - public static final String PROPERTY_PROPERTY = "property"; - - public static final String PROPERTY_BEAN = "bean"; - - /** Bean where to push data. */ - protected Serializable bean; - - /** Property of the bean to use. */ - protected String property; - - /** Time model in minutes. */ - protected Integer timeModel = 0; - - /** Real date which contains the edited time. */ - protected Date date; - - public Serializable getBean() { - return bean; - } - - public void setBean(Serializable bean) { - Object oldValue = getBean(); - this.bean = bean; - firePropertyChange(PROPERTY_BEAN, oldValue, bean); - } - - public String getProperty() { - return property; - } - - public void setProperty(String property) { - Object oldValue = getProperty(); - this.property = property; - firePropertyChange(PROPERTY_PROPERTY, oldValue, property); - } - - public Date getDate() { - return date; - } - - public void setDate(Date date) { - Object oldValue = getDate(); - this.date = date; - firePropertyChange(PROPERTY_DATE, oldValue, date); - } - - public Integer getTimeModel() { - return timeModel; - } - - public void setTimeModel(Integer timeModel) { - if (timeModel == null) { - timeModel = 0; - } - Object oldValue = getTimeModel(); - this.timeModel = timeModel; - firePropertyChange(PROPERTY_TIME_MODEL, oldValue, timeModel); - } - - public int getMinute() { - return timeModel % 60; - } - - public int getHour() { - return timeModel / 60; - } - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditorHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditorHandler.java deleted file mode 100644 index 868cc7b..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditorHandler.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.runtime.swing.editor; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.JLabel; -import javax.swing.JSlider; -import javax.swing.plaf.basic.BasicSliderUI; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseWheelEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.lang.reflect.Method; -import java.util.Calendar; -import java.util.Date; -import java.util.Dictionary; -import java.util.Hashtable; -import java.util.Map; - -import org.nuiton.util.beans.BeanUtil; - -/** @author Tony Chemit - chemit@codelutin.com */ -public class TimeEditorHandler { - - public static final Log log = LogFactory.getLog(TimeEditorHandler.class); - - public static final String BEAN_PROPERTY = "bean"; - - public static final String PROPERTY_PROPERTY = "property"; - - public static final String DATE_PROPERTY = "date"; - - public static final String TIME_MODEL_PROPERTY = "timeModel"; - - /** editor ui */ - protected TimeEditor editor; - - /** the mutator method on the property of boxed bean in the editor */ - protected Method mutator; - - protected Calendar calendar; - - protected Calendar calendarMinute; - - public TimeEditorHandler(TimeEditor ui) { - editor = ui; - calendar = Calendar.getInstance(); - calendarMinute = Calendar.getInstance(); - } - - public void init() { - - if (editor.getBean() == null) { - throw new NullPointerException("can not have a null bean in ui " + editor); - } - - // create slider labels - Map<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>(); - for (int i = 0; i < 25; i += 2) { - labelTable.put(i * 60, new JLabel(i + "")); - } - JSlider slider = editor.getSlider(); - slider.setLabelTable((Dictionary<?, ?>) labelTable); - - MouseAdapter m = new MouseAdapter() { - - @Override - public void mouseClicked(MouseEvent e) { - // set the value - int value = getSliderValue(e); - JSlider slider = (JSlider) e.getComponent(); - slider.setValueIsAdjusting(true); - slider.setValue(value); - slider.setValueIsAdjusting(false); - showToolTip(e); - e.consume(); - } - - @Override - public void mouseDragged(MouseEvent e) { - showToolTip(e); - } - - @Override - public void mouseEntered(MouseEvent e) { - showToolTip(e); - } - - @Override - public void mouseMoved(MouseEvent e) { - showToolTip(e); - } - - @Override - public void mouseReleased(MouseEvent e) { - showToolTip(e); - } - - @Override - public void mouseWheelMoved(MouseWheelEvent e) { - JSlider slider = (JSlider) e.getComponent(); - - // compute new value - int nb = e.getWheelRotation(); - int value = slider.getValue() - nb; - - // set the value - slider.setValueIsAdjusting(true); - slider.setValue(value); - slider.setValueIsAdjusting(false); - e.consume(); - } - - int getSliderValue(MouseEvent e) { - JSlider slider = (JSlider) e.getSource(); - int value = -1; - if (slider.getUI() instanceof BasicSliderUI) { - BasicSliderUI ui = (BasicSliderUI) slider.getUI(); - value = slider.getOrientation() == JSlider.HORIZONTAL - ? ui.valueForXPosition(e.getX()) - : ui.valueForYPosition(e.getY()); - } - return value; - } - - void showToolTip(MouseEvent e) { - - int value = getSliderValue(e); - if (value == -1) { - return; - } - int h = value / 60; - int m = value % 60; - - String text = ""; - if (h < 10) { - text = "0"; - } - text += h + " : "; - if (m < 10) { - text += "0"; - } - text += m; - - JSlider slider = (JSlider) e.getSource(); - slider.setToolTipText(text); - - } - }; - slider.addMouseListener(m); - slider.addMouseMotionListener(m); - slider.addMouseWheelListener(m); - - // listen when date changes (should come from outside) - editor.addPropertyChangeListener(DATE_PROPERTY, new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - Date date = (Date) evt.getNewValue(); - - if (date == null) { - return; - } - calendar.setTime(date); - int hours = calendar.get(Calendar.HOUR_OF_DAY); - int minutes = calendar.get(Calendar.MINUTE); - if (log.isDebugEnabled()) { - log.debug("date changed : new value " + hours + ":" + minutes); - } - getEditor().setTimeModel(hours * 60 + minutes); - } - }); - - // listen when time model changes (should come from editor) - editor.addPropertyChangeListener(TIME_MODEL_PROPERTY, new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - Integer time = (Integer) evt.getNewValue(); - int hours = time / 60; - int minutes = time % 60; - calendar.set(Calendar.HOUR_OF_DAY, hours); - calendar.set(Calendar.MINUTE, minutes); - setDate(null, calendar.getTime()); - } - }); - } - - public TimeEditor getEditor() { - return editor; - } - - protected Date setMinuteModel(Date incomingDate) { - if (incomingDate == null) { - incomingDate = new Date(); - } - calendarMinute.setTime(incomingDate); - calendarMinute.set(Calendar.HOUR_OF_DAY, 0); - incomingDate = calendarMinute.getTime(); - return incomingDate; - } - - public int getMinute() { - return getEditor().getTimeModel() % 60; - } - - public int getHour() { - return getEditor().getTimeModel() / 60; - } - - public void updateTimeModelFromMinuteModel(Date minuteDate) { - - calendarMinute.setTime(minuteDate); - int newHour = calendarMinute.get(Calendar.HOUR_OF_DAY); - int newMinute = calendarMinute.get(Calendar.MINUTE); - - int oldHour = getHour(); - int oldMinute = getMinute(); - - if (oldHour == newHour && oldMinute == newMinute) { - - // do nothing, same data - if (log.isDebugEnabled()) { - log.debug("Do not update time model , stay on same time = " + oldHour + ":" + oldMinute); - } - return; - } - - // by default stay on same hour - int hour = oldHour; - - // by default, use the new minute data - - if (log.isDebugEnabled()) { - log.debug("hh:mm (old from dateModel) = " + oldHour + ":" + oldMinute); - log.debug("hh:mm (new from minuteModel) = " + newHour + ":" + newMinute); - } - - if (newMinute == 0) { - - // minute pass to zero (check if a new hour is required) - if (newHour == 1) { - - if (oldHour == 23) { - - // can't pass from 23:59 to 0:00, stay on 23:59 - if (log.isDebugEnabled()) { - log.debug("Do not update time model , stay on hh:mm = " + oldHour + ":" + oldMinute); - } - getEditor().getMinuteModel().setValue(getEditor().getMinuteModel().getPreviousValue()); - return; - } - hour = (oldHour + 1) % 24; - } - } else if (newMinute == 59) { - - // minute pass to 59 (check if a new hour is required) - - if (newHour == 23) { - - if (oldHour == 0) { - - // can't pass from 0:00 to 23:59, stay on 0:00 - if (log.isDebugEnabled()) { - log.debug("Do not update time model , stay on hh:mm = " + oldHour + ":" + oldMinute); - } - getEditor().getMinuteModel().setValue(getEditor().getMinuteModel().getNextValue()); - return; - } - - // decrease hour - hour = (oldHour - 1) % 24; - } - } - - // date has changed - if (log.isDebugEnabled()) { - log.debug("Update time model to hh:mm = " + hour + ":" + newMinute); - } - getEditor().setTimeModel(hour * 60 + newMinute); - } - - protected void setDate(Date oldValue, Date newValue) { - if (editor.getBean() == null) { - return; - } - - if (log.isDebugEnabled()) { - log.debug(editor.getProperty() + " on " + editor.getBean().getClass() + " :: " + oldValue + " to " + newValue); - } - - try { - getMutator().invoke(editor.getBean(), newValue); - - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - protected Method getMutator() { - if (mutator == null) { - mutator = BeanUtil.getMutator(editor.getBean(), editor.getProperty()); - } - return mutator; - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanComboBox.jaxx b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanComboBox.jaxx deleted file mode 100644 index 1a1b5cc..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanComboBox.jaxx +++ /dev/null @@ -1,156 +0,0 @@ -<!-- - #%L - JAXX :: Widgets - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<Table fill='both' insets='0' genericType='O' - implements='jaxx.runtime.bean.BeanTypeAware<O>' - onFocusGained='handler.focusCombo()' onFocusLost='hidePopup()'> - - <import> - jaxx.runtime.swing.model.JaxxDefaultComboBoxModel - org.nuiton.decorator.JXPathDecorator - javax.swing.border.TitledBorder - </import> - - <!-- bean type --> - <Class id='beanType' genericType='O' javaBean='null'/> - - <!-- auto complete property --> - <Boolean id='autoComplete' javaBean='false'/> - - <!-- flag to reverse the sort --> - <Boolean id='reverseSort' javaBean='false'/> - - <!-- show reset property --> - <Boolean id='showReset' javaBean='false'/> - - <!-- show decorator property --> - <Boolean id='showDecorator' javaBean='true'/> - - <!-- editable combo property --> - <Boolean id='editable' javaBean='true'/> - - <!-- sortable combo property --> - <Boolean id='sortable' javaBean='true'/> - - <!-- to transmit focus from table to combo property --> - <Boolean id='autoFocus' javaBean='true'/> - - <!-- bean property linked state --> - <String id='property' javaBean='""'/> - - <!-- model property --> - <Object id='bean' javaBean='null'/> - - <!-- selectedItem property --> - <Object id='selectedItem' javaBean='null'/> - - <!-- sort index property --> - <Integer id='index' javaBean='0'/> - - <!-- datas of the combo-box --> - <java.util.List id='data' genericType='O' javaBean='null'/> - - <Integer id="maximumRowCount" javaBean="null"/> - - <!-- model of sorted property --> - <ButtonGroup id='indexes' - onStateChanged='setIndex((Integer)indexes.getSelectedValue())'/> - - <ButtonGroup id='sortGroup' - onStateChanged='setReverseSort((Boolean)sortGroup.getSelectedValue())'/> - - <!-- ui handler --> - <BeanComboBoxHandler id='handler' genericType='O' constructorParams='this'/> - - <String id='selectedToolTipText' javaBean='null'/> - - <String id='notSelectedToolTipText' javaBean='null'/> - - <String id='popupTitleText' javaBean='null'/> - - <String id='i18nPrefix' javaBean='"entitycombobox.common."'/> - - <!-- popup to change sorted property--> - <JPopupMenu id='popup' - onPopupMenuWillBecomeInvisible='getChangeDecorator().setSelected(false)' - onPopupMenuCanceled='getChangeDecorator().setSelected(false)'> - <JLabel id='popupSortLabel'/> - - <JRadioButtonMenuItem id='sortUp'/> - - <JRadioButtonMenuItem id='sortDown'/> - - <JSeparator id='popupSeparator'/> - <JLabel id='popupLabel'/> - <JSeparator/> - </JPopupMenu> - - <script><![CDATA[ - -public static final String PROPERTY_EMPTY = "empty"; - -public void init(JXPathDecorator<O> decorator, List<O> data) { - handler.init(decorator, data); -} - -protected void hidePopup() { - if (popup.isVisible()) { - popup.setVisible(false); - } -} - -public boolean isEmpty() { return handler.isEmpty(); } - -public void addItem(O item) { handler.addItem(item); } - -public void addItems(Iterable<O> items) { handler.addItems(items); } - -public void removeItem(O item) { handler.removeItem(item); } - -public void removeItems(Iterable<O> items) { handler.removeItems(items); } - -public JaxxDefaultComboBoxModel<O> getComboBoxModel() { return (JaxxDefaultComboBoxModel<O>) combobox.getModel(); } - -]]> - </script> - <row> - <cell anchor='west'> - <!-- le boutton pour reinitialiser la valeur sélectionnée --> - <JToolBar id='toolbarLeft'> - <JButton id='resetButton' onActionPerformed='setSelectedItem(null)'/> - </JToolBar> - - </cell> - <cell weightx='1'> - <!-- la liste déroulante --> - <JComboBox id='combobox' - onFocusGained='hidePopup()'/> - </cell> - <cell anchor='east' fill='both' insets='0'> - <!-- le boutton pour changer le tri --> - <JToolBar id='toolbarRight'> - <JToggleButton id='changeDecorator' - onActionPerformed='getHandler().togglePopup()'/> - </JToolBar> - </cell> - </row> -</Table> diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanComboBoxHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanComboBoxHandler.java deleted file mode 100644 index efa1aa2..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanComboBoxHandler.java +++ /dev/null @@ -1,556 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.runtime.swing.editor.bean; - -import jaxx.runtime.SwingUtil; -import jaxx.runtime.swing.JAXXButtonGroup; -import jaxx.runtime.swing.renderer.DecoratorListCellRenderer; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.autocomplete.ObjectToStringConverter; -import org.nuiton.decorator.DecoratorUtil; -import org.nuiton.decorator.JXPathDecorator; -import org.nuiton.decorator.MultiJXPathDecorator; -import org.nuiton.util.beans.BeanUtil; - -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JPopupMenu; -import javax.swing.event.PopupMenuEvent; -import javax.swing.event.PopupMenuListener; -import javax.swing.text.Document; -import javax.swing.text.JTextComponent; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.List; - -/** - * Le handler d'un {@link BeanComboBox}. - * - * Note: ce handler n'est pas stateless et n'est donc pas partageable entre plusieurs ui. - * - * @param <O> le type des objet contenus dans le modèle du composant. - * @author Tony Chemit - chemit@codelutin.com - * @see BeanComboBox - */ -public class BeanComboBoxHandler<O> implements PropertyChangeListener { - - public static final Log log = LogFactory.getLog(BeanComboBoxHandler.class); - - /** ui if the handler */ - protected BeanComboBox<O> ui; - - /** the mutator method on the property of boxed bean in the ui */ - protected Method mutator; - - /** the original document of the combbo box editor (keep it to make possible undecorate) */ - protected Document originalDocument; - - /** the convertor used to auto-complete */ - protected ObjectToStringConverter convertor; - - /** the decorator of data */ - protected MultiJXPathDecorator<O> decorator; - - protected boolean init; - - public BeanComboBoxHandler(BeanComboBox<O> ui) { - this.ui = ui; - } - - protected final FocusListener EDITOR_TEXT_COMP0NENT_FOCUSLISTENER = new FocusListener() { - - @Override - public void focusGained(FocusEvent e) { - if (log.isDebugEnabled()) { - log.debug("close popup from " + e); - } - ui.getPopup().setVisible(false); - } - - @Override - public void focusLost(FocusEvent e) { - } - }; - - private final BeanUIUtil.PopupHandler popupHandler = new BeanUIUtil.PopupHandler() { - - @Override - public JPopupMenu getPopup() { - return ui.getPopup(); - } - - @Override - public JComponent getInvoker() { - return ui.getChangeDecorator(); - } - }; - - /** - * Initialise le handler de l'ui - * - * @param decorator le decorateur a utiliser - * @param data la liste des données a gérer - */ - public void init(JXPathDecorator<O> decorator, List<O> data) { - - if (init) { - throw new IllegalStateException("can not init the handler twice"); - } - init = true; - - if (decorator == null) { - throw new NullPointerException("decorator can not be null (for type " + ui.getBeanType() + ")"); - } - - JAXXButtonGroup indexes = ui.getIndexes(); - - this.decorator = BeanUIUtil.createDecorator(decorator); - - final JComboBox combobox = ui.getCombobox(); - - // init combobox renderer base on given decorator - combobox.setRenderer(new DecoratorListCellRenderer(this.decorator)); - combobox.addPopupMenuListener(new PopupMenuListener() { - - private O selectedItem; - - boolean canceled = false; - - public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - selectedItem = (O) combobox.getSelectedItem(); - } - - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { - O newSelectedItem = (O) combobox.getSelectedItem(); - if (canceled) { - ui.setSelectedItem(null); - - } else if ((newSelectedItem == null ^ selectedItem == null) - || (newSelectedItem != null - && !selectedItem.equals(newSelectedItem))) { - ui.setSelectedItem(newSelectedItem); - } - selectedItem = null; - canceled = false; - } - - public void popupMenuCanceled(PopupMenuEvent e) { - canceled = true; - } - }); - - convertor = BeanUIUtil.newDecoratedObjectToStringConverter(this.decorator); - - // keep a trace of original document (to make possible reverse autom-complete) - JTextComponent editorComponent = (JTextComponent) combobox.getEditor().getEditorComponent(); - originalDocument = editorComponent.getDocument(); - - // build popup - popupHandler.preparePopup(ui.getSelectedToolTipText(), - ui.getNotSelectedToolTipText(), - ui.getI18nPrefix(), - ui.getPopupTitleText(), - indexes, - ui.getPopupSeparator(), - ui.getPopupLabel(), - ui.getSortUp(), - ui.getSortDown(), - this.decorator); - - ui.autoComplete = true; - - ui.addPropertyChangeListener(this); - - // set datas - ui.setData(data); - - // select sort button - indexes.setSelectedButton(ui.getIndex()); - } - - /** Toggle the popup visible state. */ - public void togglePopup() { - popupHandler.togglePopup(); - } - - /** - * @return {@code true} if there is no data in comboBox, - * {@code false} otherwise. - * @since 2.5.9 - */ - public boolean isEmpty() { - return CollectionUtils.isEmpty(ui.getData()); - } - - /** - * Add the given items into the comboBox. - * - * <strong>Note:</strong> The item will be inserted at his correct following - * the selected ordering. - * - * @param items items to add in comboBox. - * @since 2.5.28 - */ - public void addItems(Iterable<O> items) { - - List<O> data = ui.getData(); - - boolean wasEmpty = CollectionUtils.isEmpty(data); - - for (O item : items) { - data.add(item); - } - - updateUI(ui.getIndex(), ui.isReverseSort()); - - fireEmpty(wasEmpty); - } - - /** - * Remove the given items from the comboBox model. - * - * <strong>Note:</strong> If this item was selected, then selection will be - * cleared. - * - * @param items items to remove from the comboBox model - * @since 2.5.28 - */ - public void removeItems(Iterable<O> items) { - - List<O> data = ui.getData(); - - boolean needUpdate = false; - for (O item : items) { - boolean remove = data.remove(item); - - if (remove) { - - // item was found in data - - Object selectedItem = ui.getSelectedItem(); - if (item == selectedItem) { - - // item was selected item, reset selected item then - ui.setSelectedItem(null); - } - - needUpdate = true; - - } - } - - if (needUpdate) { - - updateUI(ui.getIndex(), ui.isReverseSort()); - fireEmpty(false); - } - - } - - /** - * Add the given item into the comboBox. - * - * <strong>Note:</strong> The item will be inserted at his correct following - * the selected ordering. - * - * @param item item to add in comboBox. - * @since 2.5.9 - */ - public void addItem(O item) { - - addItems(Collections.singleton(item)); - } - - /** - * Remove the given item from the comboBox model. - * - * <strong>Note:</strong> If this item was selected, then selection will be - * cleared. - * - * @param item the item to remove from the comboBox model - * @since 2.5.9 - */ - public void removeItem(O item) { - - removeItems(Collections.singleton(item)); - } - - /** - * Sort data of the model. - * - * @since 2.5.10 - */ - public void sortData() { - - // just update UI should do the math of this - updateUI(ui.getIndex(), ui.isReverseSort()); - } - - /** - * Focus combo only if autoFocus ui property is on. - * - * @since 2.8.5 - */ - public void focusCombo() { - if (ui.isAutoFocus()) { - ui.combobox.requestFocusInWindow(); - } - } - - /** - * Modifie l'état autoComplete de l'ui. - * - * @param oldValue l'ancienne valeur - * @param newValue la nouvelle valeur - */ - protected void setAutoComplete(Boolean oldValue, Boolean newValue) { - oldValue = oldValue != null && oldValue; - newValue = newValue != null && newValue; - if (oldValue.equals(newValue)) { - return; - } - if (log.isDebugEnabled()) { - log.debug("autocomplete state : <" + oldValue + " to " + newValue + ">"); - } - if (!newValue) { - JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); - editorComponent.removeFocusListener(EDITOR_TEXT_COMP0NENT_FOCUSLISTENER); - BeanUIUtil.undecorate(ui.getCombobox(), originalDocument); - } else { - BeanUIUtil.decorate(ui.getCombobox(), convertor); - JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); - editorComponent.addFocusListener(EDITOR_TEXT_COMP0NENT_FOCUSLISTENER); - } - } - - /** - * Modifie l'index du décorateur - * - * @param oldValue l'ancienne valeur - * @param newValue la nouvelle valeur - */ - protected void setIndex(Integer oldValue, Integer newValue) { - if (newValue == null || newValue.equals(oldValue)) { - return; - } - if (log.isDebugEnabled()) { - log.debug("check state : <" + oldValue + " to " + newValue + ">"); - } - updateUI(newValue, ui.isReverseSort()); - } - - /** - * Modifie l'index du décorateur - * - * @param oldValue l'ancienne valeur - * @param newValue la nouvelle valeur - */ - - protected void setSortOrder(Boolean oldValue, Boolean newValue) { - - if (newValue == null || newValue.equals(oldValue)) { - return; - } - if (log.isDebugEnabled()) { - log.debug("check state : <" + oldValue + " to " + newValue + ">"); - } - - updateUI(ui.getIndex(), newValue); - } - - protected void updateUI(int index, boolean reversesort) { - - // change decorator context - decorator.setContextIndex(index); - - // keep selected item - Object previousSelectedItem = ui.getSelectedItem(); - Boolean wasAutoComplete = ui.isAutoComplete(); - - if (wasAutoComplete) { - ui.setAutoComplete(false); - } - - // remove autocomplete - if (previousSelectedItem != null) { - ui.getCombobox().setSelectedItem(null); - ui.selectedItem = null; - } - - List<O> data = ui.getData(); - if (ui.isSortable()) { - try { - // Sort data with the decorator jxpath tokens. - DecoratorUtil.sort(decorator, - data, - index, - reversesort); - - } catch (Exception eee) { - log.warn(eee.getMessage(), eee); - } - } - - // reload the model - SwingUtil.fillComboBox(ui.getCombobox(), data, null); - - if (wasAutoComplete) { - ui.setAutoComplete(true); - } - - if (previousSelectedItem != null) { - ui.setSelectedItem(previousSelectedItem); - } - - ui.getCombobox().requestFocus(); - } - - /** - * Modifie la valeur sélectionnée dans la liste déroulante. - * - * @param oldValue l'ancienne valeur - * @param newValue la nouvelle valeur - */ - protected void setSelectedItem(O oldValue, O newValue) { - if (ui.getBean() == null) { - return; - } - - if (newValue == null) { - if (ui.getCombobox().getSelectedItem() == null) { - return; - } - ui.getCombobox().setSelectedItem(null); - - if (ui.isAutoComplete()) { - ui.setAutoComplete(false); - ui.setAutoComplete(true); - } - - if (oldValue == null) { - return; - } - } - if (log.isDebugEnabled()) { - log.debug(ui.getProperty() + " on " + getBeanType() + " :: " + oldValue + " to " + newValue); - } - - BeanUIUtil.invokeMethod(getMutator(), ui.getBean(), (O) newValue); - } - - /** @return le document de l'éditeur avant complétion. */ - public Document getOriginalDocument() { - return originalDocument; - } - - public MultiJXPathDecorator<O> getDecorator() { - return decorator; - } - - /** - * @return get the type of objects contained in the comboBox model. - * @since 2.5.9 - */ - public Class<O> getBeanType() { - Class<O> result = ui.getBeanType(); - if (result == null) { - result = decorator == null ? null : decorator.getType(); - } - return result; - } - - /** - * Obtain the type of objects contained in the comboBox using the model mutator. - * - * @return get the type of objects contained in the comboBox model. - * @deprecated since 2.5.9 (use now method {@link #getBeanType()}) - */ - @Deprecated - public Class<?> getTargetClass() { - Method m = getMutator(); - return m == null ? null : m.getParameterTypes()[0]; - } - - /** @return le mutateur a utiliser pour modifier le bean associé. */ - protected Method getMutator() { - if (mutator == null && ui.getBean() != null && ui.getProperty() != null) { - mutator = BeanUtil.getMutator(ui.getBean(), ui.getProperty()); - } - return mutator; - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - String propertyName = evt.getPropertyName(); - - if (BeanComboBox.PROPERTY_SELECTED_ITEM.equals(propertyName)) { - setSelectedItem((O) evt.getOldValue(), (O) evt.getNewValue()); - return; - } - - if (BeanComboBox.PROPERTY_AUTO_COMPLETE.equals(propertyName)) { - - setAutoComplete((Boolean) evt.getOldValue(), - (Boolean) evt.getNewValue()); - return; - } - - if (BeanListHeader.PROPERTY_INDEX.equals(propertyName)) { - - // decorator index has changed, force reload of data in ui - setIndex((Integer) evt.getOldValue(), - (Integer) evt.getNewValue()); - return; - } - - if (BeanListHeader.PROPERTY_REVERSE_SORT.equals(propertyName)) { - - // sort order has changed, force reload of data in ui - setSortOrder((Boolean) evt.getOldValue(), - (Boolean) evt.getNewValue()); - return; - } - - if (BeanListHeader.PROPERTY_DATA.equals(propertyName)) { - - // list has changed, force reload of index - setIndex(-1, ui.getIndex()); - - // list has changed, fire empty property - List list = (List) evt.getOldValue(); - fireEmpty(CollectionUtils.isEmpty(list)); - } - } - - protected void fireEmpty(boolean wasEmpty) { - ui.firePropertyChange(BeanComboBox.PROPERTY_EMPTY, wasEmpty, - isEmpty()); - } - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanDoubleList.jaxx b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanDoubleList.jaxx deleted file mode 100644 index a5c20b8..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanDoubleList.jaxx +++ /dev/null @@ -1,164 +0,0 @@ -<!-- - #%L - JAXX :: Widgets - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> -<Table genericType='O' implements='jaxx.runtime.bean.BeanTypeAware<O>'> - - <import> - org.nuiton.decorator.JXPathDecorator - </import> - - <!-- filterable list property --> - <Boolean id='filterable' javaBean='true'/> - - <!-- flag to reverse the sort --> - <Boolean id='reverseSort' javaBean='false'/> - - <!-- show decorator property --> - <Boolean id='showDecorator' javaBean='true'/> - - <!-- show reset property --> - <Boolean id='showReset' javaBean='true'/> - - <!-- to be able to select a same entry more than one time property --> - <Boolean id='useMultiSelect' javaBean='false'/> - - <!-- show showSelectPopupEnabled property --> - <Boolean id='showSelectPopupEnabled' javaBean='true'/> - - <!-- show highlightFilterText property --> - <Boolean id='highlightFilterText' javaBean='false'/> - - <!-- bean type --> - <Class id='beanType' genericType='O' javaBean='null'/> - - <!-- bean property linked state --> - <String id='property' javaBean='""'/> - - <!-- bean property --> - <Object id='bean' javaBean='null'/> - - <String id='i18nPrefix' javaBean='"beanlist.common."'/> - - <!-- model --> - <BeanDoubleListModel id='model' genericType='O' javaBean='new BeanDoubleListModel<O>()'/> - - <!-- handler --> - <BeanDoubleListHandler id='handler' genericType='O' constructorParams='this'/> - - <!-- sort index property --> - <Integer id='index' javaBean='0'/> - - <!-- model of sorted property --> - <ButtonGroup id='indexes' - onStateChanged='setIndex((Integer)indexes.getSelectedValue())'/> - - <ButtonGroup id='sortGroup' - onStateChanged='setReverseSort((Boolean)sortGroup.getSelectedValue())'/> - - <!-- popup to change sorted property--> - <JPopupMenu id='popup' - onPopupMenuWillBecomeInvisible='getChangeDecorator().setSelected(false)' - onPopupMenuCanceled='getChangeDecorator().setSelected(false)'> - <JLabel id='popupSortLabel'/> - - <JRadioButtonMenuItem id='sortUp'/> - - <JRadioButtonMenuItem id='sortDown'/> - - <JSeparator id='popupSeparator'/> - <JLabel id='popupLabel'/> - <JSeparator/> - </JPopupMenu> - - <!-- popup on the selected list --> - <JPopupMenu id='selectedListPopup'> - <JMenuItem id='selectedListMoveUpAction' - onActionPerformed='handler.moveUpSelected( (O) selectedList.getSelectedValue())'/> - <JMenuItem id='selectedListMoveDownAction' - onActionPerformed='handler.moveDownSelected( (O) selectedList.getSelectedValue())'/> - <JMenuItem id='selectedListRemoveAction' - onActionPerformed='model.removeFromSelected( (O) selectedList.getSelectedValue())'/> - </JPopupMenu> - - <row> - <cell columns='3' fill='both'> - <JPanel layout='{new BorderLayout()}' id='beforeFilterPanel'/> - </cell> - </row> - <row> - <cell columns='3' fill='both'> - <JPanel layout='{new BorderLayout()}' id='filterPanel'> - <JPanel layout='{new BorderLayout()}' constraints='BorderLayout.WEST'> - <JLabel id='filterFieldLabel' constraints='BorderLayout.WEST'/> - <JToolBar id='toolbarLeft' constraints='BorderLayout.EAST'> - <JButton id='resetButton' onActionPerformed='filterField.setText("")'/> - </JToolBar> - </JPanel> - <JTextField id='filterField' constraints='BorderLayout.CENTER'/> - <JToolBar id='toolbarRight' constraints='BorderLayout.EAST'> - <JToggleButton id='changeDecorator' - onActionPerformed='getHandler().togglePopup()'/> - </JToolBar> - </JPanel> - </cell> - </row> - <row> - <cell weightx='0.5' weighty='1' fill='both'> - <JScrollPane onFocusGained='universeList.requestFocus()'> - <!-- List of all the remaining available elements --> - <JList id='universeList' - onFocusGained='handler.selectFirstRowIfNoSelection(event)' - onMouseClicked='handler.onUniverseListClicked(event)' - onKeyPressed='handler.onKeyPressedOnUniverseList(event)'/> - </JScrollPane> - </cell> - - <cell anchor='north'> - <JPanel layout='{new GridLayout(0,1)}'> - <JButton id='addButton' onActionPerformed='handler.select()'/> - <JButton id='removeButton' onActionPerformed='handler.unselect()'/> - </JPanel> - </cell> - - <cell weightx='0.5' weighty='1' fill='both'> - <JScrollPane onFocusGained='selectedList.requestFocus()'> - <!-- List of the selected elements --> - <JList id='selectedList' - onFocusGained='handler.selectFirstRowIfNoSelection(event)' - onMouseClicked='handler.onSelectedListClicked(event)' - onKeyPressed='handler.onKeyPressedOnSelectedList(event)'/> - </JScrollPane> - </cell> - </row> - - <script><![CDATA[ - -public void init(JXPathDecorator<O> decorator, JXPathDecorator<O> decorator2, List<O> universe, List<O> selected) { - handler.init(decorator, decorator2, universe, selected); - } - -public void init(JXPathDecorator<O> decorator, List<O> universe, List<O> selected) { - handler.init(decorator, universe, selected); -} - -]]></script> - -</Table> diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanDoubleListHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanDoubleListHandler.java deleted file mode 100644 index b0f9516..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanDoubleListHandler.java +++ /dev/null @@ -1,565 +0,0 @@ -package jaxx.runtime.swing.editor.bean; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Predicate; -import com.google.common.collect.Lists; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.swing.JAXXButtonGroup; -import jaxx.runtime.swing.model.JaxxDefaultListModel; -import jaxx.runtime.swing.model.JaxxFilterableListModel; -import jaxx.runtime.swing.renderer.DecoratorListCellRenderer; -import jaxx.runtime.swing.renderer.FilteredDecoratorListCellRenderer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.decorator.DecoratorUtil; -import org.nuiton.decorator.JXPathDecorator; -import org.nuiton.decorator.MultiJXPathDecorator; -import org.nuiton.util.beans.BeanUtil; - -import javax.swing.AbstractButton; -import javax.swing.JComponent; -import javax.swing.JList; -import javax.swing.JPopupMenu; -import javax.swing.ListSelectionModel; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.event.ListDataEvent; -import javax.swing.event.ListDataListener; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import java.awt.event.FocusEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; - -/** - * The handler of a {@link BeanDoubleList}. - * - * - * @param <O> the type of the objects contained in the list. - * @author Kevin Morin - kmorin@codelutin.com - * @see BeanDoubleList - * @since 2.5.8 - */ -public class BeanDoubleListHandler<O> implements PropertyChangeListener { - - private static final Log log = LogFactory.getLog(BeanDoubleListHandler.class); - - /** the mutator method on the property of boxed bean in the ui */ - protected Method mutator; - - /** ui of the handler */ - protected BeanDoubleList<O> ui; - - /** the decorator of data */ - protected MultiJXPathDecorator<O> decorator; - - public BeanDoubleListHandler(BeanDoubleList<O> ui) { - this.ui = ui; - } - - private final BeanUIUtil.PopupHandler popupHandler = new BeanUIUtil.PopupHandler() { - - @Override - public JPopupMenu getPopup() { - return ui.getPopup(); - } - - @Override - public JComponent getInvoker() { - return ui.getChangeDecorator(); - } - }; - - public JPopupMenu getSelectedListPopup(boolean showIt) { - JPopupMenu result; - if (showIt) { - result = ui.getSelectedListPopup(); - } else { - result = null; - } - return result; - } - - /** - * Initializes the handler of the UI - * - * @param decorator the decorator to use to display the data nicely - * @param universe the list of all the available items - * @param selected the list of selected items - */ - public void init(JXPathDecorator<O> decorator, List<O> universe, List<O> selected) { - init(decorator, decorator, universe, selected); - } - /** - * Initializes the handler of the UI - * - * @param decorator the decorator to use to display the data nicely - * @param decorator2 the selected decorator to use to display the selected data nicely (if none, then reuse the first one) - * @param universe the list of all the available items - * @param selected the list of selected items - */ - public void init(JXPathDecorator<O> decorator,JXPathDecorator<O> decorator2, List<O> universe, List<O> selected) { - - if (decorator == null) { - throw new NullPointerException("decorator can not be null (for type " + ui.getBeanType() + ")"); - } - - this.decorator = BeanUIUtil.createDecorator(decorator); - - final BeanDoubleListModel<O> uiModel = ui.getModel(); - - // make sure useMultiSelect is set before filling universe and select lists - uiModel.setUseMultiSelect(ui.getUseMultiSelect()); - - uiModel.setUniverse(universe); - uiModel.setSelected(selected); - - JList universeList = ui.getUniverseList(); - final JList selectedList = ui.getSelectedList(); - - uiModel.addCanRemoveItemsPredicate(new Predicate<List<O>>() { - - @Override - public boolean apply(List<O> o) { - return !o.isEmpty(); - } - }); - - final FilteredDecoratorListCellRenderer universeListCellRenderer - = new FilteredDecoratorListCellRenderer(this.decorator); - universeList.setCellRenderer(universeListCellRenderer); - - if (decorator2 != null) { - decorator2 = BeanUIUtil.createDecorator(decorator2); - } else { - decorator2 = this.decorator; - } - selectedList.setCellRenderer(new DecoratorListCellRenderer(decorator2)); - - // When universe list selection model changed, update the add button enabled property - universeList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - ListSelectionModel source = (ListSelectionModel) e.getSource(); - uiModel.setAddEnabled(!source.isSelectionEmpty()); - } - }); - - // When selected list selection model changed, update the add button enabled property - selectedList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - if (!e.getValueIsAdjusting()) { - recomputeButtonStates(); - } - } - }); - - // When selected list model changed, push back selected list to bean - selectedList.getModel().addListDataListener(new ListDataListener() { - - @Override - public void intervalAdded(ListDataEvent e) { - fireSelectionUpdate(); - } - - @Override - public void intervalRemoved(ListDataEvent e) { - fireSelectionUpdate(); - } - - @Override - public void contentsChanged(ListDataEvent e) { - fireSelectionUpdate(); - } - }); - - JAXXButtonGroup indexes = ui.getIndexes(); - - // build popup - popupHandler.preparePopup(null, - null, - ui.getI18nPrefix(), - null, - indexes, - ui.getPopupSeparator(), - ui.getPopupLabel(), - ui.getSortUp(), - ui.getSortDown(), - this.decorator); - - ui.addPropertyChangeListener(this); - - final JaxxFilterableListModel<O> filterModel = (JaxxFilterableListModel) uiModel.getUniverseModel(); - - filterModel.setDecorator(this.decorator); - - ui.getFilterField().getDocument().addDocumentListener(new DocumentListener() { - - @Override - public void insertUpdate(DocumentEvent e) { - String text = ui.getFilterField().getText(); - universeListCellRenderer.setFilterText(text); - filterModel.setFilterText(text); - } - - @Override - public void removeUpdate(DocumentEvent e) { - String text = ui.getFilterField().getText(); - universeListCellRenderer.setFilterText(text); - filterModel.setFilterText(text); - } - - @Override - public void changedUpdate(DocumentEvent e) { - String text = ui.getFilterField().getText(); - universeListCellRenderer.setFilterText(text); - filterModel.setFilterText(text); - } - }); - - // select sort button - indexes.setSelectedButton(ui.getIndex()); - - sortData(); - - // force to reload the showSelectPopup binding - ui.processDataBinding(BeanDoubleList.BINDING_SELECTED_LIST_COMPONENT_POPUP_MENU); - } - - public void recomputeButtonStates() { - JList selectedList = ui.getSelectedList(); - BeanDoubleListModel<O> uiModel = ui.getModel(); - - List<O> selectedItems = (List<O>) Lists.newArrayList(selectedList.getSelectedValues()); - boolean removeEnabled = uiModel.computeRemoveEnabled(selectedItems); - - ListSelectionModel selectionModel = selectedList.getSelectionModel(); - int minSelectionIndex = selectionModel.getMinSelectionIndex(); - int maxSelectionIndex = selectionModel.getMaxSelectionIndex(); - - boolean oneSelection = minSelectionIndex == maxSelectionIndex; - - boolean upEnabled = removeEnabled && - oneSelection && - minSelectionIndex > 0; - uiModel.setSelectedUpEnabled(upEnabled); - - boolean downEnabled = removeEnabled && - oneSelection && - minSelectionIndex + 1 < uiModel.getSelectedListSize(); - uiModel.setSelectedDownEnabled(downEnabled); - } - - public void setUniverse(List<O> selection) { - ui.getModel().setUniverse(selection); - sortData(); - } - - public void setSelected(List<O> selection) { - ui.getModel().setSelected(selection); - sortData(); - } - - /** Toggle the popup visible state. */ - public void togglePopup() { - popupHandler.togglePopup(); - } - - /** - * Sort data of the model. - * - * @since 2.5.10 - */ - public void sortData() { - - // just update UI should do the math of this - updateUI(ui.getIndex(), ui.isReverseSort()); - } - - /** - * Move up a selected item. - * - * @param item the selected item - * @since 2.5.26 - */ - public void moveUpSelected(O item) { - ui.getModel().moveUpSelected(item); - ui.getSelectedList().setSelectedValue(item, true); - } - - /** - * Move down a selected item. - * - * @param item the selected item - * @since 2.5.26 - */ - public void moveDownSelected(O item) { - ui.getModel().moveDownSelected(item); - ui.getSelectedList().setSelectedValue(item, true); - } - - /** - * Modifie l'index du décorateur - * - * @param oldValue l'ancienne valeur - * @param newValue la nouvelle valeur - */ - protected void setIndex(Integer oldValue, Integer newValue) { - if (newValue == null || newValue.equals(oldValue)) { - return; - } - if (log.isDebugEnabled()) { - log.debug("check state : <" + oldValue + " to " + newValue + ">"); - } - AbstractButton button = ui.getIndexes().getButton(newValue); - if (button != null) { - button.setSelected(true); - } - updateUI(newValue, ui.isReverseSort()); - } - - /** - * Modifie l'index du décorateur - * - * @param oldValue l'ancienne valeur - * @param newValue la nouvelle valeur - */ - - protected void setSortOrder(Boolean oldValue, Boolean newValue) { - - if (newValue == null || newValue.equals(oldValue)) { - return; - } - if (log.isDebugEnabled()) { - log.debug("check state : <" + oldValue + " to " + newValue + ">"); - } - - updateUI(ui.getIndex(), newValue); - } - - protected void setHighlightFilterText(Boolean newValue) { - FilteredDecoratorListCellRenderer universeListCellRenderer = - (FilteredDecoratorListCellRenderer) ui.getUniverseList().getCellRenderer(); - universeListCellRenderer.setHighlightFilterText(newValue); - ui.getUniverseList().repaint(); - } - - protected void updateUI(int index, boolean reversesort) { - - // change decorator context - decorator.setContextIndex(index); - - List<O> data = (List<O>) Arrays.asList(((JaxxDefaultListModel<O>) ui.getModel().getUniverseModel()).toArray()); - try { - // Sort data with the decorator jxpath tokens. - DecoratorUtil.sort(decorator, - data, - index, - reversesort - ); - - } catch (Exception eee) { - log.warn(eee.getMessage(), eee); - } - - // reload the model - SwingUtil.fillList(ui.getUniverseList(), data, null); - - ui.getUniverseList().requestFocus(); - } - - /** - * When universe list was double clicked, move selected items to selected list. - * - * @param event mouse event - */ - public void onUniverseListClicked(MouseEvent event) { - JList universeList = ui.getUniverseList(); - if (event.getClickCount() == 2) { - int index = universeList.locationToIndex(event.getPoint()); - if (index < 0) { - return; - } - if (!ui.getModel().isAddEnabled()) { - return; - } - O item = (O) universeList.getModel().getElementAt(index); - ui.getModel().addToSelected(item); - - sortData(); - } - } - - /** - * When selected list was double clicked, move selected items to universe list. - * - * @param event mouse event - */ - public void onSelectedListClicked(MouseEvent event) { - - JList selectedList = ui.getSelectedList(); - - if (event.getClickCount() == 2) { - int index = selectedList.locationToIndex(event.getPoint()); - if (index < 0) { - return; - } - if (!ui.getModel().isRemoveEnabled()) { - return; - } - O item = (O) selectedList.getModel().getElementAt(index); - ui.getModel().removeFromSelected(item); - - sortData(); - } - } - - /** When add button was hit, move selected items (from universe list) to selected list. */ - public void select() { - List<O> selection = (List<O>) Arrays.asList(ui.getUniverseList().getSelectedValues()); - ui.getModel().addToSelected(selection); - ui.getUniverseList().clearSelection(); - - sortData(); - } - - /** When remove button was hit, move selected items (from selected list) to universe list. */ - public void unselect() { - List<O> selection = (List<O>) Arrays.asList(ui.getSelectedList().getSelectedValues()); - ui.getModel().removeFromSelected(selection); - ui.getSelectedList().clearSelection(); - - sortData(); - } - - protected void fireSelectionUpdate() { - if (ui.getBean() != null) { - BeanUIUtil.invokeMethod(getMutator(), - ui.getBean(), - ui.getModel().getSelected()); - } - } - - public Method getMutator() { - if (mutator == null && ui.getBackground() != null && ui.getProperty() != null) { - mutator = BeanUtil.getMutator(ui.getBean(), ui.getProperty()); - } - return mutator; - } - - public MultiJXPathDecorator<O> getDecorator() { - return decorator; - } - - /** - * @return get the type of objects contained in the comboBox model. - * @since 2.5.9 - */ - public Class<O> getBeanType() { - Class<O> result = ui.getBeanType(); - if (result == null) { - result = decorator == null ? null : decorator.getType(); - } - return result; - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - String propertyName = evt.getPropertyName(); - - if (BeanListHeader.PROPERTY_INDEX.equals(propertyName)) { - - // decorator index has changed, force reload of data in ui - setIndex((Integer) evt.getOldValue(), - (Integer) evt.getNewValue()); - - } else if (BeanDoubleList.PROPERTY_REVERSE_SORT.equals(propertyName)) { - - // sort order has changed, force reload of data in ui - setSortOrder((Boolean) evt.getOldValue(), - (Boolean) evt.getNewValue()); - - } else if (BeanDoubleList.PROPERTY_HIGHLIGHT_FILTER_TEXT.equals(propertyName)) { - - setHighlightFilterText((Boolean) evt.getNewValue()); - } else if (BeanDoubleList.PROPERTY_USE_MULTI_SELECT.equals(propertyName)) { - - ui.getModel().setUseMultiSelect((Boolean) evt.getNewValue()); - } - } - - public void addFilter(Predicate<O> filter) { - ((JaxxFilterableListModel) ui.getModel().getUniverseModel()).addFilter(filter); - } - - public void removeFilter(Predicate<O> filter) { - ((JaxxFilterableListModel) ui.getModel().getUniverseModel()).removeFilter(filter); - } - - public void clearFilters() { - ((JaxxFilterableListModel) ui.getModel().getUniverseModel()).clearFilters(); - } - - public void refreshFilteredElements() { - ((JaxxFilterableListModel) ui.getModel().getUniverseModel()).refreshFilteredElements(); - } - - public void onKeyPressedOnUniverseList(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - int lastIndice = ui.getUniverseList().getSelectionModel().getLeadSelectionIndex(); - select(); - JList source = (JList) e.getSource(); - if (source.getModel().getSize() > 0) { - source.setSelectedIndex(Math.min(lastIndice, source.getModel().getSize() - 1)); - } else { - ui.getSelectedList().requestFocus(); - } - } - } - - public void onKeyPressedOnSelectedList(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_DELETE) { - int lastIndice = ui.getSelectedList().getSelectionModel().getLeadSelectionIndex(); - unselect(); - JList source = (JList) e.getSource(); - if (source.getModel().getSize() > 0) { - source.setSelectedIndex(Math.min(lastIndice, source.getModel().getSize() - 1)); - ui.getSelectedList().requestFocus(); - } - } - } - - public void selectFirstRowIfNoSelection(FocusEvent event) { - JList list = (JList) event.getSource(); - if (list.isSelectionEmpty()) { - list.setSelectedIndex(0); - } - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanDoubleListModel.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanDoubleListModel.java deleted file mode 100644 index 0546060..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanDoubleListModel.java +++ /dev/null @@ -1,350 +0,0 @@ -package jaxx.runtime.swing.editor.bean; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Predicate; -import com.google.common.collect.Lists; -import jaxx.runtime.swing.model.JaxxDefaultListModel; -import jaxx.runtime.swing.model.JaxxFilterableListModel; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.beans.AbstractSerializableBean; - -import javax.swing.ListModel; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; - -/** - * The model of the {@link BeanDoubleList} widget - * - * @param <O> the type of the object in the list - * @author Kevin Morin - kmorin@codelutin.com - * @see BeanDoubleList - * @since 2.5.8 - */ -public class BeanDoubleListModel<O> extends AbstractSerializableBean { - - private static final Log log = LogFactory.getLog(BeanDoubleListModel.class); - - public static final String PROPERTY_ADD_ENABLED = "addEnabled"; - - public static final String PROPERTY_REMOVE_ENABLED = "removeEnabled"; - - public static final String PROPERTY_SELECTED_UP_ENABLED = "selectedUpEnabled"; - - public static final String PROPERTY_SELECTED_DOWN_ENABLED = "selectedDownEnabled"; - - public static final String PROPERTY_USE_MULTI_SELECT = "useMultiSelect"; - - private static final long serialVersionUID = 1L; - - /** List of all the available items */ - protected List<O> universe = new ArrayList<O>(); - - /** Model containing the remaining available items */ - protected JaxxFilterableListModel<O> universeModel = new JaxxFilterableListModel<O>(); - - /** List of the selected items */ - protected List<O> selected = new ArrayList<O>(); - - /** Model containing the selected items */ - protected JaxxDefaultListModel<O> selectedModel = new JaxxDefaultListModel<O>(); - - protected boolean addEnabled; - - protected boolean removeEnabled; - - protected boolean selectedUpEnabled; - - protected boolean selectedDownEnabled; - - protected boolean useMultiSelect; - - protected Collection<Predicate<List<O>>> canRemoveItemsPredicates = new ArrayList<Predicate<List<O>>>(); - - /** - * To get the selected items. - * - * @return a list of O - */ - public List<O> getSelected() { - return selected; - } - - /** - * Sets the list of selected items. - * It fills the model of the list of the selected items with these items - * and removes them from the model of list of the universe. - * - * @param selected a list of O - */ - public void setSelected(List<O> selected) { - //reset all the universe in the universe list - resetUniverse(); - - if (selected == null) { - selected = Lists.newArrayList(); - } - this.selected.clear(); - selectedModel.clear(); - addToSelected(selected); - } - - /** - * To get all the available items. - * - * @return a list of O - */ - public List<O> getUniverse() { - return universe; - } - - /** - * Sets the list of the available items. - * It fills the model of the universe list with these items. - * - * @param universe a list of O - */ - public void setUniverse(List<O> universe) { - if (universe == null) { - this.universe = Lists.newArrayList(); - } else { - this.universe = Lists.newArrayList(universe); - } - resetUniverse(); - } - - protected void resetUniverse() { - universeModel.setAllElements(universe); - } - - public ListModel getSelectedModel() { - return selectedModel; - } - - public ListModel getUniverseModel() { - return universeModel; - } - - /** - * Adds an item to the selected items. - * - * @param item the item to select - */ - public void addToSelected(O item) { - selected.add(item); - selectedModel.addElement(item); - if (!useMultiSelect) { - universeModel.removeElement(item); - } - } - - /** - * Adds a list of items to the selected items. - * - * @param items the list of the items to select - */ - public void addToSelected(List<O> items) { - selected.addAll(items); - for (O item : items) { - - selectedModel.setValueIsAdjusting(true); - universeModel.setValueIsAdjusting(true); - - try { - selectedModel.addElement(item); - if (!useMultiSelect) { - universeModel.removeElement(item); - } - } finally { - selectedModel.setValueIsAdjusting(false); - universeModel.setValueIsAdjusting(false); - } - } - - selectedModel.refresh(); - universeModel.refresh(); - - } - - /** - * Removes an item from the selected items. - * - * @param item the item to unselect - */ - public void removeFromSelected(O item) { - selected.remove(item); - selectedModel.removeElement(item); - if (!useMultiSelect) { - addToUniverseList(item); - } - } - - /** - * Removes a list of items from the list of selected items. - * - * @param items the list of the items to unselect - */ - public void removeFromSelected(List<O> items) { - selected.removeAll(items); - for (O item : items) { - selectedModel.removeElement(item); - if (!useMultiSelect) { - addToUniverseList(item); - } - } - } - - /** - * Move up a selected item. - * - * @param item the selected item - * @since 2.5.26 - */ - public void moveUpSelected(O item) { - int i = selected.indexOf(item); - selected.remove(item); - selectedModel.removeElement(item); - selected.add(i - 1, item); - selectedModel.insertElementAt(item, i - 1); - } - - /** - * Move down a selected item. - * - * @param item the selected item - * @since 2.5.26 - */ - public void moveDownSelected(O item) { - int i = selected.indexOf(item); - selected.remove(item); - selectedModel.removeElement(item); - selected.add(i + 1, item); - selectedModel.insertElementAt(item, i + 1); - } - - public boolean isAddEnabled() { - return addEnabled; - } - - public void setAddEnabled(boolean addEnabled) { - boolean oldValue = isAddEnabled(); - this.addEnabled = addEnabled; - firePropertyChange(PROPERTY_ADD_ENABLED, oldValue, addEnabled); - } - - public boolean isRemoveEnabled() { - return removeEnabled; - } - - public void setRemoveEnabled(boolean removeEnabled) { - boolean oldValue = isRemoveEnabled(); - this.removeEnabled = removeEnabled; - firePropertyChange(PROPERTY_REMOVE_ENABLED, oldValue, removeEnabled); - } - - public boolean isSelectedUpEnabled() { - return selectedUpEnabled; - } - - public void setSelectedUpEnabled(boolean selectedUpEnabled) { - boolean oldValue = isSelectedUpEnabled(); - this.selectedUpEnabled = selectedUpEnabled; - firePropertyChange(PROPERTY_SELECTED_UP_ENABLED, oldValue, selectedUpEnabled); - } - - public boolean isSelectedDownEnabled() { - return selectedDownEnabled; - } - - public void setSelectedDownEnabled(boolean selectedDownEnabled) { - boolean oldValue = isSelectedDownEnabled(); - this.selectedDownEnabled = selectedDownEnabled; - firePropertyChange(PROPERTY_SELECTED_DOWN_ENABLED, oldValue, selectedDownEnabled); - } - - - public boolean isUseMultiSelect() { - return useMultiSelect; - } - - public void setUseMultiSelect(boolean useMultiSelect) { - boolean oldValue = isUseMultiSelect(); - this.useMultiSelect = useMultiSelect; - firePropertyChange(PROPERTY_USE_MULTI_SELECT, oldValue, useMultiSelect); - } - - /** - * Adds an item to the available items list at the right index - * to keep always the same order. - * - * @param item the item to add to the universe list - */ - protected void addToUniverseList(O item) { - // the maximum index where we should insert the item is its index - // in the list of all the available items - int index = universe.indexOf(item); - if (index!=-1) { - // if the index is upper than the size of the list of the remaining available items, - // get the size of this list - int insertionIndex = Math.min(index, universeModel.getSize()); - - // we decrease the index to insert until we meet an item whose index - // in the list of all the available index is lower than the one of the item - // we want to insert - while (insertionIndex > 0) { - O o = universeModel.get(--insertionIndex); - int oIndex = universe.indexOf(o); - if (oIndex < index) { - insertionIndex++; - break; - } - } - universeModel.add(insertionIndex, item); - } - } - - public int getSelectedListSize() { - return selected.size(); - } - - public void addCanRemoveItemsPredicate(Predicate<List<O>> canRemoveItemsPredicate) { - canRemoveItemsPredicates.add(canRemoveItemsPredicate); - } - - public void removeCanRemoveItemsPredicate(Predicate<List<O>> canRemoveItemsPredicate) { - canRemoveItemsPredicates.remove(canRemoveItemsPredicate); - } - - public boolean computeRemoveEnabled(List<O> toRemoveItems) { - boolean result = true; - Iterator<Predicate<List<O>>> iterator = canRemoveItemsPredicates.iterator(); - while (result && iterator.hasNext()) { - result = iterator.next().apply(toRemoveItems); - } - setRemoveEnabled(result); - return result; - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanFilterableComboBox.jaxx b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanFilterableComboBox.jaxx deleted file mode 100644 index 826f73a..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanFilterableComboBox.jaxx +++ /dev/null @@ -1,160 +0,0 @@ -<!-- - #%L - JAXX :: Widgets - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<Table fill='both' insets='0' genericType='O' - implements='jaxx.runtime.bean.BeanTypeAware<O>' - onFocusGained='handler.focusCombo()' onFocusLost='hidePopup()'> - - <import> - jaxx.runtime.swing.model.JaxxFilterableComboBoxModel - org.nuiton.decorator.JXPathDecorator - javax.swing.border.TitledBorder - </import> - - <!-- bean type --> - <Class id='beanType' genericType='O' javaBean='null'/> - - <!-- filterable property --> - <Boolean id='filterable' javaBean='true'/> - - <!-- flag to reverse the sort --> - <Boolean id='reverseSort' javaBean='false'/> - - <!-- show reset property --> - <Boolean id='showReset' javaBean='false'/> - - <!-- show decorator property --> - <Boolean id='showDecorator' javaBean='true'/> - - <!-- editable combo property --> - <Boolean id='editable' javaBean='true'/> - - <!-- sortable combo property --> - <Boolean id='sortable' javaBean='true'/> - - <!-- to transmit focus from table to combo property --> - <Boolean id='autoFocus' javaBean='true'/> - - <!-- to select using enter key when there is only one selection --> - <Boolean id='enterToSelectUniqueUniverse' javaBean='true'/> - - <!-- bean property linked state --> - <String id='property' javaBean='""'/> - - <!-- model property --> - <Object id='bean' javaBean='null'/> - - <!-- selectedItem property --> - <Object id='selectedItem' javaBean='null'/> - - <!-- sort index property --> - <Integer id='index' javaBean='0'/> - - <java.awt.Color id='invalidComboEditorTextColor' javaBean='null'/> - - <!-- datas of the combo-box --> - <java.util.List id='data' genericType='O' javaBean='null'/> - - <Integer id="maximumRowCount" javaBean="null"/> - - <!-- model of sorted property --> - <ButtonGroup id='indexes' - onStateChanged='setIndex((Integer)indexes.getSelectedValue())'/> - - <ButtonGroup id='sortGroup' - onStateChanged='setReverseSort((Boolean)sortGroup.getSelectedValue())'/> - - <!-- ui handler --> - <BeanFilterableComboBoxHandler id='handler' genericType='O' constructorParams='this'/> - - <String id='selectedToolTipText' javaBean='null'/> - - <String id='notSelectedToolTipText' javaBean='null'/> - - <String id='popupTitleText' javaBean='null'/> - - <String id='i18nPrefix' javaBean='"entitycombobox.common."'/> - - <!-- popup to change sorted property--> - <JPopupMenu id='popup' - onPopupMenuWillBecomeInvisible='getChangeDecorator().setSelected(false)' - onPopupMenuCanceled='getChangeDecorator().setSelected(false)'> - <JLabel id='popupSortLabel'/> - - <JRadioButtonMenuItem id='sortUp'/> - - <JRadioButtonMenuItem id='sortDown'/> - - <JSeparator id='popupSeparator'/> - <JLabel id='popupLabel'/> - <JSeparator/> - </JPopupMenu> - - <script><![CDATA[ - -public static final String PROPERTY_EMPTY = "empty"; - -public void init(JXPathDecorator<O> decorator, List<O> data) { - handler.init(decorator, data); -} - -protected void hidePopup() { - if (popup.isVisible()) { - popup.setVisible(false); - } -} - -public boolean isEmpty() { return handler.isEmpty(); } - -public void addItem(O item) { handler.addItem(item); } - -public void addItems(Iterable<O> items) { handler.addItems(items); } - -public void removeItem(O item) { handler.removeItem(item); } - -public void removeItems(Iterable<O> items) { handler.removeItems(items); } - -public void reset() { handler.reset(); } - -public JaxxFilterableComboBoxModel<O> getComboBoxModel() { return (JaxxFilterableComboBoxModel<O>) combobox.getModel(); } - -]]> - </script> - <row> - <cell anchor='west'> - <!-- le boutton pour reinitialiser la valeur sélectionnée --> - <JToolBar id='toolbarLeft'> - <JButton id='resetButton' onActionPerformed='handler.reset()'/> - </JToolBar> - - </cell> - <cell weightx='1'> - <!-- la liste déroulante --> - <JComboBox id='combobox'/> - </cell> - <cell anchor='east' fill='both' insets='0'> - <!-- le boutton pour changer le tri --> - <JToolBar id='toolbarRight'> - <JToggleButton id='changeDecorator' - onActionPerformed='getHandler().togglePopup()'/> - </JToolBar> - </cell> - </row> -</Table> diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanFilterableComboBoxHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanFilterableComboBoxHandler.java deleted file mode 100644 index 7a3cbe9..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanFilterableComboBoxHandler.java +++ /dev/null @@ -1,736 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.editor.bean; - -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.SwingUtil; -import jaxx.runtime.swing.JAXXButtonGroup; -import jaxx.runtime.swing.model.JaxxFilterableComboBoxModel; -import jaxx.runtime.swing.renderer.DecoratorListCellRenderer; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.decorator.DecoratorUtil; -import org.nuiton.decorator.JXPathDecorator; -import org.nuiton.decorator.MultiJXPathDecorator; -import org.nuiton.util.beans.BeanUtil; - -import javax.swing.AbstractButton; -import javax.swing.ComboBoxEditor; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JPopupMenu; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.text.JTextComponent; -import java.awt.event.ActionListener; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -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.lang.reflect.Method; -import java.util.Collections; -import java.util.List; - -/** - * Le handler d'un {@link BeanFilterableComboBox}. - * - * Note: ce handler n'est pas stateless et n'est donc pas partageable entre - * plusieurs ui. - * - * @param <O> le type des objet contenus dans le modèle du composant. - * @author Kevin Morin - morin@codelutin.com - * @see BeanFilterableComboBox - * @since 2.5.12 - */ -public class BeanFilterableComboBoxHandler<O> implements PropertyChangeListener { - - public static final Log log = LogFactory.getLog(BeanFilterableComboBoxHandler.class); - - /** ui if the handler */ - protected BeanFilterableComboBox<O> ui; - - /** the mutator method on the property of boxed bean in the ui */ - protected Method mutator; - - /** the decorator of data */ - protected MultiJXPathDecorator<O> decorator; - - protected boolean init; - - public BeanFilterableComboBoxHandler(BeanFilterableComboBox<O> ui) { - this.ui = ui; - } - - protected final FocusListener EDITOR_TEXT_COMP0NENT_FOCUSLISTENER = new FocusListener() { - @Override - public void focusGained(FocusEvent e) { - if (log.isDebugEnabled()) { - log.debug("close popup from " + e); - } - ui.getPopup().setVisible(false); - } - - @Override - public void focusLost(FocusEvent e) { - } - }; - - protected final DocumentListener EDITOR_TEXT_COMPONENT_DOCUMENTLISTENER = new DocumentListener() { - public void insertUpdate(DocumentEvent e) { - updateFilter(); - } - - public void removeUpdate(DocumentEvent e) { - updateFilter(); - } - - public void changedUpdate(DocumentEvent e) { - updateFilter(); - } - - protected void updateFilter() { - JComboBox comboBox = ui.getCombobox(); - JaxxFilterableComboBoxModel model = (JaxxFilterableComboBoxModel) comboBox.getModel(); - JTextComponent editorComponent = (JTextComponent) comboBox.getEditor().getEditorComponent(); - // hide the popup before setting the filter, otherwise the popup height does not fit - boolean wasPopupVisible = comboBox.isShowing() && comboBox.isPopupVisible(); - if (wasPopupVisible) { - comboBox.hidePopup(); - } - String text = editorComponent.getText(); - if (ui.getSelectedItem() != null) { - text = ""; - } - if (log.isDebugEnabled()) { - log.debug("updateFilter " + text); - } - model.setFilterText(text); - if (wasPopupVisible) { - comboBox.showPopup(); - } - } - - }; - - private final BeanUIUtil.PopupHandler popupHandler = new BeanUIUtil.PopupHandler() { - @Override - public JPopupMenu getPopup() { - return ui.getPopup(); - } - - @Override - public JComponent getInvoker() { - return ui.getChangeDecorator(); - } - }; - - /** - * Initialise le handler de l'ui - * - * @param decorator le decorateur a utiliser - * @param data la liste des données a gérer - */ - public void init(JXPathDecorator<O> decorator, List<O> data) { - - if (init) { - throw new IllegalStateException("can not init the handler twice"); - } - init = true; - - if (decorator == null) { - throw new NullPointerException("decorator can not be null (for type " + ui.getBeanType() + ")"); - } - - JAXXButtonGroup indexes = ui.getIndexes(); - - this.decorator = BeanUIUtil.createDecorator(decorator); - - final JComboBox combobox = ui.getCombobox(); - final JAXXFilterableComboBoxEditor editor = - new JAXXFilterableComboBoxEditor(ui.getCombobox().getEditor()); - combobox.setEditor(editor); - - editor.getEditorComponent().addMouseListener(new MouseAdapter() { - - @Override - public void mouseClicked(MouseEvent e) { - if (ui.isEnabled()) { - combobox.showPopup(); - } - } - - }); - editor.getEditorComponent().addKeyListener(new KeyAdapter() { - - @Override - public void keyPressed(KeyEvent e) { - if (!ui.isEnabled()) { - e.consume(); - return; - } - if (log.isDebugEnabled()) { - log.debug("keyPressed: " + e.getKeyCode()); - } - if (combobox.isPopupVisible() && ui.isEnterToSelectUniqueUniverse()) { - if (KeyEvent.VK_ENTER == e.getKeyCode() && combobox.getItemCount() == 1) { - // we don't want any other action for this one - if (log.isDebugEnabled()) { - log.debug("ENTER + only one selected item, consume"); - } - combobox.hidePopup(); - e.consume(); - return; - } - } - } - - @Override - public void keyReleased(KeyEvent e) { - if (log.isDebugEnabled()) { - log.debug("keyReleased: " + e.getKeyCode()); - } - if (combobox.isPopupVisible() && KeyEvent.VK_ESCAPE == e.getKeyCode()) { - if (log.isDebugEnabled()) { - log.debug("ESC , hide popup"); - } - e.consume(); - combobox.hidePopup(); - return; - } - if (!combobox.isPopupVisible() && KeyEvent.VK_ESCAPE != e.getKeyCode() && KeyEvent.VK_ENTER != e.getKeyCode()) { - if (log.isDebugEnabled()) { - log.debug("Will show popup, keycode: " + e.getKeyCode()); - } - combobox.showPopup(); - } - // if the typed text does not match the selected item, - // set the selected item to null - Object selectedItem = ui.getSelectedItem(); - String text = editor.getEditorComponent().getText(); - if (log.isDebugEnabled()) { - log.debug("keycode: " + e.getKeyCode() + ", editorText: " + text); - } - if (KeyEvent.VK_ENTER == e.getKeyCode() && ui.isEnterToSelectUniqueUniverse() && combobox.getItemCount() == 1) { - - // auto-select the - if (log.isDebugEnabled()) { - log.debug("Auto-select unique result with *ENTER* key"); - } - combobox.setSelectedIndex(0); - e.consume(); - // edition is done - combobox.hidePopup(); - return; - } - final String selectedItemString; - if (getBeanType().isInstance(selectedItem)) { - selectedItemString = BeanFilterableComboBoxHandler.this.decorator.toString(selectedItem); - } else { - selectedItemString = JAXXUtil.getStringValue(selectedItem); - } - if (selectedItem == null || !selectedItemString.equals(text)) { - unselectItem(); - } - } - - }); - - // init combobox renderer base on given decorator - combobox.setRenderer(new DecoratorListCellRenderer(this.decorator)); - ((JaxxFilterableComboBoxModel) combobox.getModel()).setDecorator(this.decorator); - combobox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE); - combobox.addItemListener(new ItemListener() { - - public void itemStateChanged(ItemEvent e) { - Object item = e.getItem(); - if (e.getStateChange() == ItemEvent.SELECTED) { - if (log.isDebugEnabled()) { - log.debug("itemStateChanged selected " + item + " - " + (item != null ? item.getClass() : null)); - } - combobox.getEditor().getEditorComponent().setForeground(null); - ui.setSelectedItem(item); - - } else { - if (log.isDebugEnabled()) { - log.debug("itemStateChanged deselected " + item + " - " + (item != null ? item.getClass() : null)); - } - combobox.getEditor().getEditorComponent().setForeground(ui.getInvalidComboEditorTextColor()); - } - } - }); - - // build popup - popupHandler.preparePopup(ui.getSelectedToolTipText(), - ui.getNotSelectedToolTipText(), - ui.getI18nPrefix(), - ui.getPopupTitleText(), - indexes, - ui.getPopupSeparator(), - ui.getPopupLabel(), - ui.getSortUp(), - ui.getSortDown(), - this.decorator); - - setFilterable(false, ui.getFilterable()); - - ui.addPropertyChangeListener(this); - - // set datas - ui.setData(data); - - // select sort button - indexes.setSelectedButton(ui.getIndex()); - } - - /** Toggle the popup visible state. */ - public void togglePopup() { - popupHandler.togglePopup(); - } - - /** - * @return {@code true} if there is no data in comboBox, {@code false} - * otherwise. - */ - public boolean isEmpty() { - return CollectionUtils.isEmpty(ui.getData()); - } - - /** - * Add the given items into the comboBox. - * - * <strong>Note:</strong> The item will be inserted at his correct following - * the selected ordering. - * - * @param items items to add in comboBox. - * @since 2.5.28 - */ - public void addItems(Iterable<O> items) { - - List<O> data = ui.getData(); - - boolean wasEmpty = CollectionUtils.isEmpty(data); - - for (O item : items) { - data.add(item); - } - - updateUI(ui.getIndex(), ui.isReverseSort()); - - fireEmpty(wasEmpty); - } - - /** - * Remove the given items from the comboBox model. - * - * <strong>Note:</strong> If this item was selected, then selection will be - * cleared. - * - * @param items items to remove from the comboBox model - * @since 2.5.28 - */ - public void removeItems(Iterable<O> items) { - - List<O> data = ui.getData(); - - boolean needUpdate = false; - for (O item : items) { - boolean remove = data.remove(item); - - if (remove) { - - // item was found in data - - Object selectedItem = ui.getSelectedItem(); - if (item == selectedItem) { - - // item was selected item, reset selected item then - ui.setSelectedItem(null); - } - - needUpdate = true; - } - } - - if (needUpdate) { - - updateUI(ui.getIndex(), ui.isReverseSort()); - fireEmpty(false); - } - - } - - /** - * Add the given item into the comboBox. - * - * <strong>Note:</strong> The item will be inserted at his correct following - * the selected ordering. - * - * @param item item to add in comboBox. - * @since 2.5.9 - */ - public void addItem(O item) { - - addItems(Collections.singleton(item)); - } - - /** - * Remove the given item from the comboBox model. - * - * <strong>Note:</strong> If this item was selected, then selection will be - * cleared. - * - * @param item the item to remove from the comboBox model - * @since 2.5.9 - */ - public void removeItem(O item) { - - removeItems(Collections.singleton(item)); - } - - /** Sort data of the model. */ - public void sortData() { - - // just update UI should do the math of this - updateUI(ui.getIndex(), ui.isReverseSort()); - } - - /** - * Reset the combo-box; says remove any selected item and filter text. - */ - public void reset() { - if (ui.getSelectedItem() != null) { - ui.setSelectedItem(null); - } else { - JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); - editorComponent.setText(""); - } - - JComboBox comboBox = ui.getCombobox(); - if (comboBox.isShowing()) { - comboBox.hidePopup(); - } - } - - /** - * Focus combo only if autoFocus ui property is on. - * - * @since 2.8.5 - */ - public void focusCombo() { - if (ui.isAutoFocus()) { - ui.combobox.requestFocusInWindow(); - } - } - - /** - * Modifie l'état filterable de l'ui. - * - * @param oldValue l'ancienne valeur - * @param newValue la nouvelle valeur - */ - protected void setFilterable(Boolean oldValue, Boolean newValue) { - oldValue = oldValue != null && oldValue; - newValue = newValue != null && newValue; - if (oldValue.equals(newValue)) { - return; - } - if (log.isDebugEnabled()) { - log.debug("filterable state : <" + oldValue + " to " + newValue + ">"); - } - if (!newValue) { - JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); - editorComponent.removeFocusListener(EDITOR_TEXT_COMP0NENT_FOCUSLISTENER); - editorComponent.getDocument().removeDocumentListener(EDITOR_TEXT_COMPONENT_DOCUMENTLISTENER); - ((JaxxFilterableComboBoxModel) ui.getCombobox().getModel()).setFilterText(null); - - } else { - JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); - editorComponent.addFocusListener(EDITOR_TEXT_COMP0NENT_FOCUSLISTENER); - editorComponent.getDocument().addDocumentListener(EDITOR_TEXT_COMPONENT_DOCUMENTLISTENER); - EDITOR_TEXT_COMPONENT_DOCUMENTLISTENER.changedUpdate(null); - } - } - - /** - * Modifie l'index du décorateur - * - * @param oldValue l'ancienne valeur - * @param newValue la nouvelle valeur - */ - protected void setIndex(Integer oldValue, Integer newValue) { - if (newValue == null || newValue.equals(oldValue)) { - return; - } - if (log.isDebugEnabled()) { - log.debug("check state : <" + oldValue + " to " + newValue + ">"); - } - AbstractButton button = ui.getIndexes().getButton(newValue); - if (button != null) { - button.setSelected(true); - } - updateUI(newValue, ui.isReverseSort()); - } - - /** - * Modifie l'index du décorateur - * - * @param oldValue l'ancienne valeur - * @param newValue la nouvelle valeur - */ - protected void setSortOrder(Boolean oldValue, Boolean newValue) { - - if (newValue == null || newValue.equals(oldValue)) { - return; - } - if (log.isDebugEnabled()) { - log.debug("check state : <" + oldValue + " to " + newValue + ">"); - } - - updateUI(ui.getIndex(), newValue); - } - - protected void updateUI(int index, boolean reversesort) { - - // change decorator context - decorator.setContextIndex(index); - - // keep selected item - Object previousSelectedItem = ui.getSelectedItem(); - - // remove autocomplete - if (previousSelectedItem != null) { - ui.getCombobox().setSelectedItem(null); - ui.selectedItem = null; - } - - List<O> data = ui.getData(); - - if (ui.isSortable() && CollectionUtils.isNotEmpty(data)) { - try { - // Sort data with the decorator jxpath tokens. - DecoratorUtil.sort(decorator, - data, - index, - reversesort); - - } catch (Exception eee) { - log.warn(eee.getMessage(), eee); - } - } - - // reload the model - SwingUtil.fillComboBox(ui.getCombobox(), data, null); - - if (previousSelectedItem != null) { - ui.setSelectedItem(previousSelectedItem); - } - - ui.getCombobox().requestFocus(); - } - - protected void unselectItem() { - if (ui.selectedItem == null) { - return; - } - - ui.selectedItem = null; - BeanUIUtil.invokeMethod(getMutator(), - ui.getBean(), - (O) null); - } - - /** - * Modifie la valeur sélectionnée dans la liste déroulante. - * - * @param oldValue l'ancienne valeur - * @param newValue la nouvelle valeur - */ - protected void setSelectedItem(O oldValue, O newValue) { - if (oldValue == null && newValue == null) { - return; - } - - if (!getBeanType().isInstance(newValue)) { - newValue = null; - } - - JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); - editorComponent.setText(""); - - if (log.isDebugEnabled()) { - log.debug(ui.getProperty() + " on " + getBeanType() + " :: " + oldValue + " to " + newValue); - } - - BeanUIUtil.invokeMethod(getMutator(), - ui.getBean(), - newValue); - } - - public MultiJXPathDecorator<O> getDecorator() { - return decorator; - } - - /** @return get the type of objects contained in the comboBox model. */ - public Class<O> getBeanType() { - Class<O> result = ui.getBeanType(); - if (result == null) { - result = decorator == null ? null : decorator.getType(); - } - return result; - } - - /** @return le mutateur a utiliser pour modifier le bean associé. */ - protected Method getMutator() { - if (mutator == null && ui.getBean() != null && ui.getProperty() != null) { - mutator = BeanUtil.getMutator(ui.getBean(), ui.getProperty()); - } - return mutator; - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - String propertyName = evt.getPropertyName(); - - if (BeanFilterableComboBox.PROPERTY_SELECTED_ITEM.equals(propertyName)) { - setSelectedItem((O) evt.getOldValue(), (O) evt.getNewValue()); - return; - } - - if (BeanFilterableComboBox.PROPERTY_FILTERABLE.equals(propertyName)) { - - setFilterable((Boolean) evt.getOldValue(), - (Boolean) evt.getNewValue()); - return; - } - - if (BeanFilterableComboBox.PROPERTY_INDEX.equals(propertyName)) { - - // decorator index has changed, force reload of data in ui - setIndex((Integer) evt.getOldValue(), - (Integer) evt.getNewValue()); - return; - } - - if (BeanFilterableComboBox.PROPERTY_REVERSE_SORT.equals(propertyName)) { - - // sort order has changed, force reload of data in ui - setSortOrder((Boolean) evt.getOldValue(), - (Boolean) evt.getNewValue()); - return; - } - - if (BeanFilterableComboBox.PROPERTY_DATA.equals(propertyName)) { - - // list has changed, force reload of index - setIndex(null, ui.getIndex()); - - // list has changed, fire empty property - List list = (List) evt.getOldValue(); - fireEmpty(CollectionUtils.isEmpty(list)); - } - } - - protected void fireEmpty(boolean wasEmpty) { - ui.firePropertyChange(BeanComboBox.PROPERTY_EMPTY, wasEmpty, - isEmpty()); - } - - /** Editor for the Combobox of the UI - uses the decorator */ - class JAXXFilterableComboBoxEditor implements ComboBoxEditor { - - Object oldItem; - - ComboBoxEditor wrapped; - - public JAXXFilterableComboBoxEditor(ComboBoxEditor wrapped) { - this.wrapped = wrapped; - } - - @Override - public JTextComponent getEditorComponent() { - return (JTextComponent) wrapped.getEditorComponent(); - } - - @Override - public void setItem(Object anObject) { - if (log.isDebugEnabled()) { - log.debug("setItem " + anObject + " - " + (anObject != null ? anObject.getClass() : null)); - } - Object item = anObject; - if (anObject != null) { - if (getBeanType().isInstance(anObject)) { - item = decorator.toString(anObject); - oldItem = anObject; - } - try { - wrapped.setItem(item); - - } catch (IllegalStateException e) { - // fail silently - } - } - } - - @Override - public Object getItem() { - JTextComponent editor = getEditorComponent(); - Object newValue = editor.getText(); - if (log.isDebugEnabled()) { - log.debug("getItem " + newValue + " - " + (newValue != null ? newValue.getClass() : null)); - } - - if (oldItem != null && getBeanType().isInstance(oldItem)) { - // The original value is not a string. Should return the value in it's - // original type. - if (newValue.equals(decorator.toString(oldItem))) { - newValue = oldItem; - } - } - if (log.isDebugEnabled()) { - log.debug("getItem 2 " + newValue + " - " + (newValue != null ? newValue.getClass() : null)); - } - return newValue; - } - - @Override - public void selectAll() { - wrapped.selectAll(); - } - - @Override - public void addActionListener(ActionListener l) { - wrapped.addActionListener(l); - } - - @Override - public void removeActionListener(ActionListener l) { - wrapped.removeActionListener(l); - } - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanListHeader.jaxx b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanListHeader.jaxx deleted file mode 100644 index 5df47c9..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanListHeader.jaxx +++ /dev/null @@ -1,117 +0,0 @@ -<!-- - #%L - JAXX :: Widgets - %% - Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - %% - This program 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 General Lesser Public License for more details. - - You should have received a copy of the GNU General Lesser Public - License along with this program. If not, see - <http://www.gnu.org/licenses/lgpl-3.0.html>. - #L% - --> - -<JPanel id='top' layout='{new BorderLayout()}' genericType='O' - implements='jaxx.runtime.bean.BeanTypeAware<O>'> - - <import> - org.nuiton.decorator.JXPathDecorator - javax.swing.border.TitledBorder - </import> - - <!-- show reset property --> - <Boolean id='showReset' javaBean='false'/> - - <!-- show decorator property --> - <Boolean id='showDecorator' javaBean='true'/> - - <!-- flag to reverse the sort --> - <Boolean id='reverseSort' javaBean='false'/> - - <!-- editable combo property --> - <Boolean id='editable' javaBean='true'/> - - <!-- bean type --> - <Class id='beanType' genericType='O' javaBean='null'/> - - <!-- label --> - <String id='labelText' javaBean='null'/> - - <!-- sort index property --> - <Integer id='index' javaBean='0'/> - - <!-- datas of the combo-box --> - <java.util.List id='data' genericType='O' javaBean='null'/> - - <!-- model of sorted property --> - <ButtonGroup id='indexes' - onStateChanged='setIndex((Integer)indexes.getSelectedValue())'/> - - <ButtonGroup id='sortGroup' - onStateChanged='setReverseSort((Boolean)sortGroup.getSelectedValue())'/> - - <!-- ui handler --> - <BeanListHeaderHandler id='handler' genericType='O' constructorParams='this'/> - - <String id='selectedToolTipText' javaBean='null'/> - - <String id='notSelectedToolTipText' javaBean='null'/> - - <String id='popupTitleText' javaBean='null'/> - - <String id='i18nPrefix' javaBean='"beanlist.common."'/> - - <!-- popup to change sorted property--> - <JPopupMenu id='popup' - onPopupMenuWillBecomeInvisible='getChangeDecorator().setSelected(false)' - onPopupMenuCanceled='getChangeDecorator().setSelected(false)'> - - <JLabel id='popupSortLabel'/> - - <JRadioButtonMenuItem id='sortUp'/> - - <JRadioButtonMenuItem id='sortDown'/> - - <JSeparator id='popupSeparator'/> - <JLabel id='popupLabel'/> - - </JPopupMenu> - - <JList id='list' javaBean="new JList()"/> - - <script><![CDATA[ - -public void init(JXPathDecorator<O> decorator, List<O> data) { - handler.init(decorator, data); -} - -public O getSelectedValue() { - return handler.getSelectedValue(); -} - -]]> - </script> - - <JLabel id="label" constraints='BorderLayout.CENTER'/> - - <JToolBar id='toolbar' constraints='BorderLayout.EAST'> - - <!-- le boutton pour reinitialiser la valeur sélectionnée --> - <JButton id='resetSelection' - onActionPerformed='getList().getSelectionModel().clearSelection()'/> - - <!-- le boutton pour changer le tri --> - <JToggleButton id='changeDecorator' - onActionPerformed='getHandler().togglePopup()'/> - </JToolBar> -</JPanel> - diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanListHeaderHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanListHeaderHandler.java deleted file mode 100644 index fdb7295..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanListHeaderHandler.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package jaxx.runtime.swing.editor.bean; - -import jaxx.runtime.swing.JAXXButtonGroup; -import jaxx.runtime.swing.renderer.DecoratorListCellRenderer; -import org.apache.commons.collections.primitives.ArrayIntList; -import org.apache.commons.collections.primitives.IntList; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.decorator.DecoratorUtil; -import org.nuiton.decorator.JXPathDecorator; -import org.nuiton.decorator.MultiJXPathDecorator; - -import javax.swing.DefaultListModel; -import javax.swing.JComponent; -import javax.swing.JList; -import javax.swing.JPopupMenu; -import javax.swing.ListModel; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.List; - -/** - * Le handler d'un {@link BeanListHeader}. - * - * Note: ce handler n'est pas stateless et n'est donc pas partageable entre - * plusieurs ui. - * - * @param <O> le type des objet contenus dans le modèle du composant. - * @author Tony Chemit - chemit@codelutin.com - * @see BeanListHeader - * @since 2.2 - */ -public class BeanListHeaderHandler<O> implements PropertyChangeListener { - - public static final Log log = - LogFactory.getLog(BeanListHeaderHandler.class); - - /** ui if the handler */ - protected BeanListHeader<O> ui; - - /** the decorator of data */ - protected MultiJXPathDecorator<O> decorator; - - /** flag to mark when handler was init (it can be init only once). */ - protected boolean init; - - private final BeanUIUtil.PopupHandler popupHandler = new BeanUIUtil.PopupHandler() { - - @Override - public JPopupMenu getPopup() { - return ui.getPopup(); - } - - @Override - public JComponent getInvoker() { - return ui.getChangeDecorator(); - } - }; - - public BeanListHeaderHandler(BeanListHeader<O> ui) { - this.ui = ui; - } - - /** - * Initialise le handler de l'ui - * - * @param decorator le decorateur a utiliser - * @param data la liste des données a gérer - */ - public void init(JXPathDecorator<O> decorator, List<O> data) { - - if (init) { - throw new IllegalStateException("can not init the handler twice"); - } - init = true; - - if (decorator == null) { - throw new NullPointerException("decorator can not be null (for type " + ui.getBeanType() + ")"); - } - - // list could have changed and the complex binding is not registred... - ui.removeDataBinding(BeanListHeader.BINDING_RESET_SELECTION_ENABLED); - ui.applyDataBinding(BeanListHeader.BINDING_RESET_SELECTION_ENABLED); - - JAXXButtonGroup indexes = ui.getIndexes(); - - this.decorator = BeanUIUtil.createDecorator(decorator); - - // init combobox renderer base on given decorator - ui.getList().setCellRenderer(new DecoratorListCellRenderer(this.decorator)); - - // build popup - popupHandler.preparePopup(ui.getSelectedToolTipText(), - ui.getNotSelectedToolTipText(), - ui.getI18nPrefix(), - ui.getPopupTitleText(), - indexes, - ui.getPopupSeparator(), - ui.getPopupLabel(), - ui.getSortUp(), - ui.getSortDown(), - this.decorator); - - ui.addPropertyChangeListener(this); - - // set datas - ui.setData(data); - - // select sort button - indexes.setSelectedButton(ui.getIndex()); - } - - /** Toggle the popup visible state. */ - public void togglePopup() { - popupHandler.togglePopup(); - } - - /** - * Modifie l'index du décorateur - * - * @param oldValue l'ancienne valeur - * @param newValue la nouvelle valeur - */ - protected void setIndex(Integer oldValue, Integer newValue) { - if (newValue == null || newValue.equals(oldValue)) { - return; - } - if (log.isDebugEnabled()) { - log.debug("check state : <" + oldValue + " to " + newValue + ">"); - } - updateUI(newValue, ui.isReverseSort()); - } - - /** - * Modifie l'index du décorateur - * - * @param oldValue l'ancienne valeur - * @param newValue la nouvelle valeur - */ - - protected void setSortOrder(Boolean oldValue, Boolean newValue) { - - if (newValue == null || newValue.equals(oldValue)) { - return; - } - if (log.isDebugEnabled()) { - log.debug("check state : <" + oldValue + " to " + newValue + ">"); - } - - updateUI(ui.getIndex(), newValue); - } - - @SuppressWarnings({"unchecked"}) - protected void updateUI(int index, boolean reverseSort) { - - // change decorator context - decorator.setContextIndex(index); - - String expression = decorator.getExpression(); - if (log.isDebugEnabled()) { - log.debug("will use expression (index = " + index + ") : " + - expression); - } - - // get the current selection in list - Object[] selection = ui.getList().getSelectedValues(); - - List<O> datas = ui.getData(); - try { - - // Sort data with the decorator jxpath tokens. - DecoratorUtil.sort(decorator, - datas, - index, - reverseSort); - } catch (Exception e) { - log.warn(e.getMessage(), e); - } - - ui.getList().setValueIsAdjusting(true); - try { - - // reload the model - ListModel listModel = ui.getList().getModel(); - - if (listModel instanceof DefaultListModel) { - DefaultListModel model = (DefaultListModel) listModel; - model.removeAllElements(); - for (O data : datas) { - model.addElement(data); - } - - } else { - - ui.getList().setListData(datas.toArray(new Object[datas.size()])); - } - - // re-apply selection - if (selection.length > 0) { - - // re compute selection (the new data could not contains some - // previously selected items) - IntList newSelection = new ArrayIntList(); - for (Object o : selection) { - if (datas.contains(o)) { - - newSelection.add(datas.indexOf(o)); - } - } - - if (!newSelection.isEmpty()) { - - // there is still a selection to re-apply - int[] ints = newSelection.toArray(new int[newSelection.size()]); - newSelection.clear(); - ui.getList().setSelectedIndices(ints); - } - } - - } finally { - ui.getList().setValueIsAdjusting(false); - } - - ui.getList().requestFocus(); - } - - public MultiJXPathDecorator<O> getDecorator() { - return decorator; - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - String propertyName = evt.getPropertyName(); - - if (BeanListHeader.PROPERTY_INDEX.equals(propertyName)) { - - // decorator index has changed, force reload of data in ui - setIndex((Integer) evt.getOldValue(), - (Integer) evt.getNewValue()); - return; - } - - if (BeanListHeader.PROPERTY_REVERSE_SORT.equals(propertyName)) { - - // sort order has changed, force reload of data in ui - setSortOrder((Boolean) evt.getOldValue(), - (Boolean) evt.getNewValue()); - return; - } - - if (BeanListHeader.PROPERTY_DATA.equals(propertyName)) { - - // list has changed, force reload of index - setIndex(-1, ui.getIndex()); - } - - if (BeanListHeader.PROPERTY_LIST.equals(propertyName)) { - - // ui list has changed, replace binding - ui.removeDataBinding(BeanListHeader.BINDING_RESET_SELECTION_ENABLED); - ui.applyDataBinding(BeanListHeader.BINDING_RESET_SELECTION_ENABLED); - } - } - - public O getSelectedValue() { - JList list = ui.getList(); - return list == null ? null : (O) list.getSelectedValue(); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanUIUtil.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanUIUtil.java deleted file mode 100644 index 6f73cc0..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanUIUtil.java +++ /dev/null @@ -1,430 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.editor.bean; - -import jaxx.runtime.swing.JAXXButtonGroup; -import jaxx.runtime.swing.JAXXRuntimeException; -import org.apache.commons.beanutils.MethodUtils; -import org.apache.commons.beanutils.PropertyUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.swingx.autocomplete.AutoCompleteComboBoxEditor; -import org.jdesktop.swingx.autocomplete.AutoCompleteDecorator; -import org.jdesktop.swingx.autocomplete.AutoCompleteDocument; -import org.jdesktop.swingx.autocomplete.ComboBoxAdaptor; -import org.jdesktop.swingx.autocomplete.ObjectToStringConverter; -import org.nuiton.decorator.Decorator; -import org.nuiton.decorator.DecoratorUtil; -import org.nuiton.decorator.JXPathDecorator; -import org.nuiton.decorator.MultiJXPathDecorator; - -import javax.swing.AbstractButton; -import javax.swing.ActionMap; -import javax.swing.ButtonGroup; -import javax.swing.ComboBoxEditor; -import javax.swing.InputMap; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JPopupMenu; -import javax.swing.JRadioButtonMenuItem; -import javax.swing.JSeparator; -import javax.swing.SwingUtilities; -import javax.swing.text.Document; -import javax.swing.text.JTextComponent; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.event.ActionListener; -import java.awt.event.FocusListener; -import java.awt.event.KeyListener; -import java.beans.Introspector; -import java.beans.PropertyChangeListener; -import java.beans.PropertyDescriptor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Date; -import java.util.List; - -import static java.util.Arrays.asList; -import static java.util.Collections.unmodifiableList; -import static org.nuiton.i18n.I18n.t; -import static org.nuiton.i18n.I18n.n; - -/** - * Class with usefull methods used in bean uis. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.2 - */ -public class BeanUIUtil { - - public static final String DEFAULT_POPUP_LABEL = n("bean.popup.label"); - - public static final String DEFAULT_SELECTED_TOOLTIP = n("bean.sort.on"); - - public static final String DEFAULT_NOT_SELECTED_TOOLTIP = n("bean.sort.off"); - - public static final Object[] EMPTY_CLASS_ARRAY = new Object[0]; - - public static void invokeMethod(Method mut, Object source, Object... params) { - - if (mut != null) { - try { - mut.invoke(source, params); - } catch (IllegalAccessException e) { - throw new JAXXRuntimeException(e); - } catch (InvocationTargetException e) { - throw new JAXXRuntimeException(e.getCause()); - } - } - } - - /** - * Encapsule un {@link Decorator} dans un {@link ObjectToStringConverter}. - * - * @param decorator le decorateur a encapsuler. - * @return le converter encapsule dans un {@link ObjectToStringConverter} - */ - public static ObjectToStringConverter newDecoratedObjectToStringConverter(final Decorator<?> decorator) { - - return new ObjectToStringConverter() { - - @Override - public String getPreferredStringForItem(Object item) { - return item instanceof String ? (String) item : item == null ? "" : decorator.toString(item); - } - }; - } - - /** - * Ajout l'auto-complétion sur une liste déroulante, en utilisant le - * converteur donné pour afficher les données. - * - * @param combo la combo à décorer - * @param convertor le converter utilisé pour afficher les données. - */ - public static void decorate(JComboBox combo, ObjectToStringConverter convertor) { - - // tchemit 2010-10-05 since swingx 1.6.2, undecorate stuff is no more - // public and we want to use it, so hack it... - combo.putClientProperty("oldEditor", combo.getEditor()); - combo.putClientProperty("oldDocument", combo.getEditor().getEditorComponent()); - - AutoCompleteDecorator.decorate(combo, convertor); - } - - /** - * Désactive l'aut-complétion sur une liste déroulante, en y repositionnant - * le modèle du document d'édition d'avant auto-complétion. - * - * @param comboBox la liste déroulante à décorer - * @param originalDocument le document original de l'édtieur de la - * liste déroulante. - */ - public static void undecorate(JComboBox comboBox, Document originalDocument) { - - // has not to be editable - comboBox.setEditable(false); - - // configure the text component=editor component - Component c = comboBox.getEditor().getEditorComponent(); - JTextComponent editorComponent = (JTextComponent) c; - editorComponent.setDocument(originalDocument); - editorComponent.setText(null); - //undecorate(comboBox); - - //remove old property change listener - //for (PropertyChangeListener l : c.getPropertyChangeListeners("editor")) { - // if (l instanceof AutoCompletePropertyChangeListener) { - // c.removePropertyChangeListener("editor", l); - // } - //} - - ComboBoxEditor oldEditor = (ComboBoxEditor) comboBox.getClientProperty("oldEditor"); - - if (editorComponent.getDocument() instanceof AutoCompleteDocument) { - AutoCompleteDocument doc = (AutoCompleteDocument) editorComponent.getDocument(); - - if (doc.isStrictMatching()) { - ActionMap map = comboBox.getActionMap(); - - for (String key : COMBO_BOX_ACTIONS) { - map.put(key, null); - } - } - - //remove old property change listener - for (PropertyChangeListener l : comboBox.getPropertyChangeListeners("editor")) { - //if (l instanceof AutoComplete.PropertyChangeListener) { - if (l.getClass().getName().contains("AutoComplete")) { - comboBox.removePropertyChangeListener("editor", l); - } - } - - for (PropertyChangeListener l : comboBox.getPropertyChangeListeners("enabled")) { - //if (l instanceof AutoComplete.PropertyChangeListener) { - if (l.getClass().getName().contains("AutoComplete")) { - comboBox.removePropertyChangeListener("enabled", l); - } - } - - AutoCompleteComboBoxEditor editor = (AutoCompleteComboBoxEditor) comboBox.getEditor(); - comboBox.setEditor(oldEditor); - - //remove old key listener - for (KeyListener l : editorComponent.getKeyListeners()) { - //if (l instanceof AutoComplete.KeyAdapter) { - if (l.getClass().getName().contains("AutoComplete")) { - editorComponent.removeKeyListener(l); - break; - } - } - - undecorate(editorComponent, originalDocument); - - for (ActionListener l : comboBox.getActionListeners()) { - if (l instanceof ComboBoxAdaptor) { - comboBox.removeActionListener(l); - break; - } - } - - //TODO remove aqua fix - - //TODO reset editibility - } - } - - static void undecorate(JTextComponent textComponent, Document originalDocument) { - Document doc = textComponent.getDocument(); - - if (doc instanceof AutoCompleteDocument) { - //remove autocomplete key/action mappings - InputMap map = textComponent.getInputMap(); - - while (map.getParent() != null) { - InputMap parent = map.getParent(); - - //if (parent instanceof AutoComplete.InputMap) { - if (parent.getClass().getName().contains("AutoComplete")) { - map.setParent(parent.getParent()); - } - - map = parent; - } - - textComponent.getActionMap().put("nonstrict-backspace", null); - - //remove old focus listener - for (FocusListener l : textComponent.getFocusListeners()) { - //if (l instanceof AutoComplete.FocusAdapter) { - if (l.getClass().getName().contains("AutoComplete")) { - textComponent.removeFocusListener(l); - break; - } - } - - //reset to original document - //textComponent.setDocument(((AutoCompleteDocument) doc).delegate); - textComponent.setDocument(originalDocument); - } - } - - public static <O> MultiJXPathDecorator<O> createDecorator(JXPathDecorator<O> decorator) { - if (decorator == null) { - throw new NullPointerException( - "can not have a null decorator as parameter"); - } - String separator; - String separatorReplacement; - - if (decorator instanceof Cloneable) { - Cloneable cloneable = (Cloneable) decorator; - - try { - Object clone = MethodUtils.invokeExactMethod(cloneable, - "clone", - EMPTY_CLASS_ARRAY - ); - return (MultiJXPathDecorator<O>) clone; - } catch (Exception e) { - throw new IllegalStateException("Could not clone decorator " + decorator, e); - } - - } - if (decorator instanceof MultiJXPathDecorator<?>) { - - separator = ((MultiJXPathDecorator<?>) decorator).getSeparator(); - separatorReplacement = ((MultiJXPathDecorator<?>) decorator).getSeparatorReplacement(); - - } else { - - separator = "??" + new Date().getTime(); - separatorReplacement = " - "; - } - - return DecoratorUtil.newMultiJXPathDecorator( - decorator.getType(), - decorator.getInitialExpression(), - separator, - separatorReplacement - ); - } - - public static abstract class PopupHandler implements Runnable { - - public static final Log log = LogFactory.getLog(PopupHandler.class); - - public abstract JPopupMenu getPopup(); - - public abstract JComponent getInvoker(); - - @Override - public void run() { - - updatePopup(); - - Dimension dim = getPopup().getPreferredSize(); - - JComponent invoker = getInvoker(); - getPopup().show( - invoker, - (int) (invoker.getPreferredSize().getWidth() - dim.getWidth()), - invoker.getHeight() - ); - } - - /** Toggle the popup visible state. */ - public void togglePopup() { - boolean newValue = !getPopup().isVisible(); - - if (log.isTraceEnabled()) { - log.trace(newValue); - } - - if (!newValue) { - if (getPopup() != null) { - getPopup().setVisible(false); - } - return; - } - SwingUtilities.invokeLater(this); - } - - protected void updatePopup() { - getPopup().pack(); - } - - /** - * Creation de l'ui pour modifier le décorateur. - * - * @param selectedTip - * @param notSelectedTip - * @param i18nPrefix - * @param title - * @param indexes - * @param popupLabel - * @param sortUp - * @param sortDown - * @param decorator le decorateur a utiliser - */ - public void preparePopup(String selectedTip, - String notSelectedTip, - String i18nPrefix, - String title, - ButtonGroup indexes, - JSeparator popupSeparator, - JLabel popupLabel, - AbstractButton sortUp, - AbstractButton sortDown, - MultiJXPathDecorator<?> decorator) { - if (selectedTip == null) { - // use default selected tip text - selectedTip = DEFAULT_SELECTED_TOOLTIP; - } - if (notSelectedTip == null) { - // use default selected tip text - notSelectedTip = DEFAULT_NOT_SELECTED_TOOLTIP; - } - JPopupMenu popup = getPopup(); - - //Container container = ui.getIndexesContainer(); - - int nbContext = decorator.getNbContext(); - if (nbContext > 1) { - for (int i = 0; i < nbContext; i++) { - String property = i18nPrefix + decorator.getProperty(i); - String propertyI18n = t(property); - JRadioButtonMenuItem button = new JRadioButtonMenuItem(propertyI18n); - button.putClientProperty(JAXXButtonGroup.BUTTON8GROUP_CLIENT_PROPERTY, indexes); - button.putClientProperty(JAXXButtonGroup.VALUE_CLIENT_PROPERTY, i); - popup.add(button); - if (selectedTip != null) { - button.putClientProperty(JAXXButtonGroup.SELECTED_TIP_CLIENT_PROPERTY, t(selectedTip, propertyI18n)); - } - if (notSelectedTip != null) { - button.putClientProperty(JAXXButtonGroup.NOT_SELECTED_TIP_CLIENT_PROPERTY, t(notSelectedTip, propertyI18n)); - } - button.setSelected(false); - indexes.add(button); - } - } - if (title == null) { - // use default popup title - title = DEFAULT_POPUP_LABEL; - - Class<?> type = decorator.getType(); - String beanI18nKey; - if (type == null) { - beanI18nKey = n("bean.unknown.type"); - } else { - beanI18nKey = i18nPrefix + Introspector.decapitalize(type.getSimpleName()); - } - String beanI18n = t(beanI18nKey); - title = t(title, beanI18n); - } else { - title = t(title); - } - - sortDown.putClientProperty(JAXXButtonGroup.SELECTED_TIP_CLIENT_PROPERTY, t("bean.sort.down.tip")); - sortDown.putClientProperty(JAXXButtonGroup.NOT_SELECTED_TIP_CLIENT_PROPERTY, t("bean.sort.down.toSelect.tip")); - - sortUp.putClientProperty(JAXXButtonGroup.SELECTED_TIP_CLIENT_PROPERTY, t("bean.sort.up.tip")); - sortUp.putClientProperty(JAXXButtonGroup.NOT_SELECTED_TIP_CLIENT_PROPERTY, t("bean.sort.up.toSelect.tip")); - - if (nbContext < 2) { - getPopup().remove(popupSeparator); - getPopup().remove(popupLabel); - } - popupLabel.setText(title); - getPopup().setLabel(title); - getPopup().invalidate(); - } - } - - - //these keys were pulled from BasicComboBoxUI from Sun JDK 1.6.0_20 - - private static final List<String> COMBO_BOX_ACTIONS = unmodifiableList(asList("selectNext", - "selectNext2", "selectPrevious", "selectPrevious2", "pageDownPassThrough", - "pageUpPassThrough", "homePassThrough", "endPassThrough")); -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/DateCellEditor.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/DateCellEditor.java deleted file mode 100644 index 6a8a7fc..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/DateCellEditor.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.editor.cell; - -import java.awt.Component; -import java.util.Date; -import javax.swing.AbstractCellEditor; -import javax.swing.JTable; -import javax.swing.table.TableCellEditor; -import jaxx.runtime.swing.JAXXDatePicker; - -/** - * @author Sylvain Lletellier - */ -public class DateCellEditor extends AbstractCellEditor - implements TableCellEditor { - - protected JAXXDatePicker datePicker; - - public DateCellEditor() { - datePicker = new JAXXDatePicker(); - } - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - datePicker.setDate((Date) value); - return datePicker; - } - - @Override - public Object getCellEditorValue() { - return datePicker.getDate(); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/FileCellEditor.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/FileCellEditor.java deleted file mode 100644 index 4e6ecc4..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/FileCellEditor.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.editor.cell; - -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import javax.swing.AbstractCellEditor; -import javax.swing.JTable; -import javax.swing.table.TableCellEditor; -import jaxx.runtime.swing.editor.FileEditor; - -/** - * @author Sylvain Lletellier - */ -public class FileCellEditor extends AbstractCellEditor - implements TableCellEditor { - - protected FileEditor fileEditor; - - public FileCellEditor() { - setFileEditor(new FileEditor()); - } - - public FileCellEditor(FileEditor editor) { - setFileEditor(editor); - } - - public void setFileEditor(FileEditor fileEditor) { - this.fileEditor = fileEditor; - fileEditor.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - fireEditingStopped(); - } - }); - } - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - File file = (File) value; - fileEditor.setSelectedFile(file); - return fileEditor; - } - - @Override - public Object getCellEditorValue() { - return fileEditor.getSelectedFile(); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/KeyStrokeCellEditor.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/KeyStrokeCellEditor.java deleted file mode 100644 index aba3a6e..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/KeyStrokeCellEditor.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.editor.cell; - -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import javax.swing.AbstractCellEditor; -import javax.swing.JTable; -import javax.swing.KeyStroke; -import javax.swing.table.TableCellEditor; -import jaxx.runtime.swing.editor.KeyStrokeEditor; - -/** - * @author Sylvain Lletellier - */ -public class KeyStrokeCellEditor extends AbstractCellEditor - implements TableCellEditor { - - protected KeyStrokeEditor keyStrokeEditor; - - public KeyStrokeCellEditor() { - keyStrokeEditor = new KeyStrokeEditor(); - keyStrokeEditor.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - fireEditingStopped(); - } - }); - } - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { - keyStrokeEditor.setKeyStroke((KeyStroke) value); - return keyStrokeEditor; - } - - @Override - public Object getCellEditorValue() { - return keyStrokeEditor.getKeyStroke(); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/NumberCellEditor.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/NumberCellEditor.java deleted file mode 100644 index 5397e65..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/NumberCellEditor.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.editor.cell; - -import java.awt.Component; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import javax.swing.AbstractCellEditor; -import javax.swing.JTable; -import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; -import javax.swing.event.AncestorEvent; -import javax.swing.event.AncestorListener; -import javax.swing.table.TableCellEditor; -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.swing.editor.NumberEditor; - -/** - * @author Sylvain Lletellier - * @deprecated since 2.17, prefer use {@code org.nuiton.jaxx.widgets.editor.cell.NumberCellEditor}. - */ -@Deprecated -public class NumberCellEditor<E extends Number> extends AbstractCellEditor - implements TableCellEditor, FocusListener, AncestorListener { - - private static final long serialVersionUID = 1L; - - protected final NumberEditor numberEditor; - - /** constructor */ - public NumberCellEditor(Class<E> type, boolean useSign) { - numberEditor = new NumberEditor(); - numberEditor.getTextField().setHorizontalAlignment(SwingConstants.RIGHT); - numberEditor.getTextField().setBorder(null); - numberEditor.getTextField().addFocusListener(this); - numberEditor.getTextField().addAncestorListener(this); - - numberEditor.setModelType(type); - - numberEditor.setUseSign(useSign); - numberEditor.init(); - } - - @Override - public Component getTableCellEditorComponent(JTable table, Object value, - boolean isSelected, int row, int column) { - - E number = (E) value; - numberEditor.setModel(number); - numberEditor.setModelText(JAXXUtil.getStringValue(number)); - return numberEditor; - } - - public NumberEditor getNumberEditor() { - return numberEditor; - } - - @Override - public E getCellEditorValue() { - return (E)numberEditor.getModel(); - } - - @Override - public void focusGained(FocusEvent e) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - numberEditor.getTextField().requestFocus(); - numberEditor.getTextField().selectAll(); - } - }); - } - - @Override - public void focusLost(FocusEvent e) { - // commenting the next line fixes http://www.nuiton.org/issues/3517 and http://www.nuiton.org/issues/3518 -// cancelCellEditing(); - } - - @Override - public void ancestorAdded(AncestorEvent event) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - numberEditor.getTextField().requestFocus(); - numberEditor.getTextField().selectAll(); - } - }); - } - - @Override - public void ancestorRemoved(AncestorEvent event) { - } - - @Override - public void ancestorMoved(AncestorEvent event) { - } - - @Override - public boolean stopCellEditing() { - boolean result = super.stopCellEditing(); - // Reset previous data to avoid keeping it on other cell edition - if (result) { - numberEditor.setModel(null); - // Use empty string, otherwise there is a NPE in NumberEditorHandler - numberEditor.setModelText(""); - // force binding, I do not know why the textfield text is not emptied - // if we do not force it - numberEditor.applyDataBinding(NumberEditor.BINDING_TEXT_FIELD_TEXT); - } - return result; - } - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinate.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinate.java deleted file mode 100644 index 90dd0db..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinate.java +++ /dev/null @@ -1,336 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.jdesktop.beans.AbstractSerializableBean; - -import java.util.regex.Pattern; - -/** - * Geo coordinate in degree decimal, minute format. - * - * Created on 10/23/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class DmdCoordinate extends AbstractSerializableBean { - - private static final long serialVersionUID = 1L; - - public static final String COORDINATE_STRING_PATTERN = "%s%s°%s'%s"; - - public static final Pattern COORDINATE_PATTERN = - Pattern.compile("(.*)°(.*)'(.*)"); - - public static final String PROPERTY_SIGN = "sign"; - - public static final String PROPERTY_DEGREE = "degree"; - - public static final String PROPERTY_MINUTE = "minute"; - - public static final String PROPERTY_DECIMAL = "decimal"; - - protected boolean sign; - - protected Integer degree; - - protected Integer minute; - - protected Integer decimal; - - public static DmdCoordinate empty() { - return new DmdCoordinate(); - } - - /** - * Methode statique de fabrique de position a partir d'un autre {@link DmdCoordinate}. - * - * Note : Si la valeur vaut <code>null</code>, alors on - * reinitialise les composants de la position a <code>null</code> et la - * methode {@link #isNull()} vaudra alors {@code true}. - * - * @param decimal la valeur au format decimal - * @return une nouvelle instance de position convertie - */ - public static DmdCoordinate valueOf(DmdCoordinate decimal) { - DmdCoordinate r = empty(); - if (decimal != null) { - r.setSign(decimal.isSign()); - r.setDegree(decimal.getDegree()); - r.setMinute(decimal.getMinute()); - r.setDecimal(decimal.getDecimal()); - } - return r; - } - - /** - * Methode statique de fabrique de position a partir d'une valeur du format - * decimal. - * - * Note : Si la valeur (au format decimal) vaut <code>null</code>, alors on - * reinitialise les composants de la position a <code>null</code> et la - * methode {@link #isNull()} vaudra alors {@code true}. - * - * @param decimal la valeur au format decimal - * @return une nouvelle instance de position convertie - */ - public static DmdCoordinate valueOf(Float decimal) { - DmdCoordinate r = new DmdCoordinate(); - r.fromDecimal(decimal); - return r; - } - - /** - * Methode statique de fabrique de position a partir d'une valeur du format - * degre décimale minute. - * - * @param d la valeur des degres - * @param m la valeur des minutes - * @param dc la valeur des décimales de minutes - * @return une nouvelle instance de position convertie - */ - public static DmdCoordinate valueOf(boolean sign, - Integer d, - Integer m, - Integer dc) { - DmdCoordinate r = new DmdCoordinate(); - r.setSign(sign); - r.setDegree(d); - r.setMinute(m); - r.setDecimal(dc); - return r; - } - - public boolean isSign() { - return sign; - } - - public Integer getDegree() { - return degree; - } - - public Integer getMinute() { - return minute; - } - - public Integer getDecimal() { - return decimal; - } - - public void setSign(boolean sign) { - Object oldValue = isSign(); - this.sign = sign; - firePropertyChange(PROPERTY_SIGN, oldValue, sign); - } - - public void setDegree(Integer degree) { - Object oldValue = getDegree(); - this.degree = degree; - firePropertyChange(PROPERTY_DEGREE, oldValue, degree); - } - - public void setMinute(Integer minute) { - Object oldValue = getMinute(); - this.minute = minute; - firePropertyChange(PROPERTY_MINUTE, oldValue, minute); - } - - public void setDecimal(Integer decimal) { - Object oldValue = getDecimal(); - this.decimal = decimal; - firePropertyChange(PROPERTY_DECIMAL, oldValue, decimal); - } - - /** - * @return {@code true} si aucune composante n'est renseignée, - * {@code false} autrement. - */ - public boolean isNull() { - return degree == null && minute == null && decimal == null; - } - - public boolean isDegreeNull() { - return degree == null || degree == 0; - } - - public boolean isMinuteNull() { - return minute == null || minute == 0; - } - - public boolean isDecimalNull() { - return decimal == null || decimal == 0; - } - - /** - * Mets a jour les composants de la position a partir d'une valeur decimal. - * - * Note : Si la valeur (au format decimal) vaut <code>null</code>, alors on - * reinitialise les composants de la position a <code>null</code> et la - * methode {@link #isNull()} vaudra alors {@code true}. - * - * @param decimalValue la valeur decimale a convertir (qui peut etre nulle). - */ - public void fromDecimal(Float decimalValue) { - Integer d = null; - Integer m = null; - Integer dc = null; - boolean si = false; - if (decimalValue != null) { - si = decimalValue < 0; - - float absDecimal = Math.abs(decimalValue); - - d = (int) (Math.round(absDecimal + 0.5) - 1); - int rest = Math.round(100 * 60.0f * (absDecimal - d)); - if (rest > 0) { - m = rest / 100; - dc = (rest - m * 100); - } - } - - degree = d; - minute = m; - decimal = dc; - sign = si; - - if (decimal != null) { - removeTrailingZero(); - } - } - - public Float toDecimal() { - if (isNull()) { - return null; - } - Integer d = getNotNullDegree(); - Integer m = getNotNullMinute(); - Integer dc = getNotNullDecimal(); - Float result = Float.valueOf(d); - result += (m + (dc / 100f)) / 60.0f; - if (sign) { - result *= -1; - } - return result; - } - - public void addTrailingZero() { - - if (degree == null) { - degree = 0; - } - if (minute == null) { - minute = 0; - } - if (decimal == null) { - decimal = 0; - } - } - - public void removeTrailingZero() { - if (degree != null && degree == 0) { - degree = null; - } - if (minute != null && minute == 0) { - minute = null; - } - if (decimal != null && decimal == 0) { - decimal = null; - } - } - - public Integer getSignedDegree() { - Integer result = null; - if (!isDegreeNull()) { - result = degree; - if (isSign()) { - result *= -1; - } - } - return result; - } - - public int getNotNullDegree() { - return isDegreeNull() ? 0 : degree; - } - - public int getNotNullMinute() { - return isMinuteNull() ? 0 : minute; - } - - public int getNotNullDecimal() { - return isDecimalNull() ? 0 : decimal; - } - - public boolean isLatitudeDegreeValid() { - return isDegreeValid(false); - } - - public boolean isLongitudeDegreeValid() { - return isDegreeValid(true); - } - - public boolean isMinuteValid() { - boolean result = true; - if (!isMinuteNull()) { - if (minute == 60) { - - // can not have decimal - result = isDecimalNull(); - } else { - result = 0 <= minute && minute < 60; - } - } - return result; - } - - public boolean isDecimalValid() { - return isDecimalNull() || (0 <= decimal && decimal < 100); - } - - @Override - public String toString() { - return "DmdCoordinateComponent{" + - "sign=" + sign + - ", degree=" + degree + - ", minute=" + minute + - ", decimal=" + decimal + - '}'; - } - - protected boolean isDegreeValid(boolean longitude) { - boolean result = true; - if (!isDegreeNull()) { - int bound = longitude ? 180 : 90; - if (bound == degree) { - - // can not have minute nor decimal - result = isMinuteNull() && isDecimalNull(); - } else { - result = 0 <= degree && degree < bound; - } - } - return result; - } - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateConverter.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateConverter.java deleted file mode 100644 index 05395fd..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateConverter.java +++ /dev/null @@ -1,143 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.beanutils.ConversionException; -import org.apache.commons.lang3.StringUtils; -import org.nuiton.converter.NuitonConverter; - -import java.util.regex.Matcher; - -import static org.nuiton.i18n.I18n.t; - -/** - * Created on 11/25/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class DmdCoordinateConverter implements NuitonConverter<DmdCoordinate> { - - protected boolean useSign; - - protected boolean forLongitude; - - public void setUseSign(boolean useSign) { - this.useSign = useSign; - } - - public void setForLongitude(boolean forLongitude) { - this.forLongitude = forLongitude; - } - - @Override - public <T> T convert(Class<T> aClass, Object value) { - - if (!isEnabled(aClass)) { - throw new ConversionException( - t("jaxx.error.no.convertor.coordinateDmd", value)); - } - - Object result = null; - - if (value == null) { - - if (aClass.equals(String.class)) { - - result = String.format( - DmdCoordinate.COORDINATE_STRING_PATTERN, - useSign ? "-" : "", - StringUtils.leftPad("", forLongitude ? 3 : 2, ' '), - StringUtils.leftPad("", 2, ' '), - StringUtils.leftPad("", 2, ' ')); - } - } else { - - if (aClass.equals(value.getClass())) { - - // same class, no convertion to do - result = value; - } else if (value instanceof String) { - - // String to Value - - Matcher matcher = DmdCoordinate.COORDINATE_PATTERN.matcher((String) value); - - if (matcher.matches()) { - - String degresStr = matcher.group(1).replaceAll("\\s", ""); - String minutesStr = matcher.group(2).replaceAll("\\s", ""); - String decimalesStr = matcher.group(3).replaceAll("\\s", ""); - - Integer degre = degresStr.isEmpty() || "-".equals(degresStr) ? null : Math.abs(Integer.valueOf(degresStr)); - Integer minutes = minutesStr.isEmpty() ? null : Integer.valueOf(minutesStr); - Integer decimal = decimalesStr.isEmpty() ? null : Integer.valueOf(decimalesStr); - - boolean signed = degresStr.contains("-"); - result = DmdCoordinate.valueOf(signed, - degre, - minutes, - decimal); - } - - } else if (value instanceof DmdCoordinate) { - - // Value to String - - DmdCoordinate coordinate = (DmdCoordinate) value; - - boolean sign = coordinate.isSign(); - String signStr = sign ? "-" : ""; - - Integer degree = coordinate.getDegree(); - String degreeStr = degree == null ? "" : degree.toString(); - - Integer minute = coordinate.getMinute(); - String minuteStr = minute == null ? "" : minute.toString(); - - Integer decimal = coordinate.getDecimal(); - String decimalStr = decimal == null ? "" : decimal.toString(); - - result = String.format( - DmdCoordinate.COORDINATE_STRING_PATTERN, - signStr, - StringUtils.leftPad(degreeStr, forLongitude ? 3 : 2, ' '), - StringUtils.leftPad(minuteStr, 2, ' '), - StringUtils.leftPad(decimalStr, 2, ' ')); - } - } - return aClass.cast(result); - } - - protected boolean isEnabled(Class<?> aClass) { - return String.class.isAssignableFrom(aClass) || - DmdCoordinate.class.isAssignableFrom(aClass); - } - - @Override - public Class<DmdCoordinate> getType() { - return DmdCoordinate.class; - } - -} - diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorHandler.java deleted file mode 100644 index 2b6ead2..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorHandler.java +++ /dev/null @@ -1,306 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Preconditions; -import jaxx.runtime.spi.UIHandler; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.util.beans.BeanUtil; - -import javax.swing.JFormattedTextField; -import javax.swing.text.DefaultFormatterFactory; -import java.awt.event.KeyEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.lang.reflect.Method; -import java.text.ParseException; - -/** - * Created on 10/16/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class DmdCoordinateEditorHandler implements UIHandler<DmdCoordinateEditor> { - - /** Logger. */ - private static final Log log = - LogFactory.getLog(DmdCoordinateEditorHandler.class); - - private DmdCoordinateEditor ui; - - protected Method signMutator; - - protected Method degreMutator; - - protected Method minuteMutator; - - protected Method decimalMutator; - - protected boolean valueIsAdjusting; - - protected boolean valueModelIsAdjusting; - - protected DmdCoordinateConverter signedConverter; - - protected DmdCoordinateConverter unsignedConverter; - - protected DefaultFormatterFactory signedFormatterFactory; - - protected DefaultFormatterFactory unsignedFormatterFactory; - - @Override - public void beforeInit(DmdCoordinateEditor ui) { - this.ui = ui; - // can't use the one from ConverterUtil since we deal with some internal states - this.signedConverter = new DmdCoordinateConverter(); - this.signedConverter.setUseSign(true); - this.unsignedConverter = new DmdCoordinateConverter(); - } - - @Override - public void afterInit(DmdCoordinateEditor ui) { - // nothing special to do here - } - - public void init(boolean longitudeEditor) { - - final DmdCoordinateEditorModel model = ui.getModel(); - - Preconditions.checkNotNull(model.getBean(), "could not find bean in " + ui); - Preconditions.checkNotNull(model.getPropertySign(), "could not find propertySign in " + ui); - Preconditions.checkNotNull(model.getPropertyDegree(), "could not find propertyDegree in " + ui); - Preconditions.checkNotNull(model.getPropertyMinute(), "could not find propertyMinute in " + ui); - Preconditions.checkNotNull(model.getPropertyDecimal(), "could not find propertyDecimal in " + ui); - - Object bean = model.getBean(); - signMutator = BeanUtil.getMutator(bean, model.getPropertySign()); - Preconditions.checkNotNull(signMutator, "could not find mutator for " + model.getPropertySign()); - - degreMutator = BeanUtil.getMutator(bean, model.getPropertyDegree()); - Preconditions.checkNotNull(degreMutator, "could not find mutator for " + model.getPropertyDegree()); - - minuteMutator = BeanUtil.getMutator(bean, model.getPropertyMinute()); - Preconditions.checkNotNull(minuteMutator, "could not find mutator for " + model.getPropertyMinute()); - - decimalMutator = BeanUtil.getMutator(bean, model.getPropertyDecimal()); - Preconditions.checkNotNull(decimalMutator, "could not find mutator for " + model.getPropertyDecimal()); - - signedConverter.setForLongitude(longitudeEditor); - unsignedConverter.setForLongitude(longitudeEditor); - - { - // prepare unsigned formatter factory - String pattern = getMaskFormatterPattern(longitudeEditor, false); - MaskFormatterFromConverter<DmdCoordinate> maskFormatter; - try { - maskFormatter = MaskFormatterFromConverter.newFormatter( - DmdCoordinate.class, - pattern, unsignedConverter); - maskFormatter.setValidCharacters(" 01234567890"); - maskFormatter.setCommitsOnValidEdit(true); - unsignedFormatterFactory = new DefaultFormatterFactory(maskFormatter); - } catch (ParseException e) { - // can't happen here - throw new RuntimeException(e); - } - } - { - // prepare signed formatter factory - String pattern = getMaskFormatterPattern(longitudeEditor, true); - MaskFormatterFromConverter<DmdCoordinate> maskFormatter; - try { - maskFormatter = MaskFormatterFromConverter.newFormatter( - DmdCoordinate.class, - pattern, signedConverter); - maskFormatter.setValidCharacters(" 01234567890"); - maskFormatter.setCommitsOnValidEdit(true); - signedFormatterFactory = new DefaultFormatterFactory(maskFormatter); - } catch (ParseException e) { - // can't happen here - throw new RuntimeException(e); - } - } - - JFormattedTextField editor = ui.getEditor(); - editor.setFormatterFactory(model.isSign() ? - signedFormatterFactory : - unsignedFormatterFactory); - editor.setFocusLostBehavior(JFormattedTextField.COMMIT); - - // When editor changes his value, propagate it to model - editor.addPropertyChangeListener("value", new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - DmdCoordinate newValue = (DmdCoordinate) evt.getNewValue(); - if (log.isDebugEnabled()) { - log.debug("Value has changed: " + newValue); - } - model.setValue(newValue); - } - }); - - // When model sign changed, let's push it back in bean - model.addPropertyChangeListener( - DmdCoordinateEditorModel.PROPERTY_SIGN, - new ModelPropertyChangeListener(model, signMutator)); - - // When model degre changed, let's push it back in bean - model.addPropertyChangeListener( - DmdCoordinateEditorModel.PROPERTY_DEGREE, - new ModelPropertyChangeListener(model, degreMutator)); - - // When model minute changed, let's push it back in bean - model.addPropertyChangeListener( - DmdCoordinateEditorModel.PROPERTY_MINUTE, - new ModelPropertyChangeListener(model, minuteMutator)); - - // When model decimal changed, let's push it back in bean - model.addPropertyChangeListener( - DmdCoordinateEditorModel.PROPERTY_DECIMAL, - new ModelPropertyChangeListener(model, decimalMutator)); - } - - public void setValue(DmdCoordinate value, boolean pushToModel) { - - if (valueModelIsAdjusting) { - // avoid re-entrant code - return; - } - - valueIsAdjusting = !pushToModel; - - try { - ui.getEditor().setValue(value); - } finally { - valueIsAdjusting = false; - } - } - - public void resetEditor() { - // set null value to model - setValue(null, true); - - // use back unsigned format - ui.getEditor().setFormatterFactory(unsignedFormatterFactory); - } - - public void onKeyReleased(KeyEvent e) { - - JFormattedTextField source = (JFormattedTextField) e.getSource(); - - char keyChar = e.getKeyChar(); - int caretPosition = source.getCaretPosition(); - if (log.isDebugEnabled()) { - log.debug("Key pressed: " + keyChar + " (caret position: " + caretPosition + ")"); - } - - if (keyChar == '-') { - - DmdCoordinate value = (DmdCoordinate) source.getValue(); - - DefaultFormatterFactory newFactory; - - // try to switch unsigned to signed - - boolean useSign = ui.getModel().isSign(); - - if (useSign) { - - if (log.isDebugEnabled()) { - log.debug("Switch to unsigned"); - } - - newFactory = unsignedFormatterFactory; - - // remove a sign - caretPosition--; - } else { - // switch to signed - if (log.isDebugEnabled()) { - log.debug("Switch to signed"); - } - newFactory = signedFormatterFactory; - - // add a sign - caretPosition++; - } - - DmdCoordinate newValue = DmdCoordinate.valueOf(value); - newValue.setSign(!useSign); - - source.setFormatterFactory(newFactory); - source.setValue(newValue); - - e.consume(); - - source.setCaretPosition(caretPosition); - } - } - - protected String getMaskFormatterPattern(boolean longitudeEditor, boolean useSign) { - String pattern = "**°**''**"; - if (longitudeEditor) { - // add one more degre - pattern = "*" + pattern; - } - if (useSign) { - pattern = "-" + pattern; - } - return pattern; - } - - private class ModelPropertyChangeListener implements PropertyChangeListener { - - private final DmdCoordinateEditorModel model; - - private final Method mutator; - - private ModelPropertyChangeListener(DmdCoordinateEditorModel model, - Method mutator) { - this.model = model; - this.mutator = mutator; - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (!valueIsAdjusting) { - Object newValue = evt.getNewValue(); - - try { - - valueModelIsAdjusting = true; - try { - mutator.invoke(model.getBean(), newValue); - } finally { - valueModelIsAdjusting = false; - } - - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorModel.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorModel.java deleted file mode 100644 index beb4bb7..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorModel.java +++ /dev/null @@ -1,122 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import java.io.Serializable; - -/** - * Created on 10/16/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class DmdCoordinateEditorModel extends DmdCoordinate { - - public static final String PROPERTY_BEAN = "bean"; - - public static final String PROPERTY_PROPERTY_SIGN = "propertySign"; - - public static final String PROPERTY_PROPERTY_DEGREE = "propertyDegree"; - - public static final String PROPERTY_PROPERTY_MINUTE = "propertyMinute"; - - public static final String PROPERTY_PROPERTY_DECIMAL = "propertyDecimal"; - - private static final long serialVersionUID = 1L; - - /** Bean where to push data. */ - protected Serializable bean; - - /** Name of the property of the bean to fire the change of the {@link #sign}. */ - protected String propertySign; - - /** Name of the property of the bean to fire the change of the {@link #degree}. */ - protected String propertyDegre; - - /** Name of the property of the bean to fire the change of the {@link #minute}. */ - protected String propertyMinute; - - /** Name of the property of the bean to fire the change of the {@link #decimal}. */ - protected String propertyDecimal; - - public Serializable getBean() { - return bean; - } - - public void setBean(Serializable bean) { - Object oldValue = getBean(); - this.bean = bean; - firePropertyChange(PROPERTY_BEAN, oldValue, bean); - } - - public String getPropertySign() { - return propertySign; - } - - public void setPropertySign(String propertySign) { - Object oldValue = getPropertySign(); - this.propertySign = propertySign; - firePropertyChange(PROPERTY_PROPERTY_SIGN, oldValue, propertySign); - } - - public String getPropertyDegree() { - return propertyDegre; - } - - public void setPropertyDegree(String propertyDegree) { - Object oldValue = getPropertyDegree(); - this.propertyDegre = propertyDegree; - firePropertyChange(PROPERTY_PROPERTY_DEGREE, oldValue, propertyDegree); - } - - public String getPropertyMinute() { - return propertyMinute; - } - - public void setPropertyMinute(String propertyMinute) { - Object oldValue = getPropertyMinute(); - this.propertyMinute = propertyMinute; - firePropertyChange(PROPERTY_PROPERTY_MINUTE, oldValue, propertyMinute); - } - - public String getPropertyDecimal() { - return propertyDecimal; - } - - public void setPropertyDecimal(String propertyDecimal) { - Object oldValue = getPropertyDecimal(); - this.propertyDecimal = propertyDecimal; - firePropertyChange(PROPERTY_PROPERTY_DECIMAL, oldValue, propertyDecimal); - } - - public void setValue(DmdCoordinate value) { - setSign(value != null && value.isSign()); - setDegree(value == null ? null : value.getDegree()); - setMinute(value == null ? null : value.getMinute()); - setDecimal(value == null ? null : value.getDecimal()); - } - - public String getStringPattern() { - return COORDINATE_STRING_PATTERN; - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinate.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinate.java deleted file mode 100644 index bdd031e..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinate.java +++ /dev/null @@ -1,364 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.jdesktop.beans.AbstractSerializableBean; - -import java.util.regex.Pattern; - -/** - * Geo coordinate in degree, minute, second format. - * - * Created on 10/23/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class DmsCoordinate extends AbstractSerializableBean { - - public static final String COORDINATE_STRING_PATTERN = "%s%s°%s'%s''"; - - public static final Pattern COORDINATE_PATTERN = - Pattern.compile("(.*)°(.*)'(.*)''"); - - private static final long serialVersionUID = 1L; - - public static final String PROPERTY_SIGN = "sign"; - - public static final String PROPERTY_DEGREE = "degree"; - - public static final String PROPERTY_MINUTE = "minute"; - - public static final String PROPERTY_SECOND = "second"; - - protected boolean sign; - - protected Integer degree; - - protected Integer minute; - - protected Integer second; - - public static DmsCoordinate empty() { - return new DmsCoordinate(); - } - - /** - * Methode statique de fabrique de position a partir d'un autre {@link DmsCoordinate}. - * - * Note : Si la valeur vaut <code>null</code>, alors on - * reinitialise les composants de la position a <code>null</code> et la - * methode {@link #isNull()} vaudra alors {@code true}. - * - * @param decimal la valeur au format decimal - * @return une nouvelle instance de position convertie - */ - public static DmsCoordinate valueOf(DmsCoordinate decimal) { - DmsCoordinate r = new DmsCoordinate(); - if (decimal != null) { - r.setSign(decimal.isSign()); - r.setDegree(decimal.getDegree()); - r.setMinute(decimal.getMinute()); - r.setSecond(decimal.getSecond()); - } - return r; - } - - /** - * Methode statique de fabrique de position a partir d'une valeur du format - * decimal. - * - * Note : Si la valeur (au format decimal) vaut <code>null</code>, alors on - * reinitialise les composants de la position a <code>null</code> et la - * methode {@link #isNull()} vaudra alors {@code true}. - * - * @param decimal la valeur au format decimal - * @return une nouvelle instance de position convertie - */ - public static DmsCoordinate valueOf(Float decimal) { - DmsCoordinate r = new DmsCoordinate(); - r.fromDecimal(decimal); - return r; - } - - /** - * Methode statique de fabrique de position a partir d'une valeur du format - * degre-minute-seconde. - * - * @param d la valeur des degres - * @param m la valeur des minutes - * @param s la valeur des secondes - * @return une nouvelle instance de position convertie - */ - public static DmsCoordinate valueOf(boolean sign, Integer d, Integer m, Integer s) { - DmsCoordinate r = new DmsCoordinate(); - r.setSign(sign); - r.setDegree(d); - r.setMinute(m); - r.setSecond(s); - return r; - } - - public boolean isSign() { - return sign; - } - - public Integer getDegree() { - return degree; - } - - public Integer getMinute() { - return minute; - } - - public Integer getSecond() { - return second; - } - - public void setSign(boolean sign) { - Object oldValue = isSign(); - this.sign = sign; - firePropertyChange(PROPERTY_SIGN, oldValue, sign); - } - - public void setDegree(Integer degree) { - Object oldValue = getDegree(); - this.degree = degree; - firePropertyChange(PROPERTY_DEGREE, oldValue, degree); - } - - public void setMinute(Integer minute) { - Object oldValue = getMinute(); - this.minute = minute; - firePropertyChange(PROPERTY_MINUTE, oldValue, minute); - } - - public void setSecond(Integer second) { - Object oldValue = getSecond(); - this.second = second; - firePropertyChange(PROPERTY_SECOND, oldValue, second); - } - - public boolean isDegreeNull() { - return degree == null || degree == 0; - } - - public boolean isMinuteNull() { - return minute == null || minute == 0; - } - - public boolean isSecondNull() { - return second == null || second == 0; - } - - /** - * @return {@code true} si aucune composante n'est renseignée, - * {@code false} autrement. - */ - public boolean isNull() { - return degree == null && minute == null && second == null; - } - - /** - * Mets a jour les composants de la position a partir d'une valeur decimal. - * - * Note : Si la valeur (au format decimal) vaut <code>null</code>, alors on - * reinitialise les composants de la position a <code>null</code> et la - * methode {@link #isNull()} vaudra alors {@code true}. - * - * @param decimal la valeur decimale a convertir (qui peut etre nulle). - */ - public void fromDecimal(Float decimal) { - Integer d = null; - Integer m = null; - Integer s = null; - boolean si = false; - if (decimal != null) { - si = decimal < 0; - - decimal = Math.abs(decimal); - int remain = 0; - - d = (int) (Math.round(decimal + 0.5) - 1); - m = 0; - s = 0; - decimal = 60.0f * (decimal - d); - if (decimal > 0) { - m = (int) (Math.round(decimal + 0.5) - 1); - decimal = 60 * (decimal - m); - if (decimal > 0) { - s = (int) (Math.round(decimal + 0.5) - 1); - remain = (int) (10 * (decimal - s)); - } - } - if (remain > 9) { - s++; - } - if (s == 60) { - m++; - s = 0; - } - if (m == 60) { - d++; - m = 0; - } - } - - degree = d; - minute = m; - second = s; - sign = si; - - if (decimal != null) { - removeTrailingZero(); - } - } - - public Float toDecimal() { - if (isNull()) { - return null; - } - Integer d = getNotNullDegree(); - Integer m = getNotNullMinute(); - - Integer s = getNotNullSecond(); - - Float result = Float.valueOf(d); - - if (m > 0) { - result += (float) m / 60; - if (s == 0) { - result += 0.5f / 3600; - } - } - if (s > 0) { - result += ((float) s + 0.5f) / 3600; - } - - if (sign) { - result *= -1; - } - return result; - } - - public DmsCoordinate addTrailingZero() { - if (degree == null) { - degree = 0; - } - if (minute == null) { - minute = 0; - } - if (second == null) { - second = 0; - } - return this; - } - - public DmsCoordinate removeTrailingZero() { - if (degree != null && degree == 0) { - degree = null; - } - if (minute != null && minute == 0) { - minute = null; - } - if (second != null && second == 0) { - second = null; - } - return this; - } - - public Integer getSignedDegree() { - Integer result = null; - if (!isDegreeNull()) { - result = degree; - if (isSign()) { - result *= -1; - } - } - return result; - } - - public int getNotNullDegree() { - return isDegreeNull() ? 0 : degree; - } - - public int getNotNullMinute() { - return isMinuteNull() ? 0 : minute; - } - - - public int getNotNullSecond() { - return isSecondNull() ? 0 : second; - } - - public boolean isLatitudeDegreeValid() { - return isDegreeValid(false); - } - - public boolean isLongitudeDegreeValid() { - return isDegreeValid(true); - } - - public boolean isMinuteValid() { - boolean result = true; - if (!isMinuteNull()) { - if (60 == minute) { - - // check minute and second are null - result = isSecondNull(); - } else { - result = 0 <= minute && minute < 60; - } - } - return result; - } - - public boolean isSecondValid() { - return isSecondNull() || (0 <= second && second < 60); - } - - @Override - public String toString() { - return "DmsCoordinateComponent{" + - "sign=" + sign + - ", degree=" + degree + - ", minute=" + minute + - ", second=" + second + - '}'; - } - - protected boolean isDegreeValid(boolean longitude) { - boolean result = true; - if (!isDegreeNull()) { - int bound = longitude ? 180 : 90; - if (bound == degree) { - - // check minute and second are null - result = isMinuteNull() && isSecondNull(); - } else { - result = degree < bound; - } - } - return result; - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateConverter.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateConverter.java deleted file mode 100644 index 1b6814a..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateConverter.java +++ /dev/null @@ -1,144 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.beanutils.ConversionException; -import org.apache.commons.lang3.StringUtils; -import org.nuiton.converter.NuitonConverter; - -import java.util.regex.Matcher; - -import static org.nuiton.i18n.I18n.t; - -/** - * Created on 11/25/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class DmsCoordinateConverter implements NuitonConverter<DmsCoordinate> { - - protected boolean useSign; - - protected boolean forLongitude; - - public void setUseSign(boolean useSign) { - this.useSign = useSign; - } - - public void setForLongitude(boolean forLongitude) { - this.forLongitude = forLongitude; - } - - @Override - public <T> T convert(Class<T> aClass, Object value) { - - if (!isEnabled(aClass)) { - throw new ConversionException( - t("jaxx.error.no.convertor.coordinateDms", value)); - } - - Object result = null; - - if (value == null) { - - if (aClass.equals(String.class)) { - - result = String.format( - DmsCoordinate.COORDINATE_STRING_PATTERN, - useSign ? "-" : "", - StringUtils.leftPad("", forLongitude ? 3 : 2, ' '), - StringUtils.leftPad("", 2, ' '), - StringUtils.leftPad("", 2, ' ')); - } - } else { - - if (aClass.equals(value.getClass())) { - - // same class, no convertion to do - result = value; - } else if (value instanceof String) { - - // String to Value - - Matcher matcher = DmsCoordinate.COORDINATE_PATTERN.matcher((String) value); - - if (matcher.matches()) { - - String degresStr = matcher.group(1).replaceAll("\\s", ""); - String minutesStr = matcher.group(2).replaceAll("\\s", ""); - String secondsStr = matcher.group(3).replaceAll("\\s", ""); - - Integer degre = degresStr.isEmpty() || "-".equals(degresStr) ? null : Math.abs(Integer.valueOf(degresStr)); - Integer minutes = minutesStr.isEmpty() ? null : Integer.valueOf(minutesStr); - Integer seconds = secondsStr.isEmpty() ? null : Integer.valueOf(secondsStr); - - boolean signed = degresStr.contains("-"); - result = DmsCoordinate.valueOf(signed, - degre, - minutes, - seconds); - } - - } else if (value instanceof DmsCoordinate) { - - // Value to String - - DmsCoordinate coordinate = (DmsCoordinate) value; - - boolean sign = coordinate.isSign(); - String signStr = sign ? "-" : ""; - - Integer degree = coordinate.getDegree(); - String degreeStr = degree == null ? "" : degree.toString(); - - Integer minute = coordinate.getMinute(); - String minuteStr = minute == null ? "" : minute.toString(); - - Integer second = coordinate.getSecond(); - String secondStr = second == null ? "" : second.toString(); - - result = String.format( - DmsCoordinate.COORDINATE_STRING_PATTERN, - signStr, - StringUtils.leftPad(degreeStr, forLongitude ? 3 : 2, ' '), - StringUtils.leftPad(minuteStr, 2, ' '), - StringUtils.leftPad(secondStr, 2, ' ')); - } - } - return aClass.cast(result); - - } - - protected boolean isEnabled(Class<?> aClass) { - return String.class.isAssignableFrom(aClass) || - DmsCoordinate.class.isAssignableFrom(aClass); - } - - @Override - public Class<DmsCoordinate> getType() { - return DmsCoordinate.class; - } - -} - diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorHandler.java deleted file mode 100644 index 60a8714..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorHandler.java +++ /dev/null @@ -1,317 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import com.google.common.base.Preconditions; -import jaxx.runtime.spi.UIHandler; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.util.beans.BeanUtil; - -import javax.swing.JFormattedTextField; -import javax.swing.text.DefaultFormatterFactory; -import java.awt.event.KeyEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.lang.reflect.Method; -import java.text.ParseException; - -/** - * Created on 10/16/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class DmsCoordinateEditorHandler implements UIHandler<DmsCoordinateEditor>{ - - /** Logger. */ - private static final Log log = - LogFactory.getLog(DmsCoordinateEditorHandler.class); - - protected DmsCoordinateEditor ui; - - protected Method signMutator; - - protected Method degreMutator; - - protected Method minuteMutator; - - protected Method secondMutator; - - protected boolean valueIsAdjusting; - - protected boolean valueModelIsAdjusting; - - protected DmsCoordinateConverter signedConverter; - - protected DmsCoordinateConverter unsignedConverter; - - protected DefaultFormatterFactory signedFormatterFactory; - - protected DefaultFormatterFactory unsignedFormatterFactory; - -// public DmsCoordinateEditorHandler(DmsCoordinateEditor ui) { -// this.ui = ui; -// -// // can't use the one from ConverterUtil since we deal with some internal states -// this.signedConverter = new DmsCoordinateConverter(); -// this.signedConverter.setUseSign(true); -// this.unsignedConverter = new DmsCoordinateConverter(); -// } - - @Override - public void beforeInit(DmsCoordinateEditor ui) { - this.ui=ui; - // can't use the one from ConverterUtil since we deal with some internal states - this.signedConverter = new DmsCoordinateConverter(); - this.signedConverter.setUseSign(true); - this.unsignedConverter = new DmsCoordinateConverter(); - } - - @Override - public void afterInit(DmsCoordinateEditor ui) { - // nothing special to do here - } - - public void init(boolean longitudeEditor) { - - final DmsCoordinateEditorModel model = ui.getModel(); - - Preconditions.checkNotNull(model.getBean(), "could not find bean in " + ui); - Preconditions.checkNotNull(model.getPropertySign(), "could not find propertySign in " + ui); - Preconditions.checkNotNull(model.getPropertyDegree(), "could not find propertyDegree in " + ui); - Preconditions.checkNotNull(model.getPropertyMinute(), "could not find propertyMinute in " + ui); - Preconditions.checkNotNull(model.getPropertySecond(), "could not find propertySecond in " + ui); - - Object bean = model.getBean(); - signMutator = BeanUtil.getMutator(bean, model.getPropertySign()); - Preconditions.checkNotNull(signMutator, "could not find mutator for " + model.getPropertySign()); - - degreMutator = BeanUtil.getMutator(bean, model.getPropertyDegree()); - Preconditions.checkNotNull(degreMutator, "could not find mutator for " + model.getPropertyDegree()); - - minuteMutator = BeanUtil.getMutator(bean, model.getPropertyMinute()); - Preconditions.checkNotNull(minuteMutator, "could not find mutator for " + model.getPropertyMinute()); - - secondMutator = BeanUtil.getMutator(bean, model.getPropertySecond()); - Preconditions.checkNotNull(secondMutator, "could not find mutator for " + model.getPropertySecond()); - - signedConverter.setForLongitude(longitudeEditor); - unsignedConverter.setForLongitude(longitudeEditor); - - { - // prepare unsigned formatter factory - String pattern = getMaskFormatterPattern(longitudeEditor, false); - MaskFormatterFromConverter<DmsCoordinate> maskFormatter; - try { - maskFormatter = MaskFormatterFromConverter.newFormatter( - DmsCoordinate.class, - pattern, unsignedConverter); - maskFormatter.setValidCharacters(" 01234567890"); - maskFormatter.setCommitsOnValidEdit(true); - unsignedFormatterFactory = new DefaultFormatterFactory(maskFormatter); - } catch (ParseException e) { - // can't happen here - throw new RuntimeException(e); - } - } - { - // prepare signed formatter factory - String pattern = getMaskFormatterPattern(longitudeEditor, true); - MaskFormatterFromConverter<DmsCoordinate> maskFormatter; - try { - maskFormatter = MaskFormatterFromConverter.newFormatter( - DmsCoordinate.class, - pattern, signedConverter); - maskFormatter.setValidCharacters(" 01234567890"); - maskFormatter.setCommitsOnValidEdit(true); - signedFormatterFactory = new DefaultFormatterFactory(maskFormatter); - } catch (ParseException e) { - // can't happen here - throw new RuntimeException(e); - } - } - - JFormattedTextField editor = ui.getEditor(); - editor.setFormatterFactory(model.isSign() ? - signedFormatterFactory : - unsignedFormatterFactory); - editor.setFocusLostBehavior(JFormattedTextField.COMMIT); - - // When editor changes his value, propagate it to model - editor.addPropertyChangeListener("value", new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - DmsCoordinate newValue = (DmsCoordinate) evt.getNewValue(); - if (log.isDebugEnabled()) { - log.debug("Value has changed: " + newValue); - } - model.setValue(newValue); - } - }); - - // When model sign changed, let's push it back in bean - model.addPropertyChangeListener( - DmsCoordinateEditorModel.PROPERTY_SIGN, - new ModelPropertyChangeListener(model, signMutator)); - - // When model degre changed, let's push it back in bean - model.addPropertyChangeListener( - DmsCoordinateEditorModel.PROPERTY_DEGREE, - new ModelPropertyChangeListener(model, degreMutator)); - - // When model minute changed, let's push it back in bean - model.addPropertyChangeListener( - DmsCoordinateEditorModel.PROPERTY_MINUTE, - new ModelPropertyChangeListener(model, minuteMutator)); - - // When model second changed, let's push it back in bean - model.addPropertyChangeListener( - DmsCoordinateEditorModel.PROPERTY_SECOND, - new ModelPropertyChangeListener(model, secondMutator)); - } - - public void setValue(DmsCoordinate value, boolean pushToModel) { - - if (valueModelIsAdjusting) { - // avoid re-entrant code - return; - } - - valueIsAdjusting = !pushToModel; - - try { - ui.getEditor().setValue(value); - } finally { - valueIsAdjusting = false; - } - } - - public void resetEditor() { - - // set null value to model - setValue(null, true); - - // use back unsigned format - ui.getEditor().setFormatterFactory(unsignedFormatterFactory); - } - - public void onKeyReleased(KeyEvent e) { - - JFormattedTextField source = (JFormattedTextField) e.getSource(); - - char keyChar = e.getKeyChar(); - int caretPosition = source.getCaretPosition(); - if (log.isDebugEnabled()) { - log.debug("Key pressed: " + keyChar + " (caret position: " + caretPosition + ")"); - } - - if (keyChar == '-') { - - DmsCoordinate value = (DmsCoordinate) source.getValue(); - - DefaultFormatterFactory newFactory; - - // try to switch unsigned to signed - - boolean useSign = ui.getModel().isSign(); - - if (useSign) { - - if (log.isDebugEnabled()) { - log.debug("Switch to unsigned"); - } - - newFactory = unsignedFormatterFactory; - - // remove a sign - caretPosition--; - } else { - // switch to signed - if (log.isDebugEnabled()) { - log.debug("Switch to signed"); - } - newFactory = signedFormatterFactory; - - // add a sign - caretPosition++; - } - - DmsCoordinate newValue = DmsCoordinate.valueOf(value); - newValue.setSign(!useSign); - - source.setFormatterFactory(newFactory); - source.setValue(newValue); - - e.consume(); - - source.setCaretPosition(caretPosition); - } - } - - protected String getMaskFormatterPattern(boolean longitudeEditor, - boolean useSign) { - String pattern = "**°**''**''''"; - if (longitudeEditor) { - // add one more degre - pattern = "*" + pattern; - } - if (useSign) { - pattern = "-" + pattern; - } - return pattern; - } - - private class ModelPropertyChangeListener implements PropertyChangeListener { - - private final DmsCoordinateEditorModel model; - - private final Method mutator; - - private ModelPropertyChangeListener(DmsCoordinateEditorModel model, Method mutator) { - this.model = model; - this.mutator = mutator; - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (!valueIsAdjusting) { - Object newValue = evt.getNewValue(); - - try { - - valueModelIsAdjusting = true; - try { - mutator.invoke(model.getBean(), newValue); - } finally { - valueModelIsAdjusting = false; - } - - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorModel.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorModel.java deleted file mode 100644 index 058c1a4..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorModel.java +++ /dev/null @@ -1,122 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import java.io.Serializable; - -/** - * Created on 10/16/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class DmsCoordinateEditorModel extends DmsCoordinate { - - public static final String PROPERTY_BEAN = "bean"; - - public static final String PROPERTY_PROPERTY_SIGN = "propertySign"; - - public static final String PROPERTY_PROPERTY_DEGREE = "propertyDegree"; - - public static final String PROPERTY_PROPERTY_MINUTE = "propertyMinute"; - - public static final String PROPERTY_PROPERTY_SECOND = "propertySecond"; - - private static final long serialVersionUID = 1L; - - /** Bean where to push data. */ - protected Serializable bean; - - /** Name of the property of the bean to fire the change of the {@link #sign}. */ - protected String propertySign; - - /** Name of the property of the bean to fire the change of the {@link #degree}. */ - protected String propertyDegree; - - /** Name of the property of the bean to fire the change of the {@link #minute}. */ - protected String propertyMinute; - - /** Name of the property of the bean to fire the change of the {@link #second}. */ - protected String propertySecond; - - public Serializable getBean() { - return bean; - } - - public void setBean(Serializable bean) { - Object oldValue = getBean(); - this.bean = bean; - firePropertyChange(PROPERTY_BEAN, oldValue, bean); - } - - public String getPropertySign() { - return propertySign; - } - - public void setPropertySign(String propertySign) { - Object oldValue = getPropertySign(); - this.propertySign = propertySign; - firePropertyChange(PROPERTY_PROPERTY_SIGN, oldValue, propertySign); - } - - public String getPropertyDegree() { - return propertyDegree; - } - - public void setPropertyDegree(String propertyDegree) { - Object oldValue = getPropertyDegree(); - this.propertyDegree = propertyDegree; - firePropertyChange(PROPERTY_PROPERTY_DEGREE, oldValue, propertyDegree); - } - - public String getPropertyMinute() { - return propertyMinute; - } - - public void setPropertyMinute(String propertyMinute) { - Object oldValue = getPropertyMinute(); - this.propertyMinute = propertyMinute; - firePropertyChange(PROPERTY_PROPERTY_MINUTE, oldValue, propertyMinute); - } - - public String getPropertySecond() { - return propertySecond; - } - - public void setPropertySecond(String propertySecond) { - Object oldValue = getPropertySecond(); - this.propertySecond = propertySecond; - firePropertyChange(PROPERTY_PROPERTY_SECOND, oldValue, propertySecond); - } - - public void setValue(DmsCoordinate value) { - setSign(value != null && value.isSign()); - setDegree(value == null ? null : value.getDegree()); - setMinute(value == null ? null : value.getMinute()); - setSecond(value == null ? null : value.getSecond()); - } - - public String getStringPattern() { - return COORDINATE_STRING_PATTERN; - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/MaskFormatterFromConverter.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/MaskFormatterFromConverter.java deleted file mode 100644 index c00038f..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/MaskFormatterFromConverter.java +++ /dev/null @@ -1,75 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.beanutils.Converter; - -import javax.swing.text.MaskFormatter; -import java.text.ParseException; - -/** - * Created on 11/25/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class MaskFormatterFromConverter<O> extends MaskFormatter { - - private static final long serialVersionUID = 1L; - - private final Converter converter; - - private final Class<O> type; - - public static <O> MaskFormatterFromConverter<O> newFormatter(Class<O> type, - String pattern, - Converter converter) throws ParseException { - return new MaskFormatterFromConverter<O>(type, pattern, converter); - } - - protected MaskFormatterFromConverter(Class<O> type, - String pattern, - Converter converter) throws ParseException { - super(pattern); - this.type = type; - this.converter = converter; - } - - @Override - public String valueToString(Object value) throws ParseException { - return (String) converter.convert(String.class, value); - } - - @Override - public Object stringToValue(String value) throws ParseException { - return converter.convert(type, value); - } - - protected Converter getConverter() { - return converter; - } - - protected Class<O> getType() { - return type; - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/ActionCheckListModel.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/ActionCheckListModel.java deleted file mode 100644 index d04aff3..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/ActionCheckListModel.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ - -package jaxx.runtime.swing.list; - -import org.nuiton.decorator.Decorator; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.swing.event.ListDataEvent; -import javax.swing.event.ListDataListener; - -public class ActionCheckListModel<T> implements CheckListModel<T> { - - protected final List<ListDataListener> listeners = Collections.synchronizedList( new ArrayList<ListDataListener>()); - protected final CheckListModel<T> originalModel; - - protected final CheckListAction<T> actionCheckAll = new CheckListAction.CheckAll<T>(); - - @SuppressWarnings("unchecked") - protected final List<CheckListAction<T>> actionItems = Arrays.asList( actionCheckAll ); - protected final Set<CheckListAction<T>> checks = new HashSet<CheckListAction<T>>(); - - public ActionCheckListModel( final CheckListModel<T> originalModel ) { - - if ( originalModel == null ) throw new NullPointerException(); - this.originalModel = originalModel; - - //react on original model changes - this.originalModel.addListDataListener( new ListDataListener () { - - @Override - public void intervalAdded(ListDataEvent e) { - ListDataEvent event = toDecoratedEvent(e); - for( ListDataListener l: listeners ) { - l.intervalAdded(event); - } - } - - @Override - public void intervalRemoved(ListDataEvent e) { - ListDataEvent event = toDecoratedEvent(e); - for( ListDataListener l: listeners ) { - l.intervalRemoved(event); - } - } - - @Override - public void contentsChanged(ListDataEvent e) { - ListDataEvent event = toDecoratedEvent(e); - for( ListDataListener l: listeners ) { - l.contentsChanged(event); - } - if ( originalModel.getCheckedItems().size() < originalModel.getOriginalSize() ) { - checks.remove(actionCheckAll); - } else { - checks.add(actionCheckAll); - } - fireListDataChanged(); - } - }); - } - - @Override - public int getSize() { - return originalModel.getSize() + actionItems.size(); - } - - @Override - public int getOriginalSize() { - return originalModel.getOriginalSize() + actionItems.size(); - } - - @Override - public Object getElementAt(int index) { - if ( isDecoratedIndex(index)) { - return actionItems.get(index); - } else { - return originalModel.getElementAt( toOriginalIndex(index)); - } - } - - private int toOriginalIndex( int index ) { - return index - actionItems.size(); - } - - private int toDecoratedIndex( int index ) { - return index + actionItems.size(); - } - - private boolean isDecoratedIndex( int index ) { - int size = actionItems.size(); - return size > 0 && index >= 0 && index < size; - } - - - @Override - public void addListDataListener(ListDataListener l) { - listeners.add(l); - } - - @Override - public void removeListDataListener(ListDataListener l) { - listeners.remove(l); - } - - private void fireListDataChanged() { - ListDataEvent e = new ListDataEvent( this, 0, 0, getSize() ); - for( ListDataListener l: listeners ) { - l.contentsChanged(e); - } - } - - private ListDataEvent toDecoratedEvent( ListDataEvent e ) { - return new ListDataEvent( - e.getSource(), - e.getType(), - toDecoratedIndex(e.getIndex0()), - toDecoratedIndex(e.getIndex1())); - } - - @Override - public boolean isCheckedIndex(int index) { - if ( isDecoratedIndex(index)) { - return checks.contains(actionItems.get(index)); - } else { - return originalModel.isCheckedIndex( toOriginalIndex(index)); - } - - } - - @Override - public void setCheckedIndex(int index, boolean value) { - if ( isDecoratedIndex(index)) { - CheckListAction<T> item = actionItems.get(index); - item.check(originalModel, value); - if ( value ) checks.add(item); else checks.remove(item); - fireListDataChanged(); - } else { - originalModel.setCheckedIndex( toOriginalIndex(index), value); - } - } - - @Override - public Collection<T> getCheckedItems() { - return originalModel.getCheckedItems(); - } - - @Override - public void setCheckedItems(Collection<T> items) { - originalModel.setCheckedItems(items); - } - -// @Override -// public void filter(String filter, Decorator<Object> decorator, CheckListFilterType filterType) { -// originalModel.filter(filter, decorator, filterType); -// } - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckList.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckList.java deleted file mode 100644 index 7c33299..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckList.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - * - */ - -package jaxx.runtime.swing.list; - -import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseListener; -import java.util.Collection; - -import javax.swing.AbstractAction; -import javax.swing.JList; -import javax.swing.KeyStroke; -import javax.swing.ListSelectionModel; - -/** - * The decorator for JList which makes it work like check list - * UI can be designed using JList and which can be later decorated to become a check list - * @author Eugene Ryzhikov - * @author Kevin Morin - * - * @param <T> list item type - */ -public class CheckList<T> { - - private final JList list; - private static final MouseAdapter checkBoxEditor = new CheckListEditor(); - - /** - * Wraps the standard JList and makes it work like check list - */ - public CheckList() { - - this.list = new JList(); - this.list.getSelectionModel().setSelectionMode( ListSelectionModel.SINGLE_SELECTION); - - if ( !isEditorAttached() ) list.addMouseListener(checkBoxEditor); - this.list.setCellRenderer(new CheckListRenderer()); - - setupKeyboardActions(list); - - } - - @SuppressWarnings("serial") - private void setupKeyboardActions(final JList list) { - String actionKey = "toggle-check"; - list.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0), actionKey); - list.getActionMap().put(actionKey, new AbstractAction(){ - - @Override - public void actionPerformed(ActionEvent e) { - toggleIndex(list.getSelectedIndex()); - }}); - } - - private boolean isEditorAttached() { - - for( MouseListener ml: list.getMouseListeners() ) { - if ( ml instanceof CheckListEditor ) return true; - } - return false; - - } - - public JList getList() { - return list; - } - - /** - * Sets data to a check list. Simplification for setting new the model - * @param data - */ - public void setData( Collection<T> data ) { - setModel( new DefaultCheckListModel<T>(data)); - } - - /** - * Sets the model for check list. - * @param model - */ - public void setModel( CheckListModel<T> model ) { - list.setModel(model); - } - - @SuppressWarnings("unchecked") - public CheckListModel<T> getModel() { - return (CheckListModel<T>) list.getModel(); - } - - /** - * Returns a collection of checked items. - * @return collection of checked items. Empty collection if nothing is selected - */ - public Collection<T> getCheckedItems() { - return getModel().getCheckedItems(); - } - - /** - * Resets checked elements - * @param elements - */ - public void setCheckedItems( Collection<T> elements ) { - getModel().setCheckedItems(elements); - } - - public void toggleIndex( int index ) { - if ( index >= 0 && index < list.getModel().getSize()) { - CheckListModel<T> model = getModel(); - model.setCheckedIndex(index, !model.isCheckedIndex(index)); - } - } - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckListAction.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckListAction.java deleted file mode 100644 index 6ecc688..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckListAction.java +++ /dev/null @@ -1,58 +0,0 @@ -package jaxx.runtime.swing.list; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - - -import java.util.ArrayList; -import java.util.Collection; - -import static org.nuiton.i18n.I18n.t; - - -public interface CheckListAction<T> { - - void check( CheckListModel<T> model, boolean value ); - - public static class CheckAll<T> implements CheckListAction<T> { - - @Override - public String toString() { - return "(" + t("jaxx.list.check.all") + ")"; - } - - @SuppressWarnings("unchecked") - @Override - public void check(CheckListModel<T> model, boolean value) { - Collection<T> items = new ArrayList<T>(); - if (value) { - for( int i=0, s=model.getSize(); i<s; i++ ) { - items.add((T) model.getElementAt(i)); - } - } - model.setCheckedItems( items ); - - } - - } - -} \ No newline at end of file diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckListEditor.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckListEditor.java deleted file mode 100644 index c3b7c7e..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckListEditor.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ - -package jaxx.runtime.swing.list; - -import java.awt.Rectangle; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.Arrays; - -import javax.swing.JList; -import javax.swing.SwingUtilities; - - -/** - * Determines mouse click and - * 1. Toggles the check on selected item if clicked once - * 2. Clears checks and checks selected item if clicked more then once - * - * Created on Feb 4, 2011 - * @author Eugene Ryzhikov - * @author Kevin Morin - * - */ -final class CheckListEditor extends MouseAdapter { - @Override - public void mouseClicked(MouseEvent e) { - - if (!SwingUtilities.isLeftMouseButton(e)) return; - - JList list = (JList) e.getSource(); - if ( !list.isEnabled() || (!(list.getModel() instanceof CheckListModel<?>))) return; - - int index = list.locationToIndex(e.getPoint()); - if (index < 0) return; - - Rectangle bounds = list.getCellBounds(index, index); - - if ( bounds.contains(e.getPoint()) ) { - - @SuppressWarnings("unchecked") - CheckListModel<Object> model = (CheckListModel<Object>) list.getModel(); - - if ( e.getClickCount() > 1 ) { - // clear all and check selected for more then 1 clicks - model.setCheckedItems( Arrays.asList( model.getElementAt(index))); - } else { - // simple toggle for 1 click - model.setCheckedIndex(index, !model.isCheckedIndex(index)); - } - e.consume(); - } - - } - -} - diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckListModel.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckListModel.java deleted file mode 100644 index a5acd28..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckListModel.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ - -package jaxx.runtime.swing.list; - -import java.util.Collection; - -import javax.swing.ListModel; - -public interface CheckListModel<T> extends ListModel { - - /** - * Returns the check state of the element at specified position - * @param index element index - * @return true if element at specified position is checked - * @throws IndexOutOfBoundsException if index is out of range - */ - boolean isCheckedIndex(int index); - - /** - * Sets the check state of the element at specified position - * @param index element index - * @param value - * @throws IndexOutOfBoundsException if index is out of range - */ - void setCheckedIndex(int index, boolean value); - - /** - * Returns a collections of checked items - * @return - */ - Collection<T> getCheckedItems(); - - /** - * Sets checked items - * @param items - */ - void setCheckedItems(Collection<T> items); - - /** - * Returns the number of items before the filter was applied - * @return - */ - int getOriginalSize(); - -} \ No newline at end of file diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckListRenderer.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckListRenderer.java deleted file mode 100644 index 5e22844..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/CheckListRenderer.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ - -package jaxx.runtime.swing.list; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Rectangle; -import java.io.Serializable; - -import javax.swing.DefaultListCellRenderer; -import javax.swing.Icon; -import javax.swing.JCheckBox; -import javax.swing.JList; -import javax.swing.ListCellRenderer; -import javax.swing.UIManager; -import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; - -public class CheckListRenderer extends JCheckBox implements ListCellRenderer, Serializable { - - private static final long serialVersionUID = 1L; - - private static final Border NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1); - private static final Border SAFE_NO_FOCUS_BORDER = NO_FOCUS_BORDER; // may change in the feature - - /** - * Constructs a default renderer object for an item in a list. - */ - public CheckListRenderer() { - super(); - setOpaque(true); - setBorder(getNoFocusBorder()); - } - - private static Border getNoFocusBorder() { - if (System.getSecurityManager() != null) { - return SAFE_NO_FOCUS_BORDER; - } else { - return NO_FOCUS_BORDER; - } - } - - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, - boolean cellHasFocus) { - - setComponentOrientation(list.getComponentOrientation()); - - Color bg = null; - Color fg = null; - - JList.DropLocation dropLocation = list.getDropLocation(); - if (dropLocation != null && !dropLocation.isInsert() && dropLocation.getIndex() == index) { - - bg = UIManager.getColor("List.dropCellBackground"); - fg = UIManager.getColor("List.dropCellForeground"); - - isSelected = true; - } - - if (isSelected) { - setBackground(bg == null ? list.getSelectionBackground() : bg); - setForeground(fg == null ? list.getSelectionForeground() : fg); - } else { - setBackground(list.getBackground()); - setForeground(list.getForeground()); - } - - if (value instanceof Icon) { - setIcon((Icon) value); - setText(""); - } else { - setIcon(null); - setText(getObjectAsText(value)); - } - - setSelected( isChecked(list, index)); - - setEnabled(list.isEnabled()); - setFont(list.getFont()); - - Border border = null; - if (cellHasFocus) { - if (isSelected) { - border = UIManager.getBorder("List.focusSelectedCellHighlightBorder"); - } - if (border == null) { - border = UIManager.getBorder("List.focusCellHighlightBorder"); - } - } else { - border = getNoFocusBorder(); - } - setBorder(border); - - return this; - } - - protected String getObjectAsText(Object obj) { - return (obj == null) ? "" : obj.toString(); - } - - private boolean isChecked(JList list, int index) { - - if (list.getModel() instanceof CheckListModel<?>) { - return ((CheckListModel<?>) list.getModel()).isCheckedIndex(index); - } else { - return false; - } - - } - - /** - * @return true if the background is opaque and differs from the JList's background; false otherwise - */ - @Override - public boolean isOpaque() { - Color back = getBackground(); - Component p = getParent(); - if (p != null) { - p = p.getParent(); - } - // p should now be the JList. - boolean colorMatch = (back != null) && (p != null) && back.equals(p.getBackground()) && p.isOpaque(); - return !colorMatch && super.isOpaque(); - } - - @Override - protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { - - if ("text".equals(propertyName) || - (("font".equals(propertyName) || "foreground".equals(propertyName)) && - oldValue != newValue && getClientProperty(javax.swing.plaf.basic.BasicHTML.propertyKey) != null)) { - - super.firePropertyChange(propertyName, oldValue, newValue); - } - } - - // Methods below are overridden for performance reasons. - - @Override - public void validate() { - } - - @Override - public void invalidate() { - } - - @Override - public void repaint() { - } - - @Override - public void revalidate() { - } - - @Override - public void repaint(long tm, int x, int y, int width, int height) { - } - - @Override - public void repaint(Rectangle r) { - } - - @Override - public void firePropertyChange(String propertyName, byte oldValue, byte newValue) { - } - - @Override - public void firePropertyChange(String propertyName, char oldValue, char newValue) { - } - - @Override - public void firePropertyChange(String propertyName, short oldValue, short newValue) { - } - - @Override - public void firePropertyChange(String propertyName, int oldValue, int newValue) { - } - - @Override - public void firePropertyChange(String propertyName, long oldValue, long newValue) { - } - - @Override - public void firePropertyChange(String propertyName, float oldValue, float newValue) { - } - - @Override - public void firePropertyChange(String propertyName, double oldValue, double newValue) { - } - - @Override - public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { - } - - @SuppressWarnings("serial") - public static class UIResource extends DefaultListCellRenderer implements javax.swing.plaf.UIResource { - } - -} \ No newline at end of file diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/DefaultCheckListModel.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/DefaultCheckListModel.java deleted file mode 100644 index a2696e0..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/DefaultCheckListModel.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ - -package jaxx.runtime.swing.list; - -import jaxx.runtime.JAXXUtil; -import org.nuiton.decorator.Decorator; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.swing.AbstractListModel; - -/** - * Default model for check list. It is based on the list of items - * Implementation of checks is based on HashSet of checked items - * - * @author Eugene Ryzhikov - * @author Kevin Morin - * - * @param <T> list element type - */ -public class DefaultCheckListModel<T> extends AbstractListModel implements CheckListModel<T> { - - private static final long serialVersionUID = 1L; - - protected final List<T> data = new ArrayList<T>(); - protected final Set<T> checks = new HashSet<T>(); - - public DefaultCheckListModel( Collection<? extends T> data ) { - - if ( data == null ) return; - for (T object : data) { - this.data.add( object ); - checks.clear(); - } - } - - public DefaultCheckListModel( T... data ) { - this( Arrays.asList( data )); - } - - /* (non-Javadoc) - * @see org.oxbow.swingbits.list.ICheckListModel#getSize() - */ - @Override - public int getSize() { - return data().size(); - } - - @Override - public int getOriginalSize() { - return data.size(); - } - - protected List<T> data() { - return data; - } - - - /* (non-Javadoc) - * @see org.oxbow.swingbits.list.ICheckListModel#getElementAt(int) - */ - @Override - public Object getElementAt(int index) { - return data().get(index); - } - - /* (non-Javadoc) - * @see org.oxbow.swingbits.list.ICheckListModel#isChecked(int) - */ - @Override - public boolean isCheckedIndex( int index ) { - return checks.contains( data().get(index)); - } - - /* (non-Javadoc) - * @see org.oxbow.swingbits.list.ICheckListModel#setChecked(int, boolean) - */ - @Override - public void setCheckedIndex( int index, boolean value ) { - T o = data().get(index); - if ( value ) checks.add(o); else checks.remove(o); - fireContentsChanged(this, index, index); - } - - /* (non-Javadoc) - * @see org.oxbow.swingbits.list.ICheckListModel#getChecked() - */ - @Override - public Collection<T> getCheckedItems() { - List<T> items = new ArrayList<T>(checks); - items.retainAll(data); - return Collections.unmodifiableList( items ); - } - - /* (non-Javadoc) - * @see org.oxbow.swingbits.list.ICheckListModel#setChecked(java.util.Collection) - */ - @Override - public void setCheckedItems( Collection<T> items ) { - - List<T> correctedItems = new ArrayList<T>(items); - correctedItems.retainAll(data); - - checks.clear(); - checks.addAll( correctedItems ); - fireContentsChanged(this, 0, checks.size()-1); - } - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/CheckListFilterType.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/CheckListFilterType.java deleted file mode 100644 index 4394b2f..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/CheckListFilterType.java +++ /dev/null @@ -1,54 +0,0 @@ -package jaxx.runtime.swing.list.filter; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - - -public enum CheckListFilterType { - - STARTS_WITH { - - @Override - public boolean include( String element, String filter ) { - - if ( element == null || filter == null ) return false; - return element.startsWith(filter); - - } - - }, - - CONTAINS { - - @Override - public boolean include( String element, String filter ) { - - if ( element == null || filter == null ) return false; - return element.toLowerCase().contains(filter.toLowerCase()); - - } - - }; - - public abstract boolean include( String element, String filter ); - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/DefaultFilterableCheckListModel.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/DefaultFilterableCheckListModel.java deleted file mode 100644 index cf42ba0..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/DefaultFilterableCheckListModel.java +++ /dev/null @@ -1,84 +0,0 @@ -package jaxx.runtime.swing.list.filter; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.swing.list.DefaultCheckListModel; -import org.nuiton.decorator.Decorator; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -/** - * @author Kevin Morin (Code Lutin) - * @since 2.13 - */ -public class DefaultFilterableCheckListModel<T> extends DefaultCheckListModel<T> implements FilterableCheckListModel<T> { - - private List<T> filteredData = null; - - public DefaultFilterableCheckListModel(Collection<? extends T> data) { - super(data); - } - - public DefaultFilterableCheckListModel(T... data) { - super(Arrays.asList(data)); - } - - protected List<T> data() { - return filteredData == null ? data: filteredData; - } - - @Override - public void filter(String filter, Decorator<Object> decorator, CheckListFilterType filterType) { - - if ( filter == null || filter.trim().length() == 0 ) { - filteredData = null; - } else { - - CheckListFilterType ft = filterType == null? CheckListFilterType.CONTAINS: filterType; - - String f = filter.toLowerCase(); - - List<T> fData = new ArrayList<T>(); - - for( T o: data ) { - String decorated; - if (o != null && decorator != null) { - decorated = decorator.toString(o); - } else { - decorated = JAXXUtil.getStringValue(o); - } - if ( ft.include(decorated, f)) { - fData.add(o); - } - } - filteredData = fData; - } - - fireContentsChanged( this, 0, data.size()-1); - } - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/FilterableActionCheckListModel.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/FilterableActionCheckListModel.java deleted file mode 100644 index f1897a2..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/FilterableActionCheckListModel.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ - -package jaxx.runtime.swing.list.filter; - -import jaxx.runtime.swing.list.ActionCheckListModel; -import org.nuiton.decorator.Decorator; - -public class FilterableActionCheckListModel<T> extends ActionCheckListModel<T> implements FilterableCheckListModel<T> { - - public FilterableActionCheckListModel(final DefaultFilterableCheckListModel<T> originalModel) { - super(originalModel); - } - - @Override - public void filter(String filter, Decorator<Object> decorator, CheckListFilterType filterType) { - ((DefaultFilterableCheckListModel) originalModel).filter(filter, decorator, filterType); - } - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/FilterableCheckList.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/FilterableCheckList.java deleted file mode 100644 index 32ea503..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/FilterableCheckList.java +++ /dev/null @@ -1,55 +0,0 @@ -package jaxx.runtime.swing.list.filter; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.swing.list.CheckList; -import jaxx.runtime.swing.list.CheckListModel; -import org.nuiton.decorator.Decorator; - -/** - * @author Kevin Morin (Code Lutin) - * @since 2.13 - */ -public class FilterableCheckList<T> extends CheckList<T> { - - /** - * Sets the model for check list. - * @param model - */ - public void setModel( CheckListModel<T> model ) { - getList().setModel(model); - } - - @SuppressWarnings("unchecked") - public FilterableCheckListModel<T> getModel() { - return (FilterableCheckListModel<T>) getList().getModel(); - } - - /** - * Filters list view without losing actual data - * @param filter - */ - public void filter( String filter, Decorator<Object> decorator, CheckListFilterType filterType ) { - getModel().filter(filter, decorator, filterType); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/FilterableCheckListModel.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/FilterableCheckListModel.java deleted file mode 100644 index 481e74b..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/list/filter/FilterableCheckListModel.java +++ /dev/null @@ -1,40 +0,0 @@ -package jaxx.runtime.swing.list.filter; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 CodeLutin - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.swing.list.CheckListModel; -import org.nuiton.decorator.Decorator; - -/** - * @author Kevin Morin (Code Lutin) - * @since 2.13 - */ -public interface FilterableCheckListModel<T> extends CheckListModel<T> { - - /** - * Filters list view without losing actual data - * @param filter - */ - void filter( String filter, Decorator<Object> decorator, CheckListFilterType filterType ); - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jAppender.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jAppender.java deleted file mode 100644 index ddffed6..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jAppender.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.log; - -import org.apache.log4j.Level; -import org.apache.log4j.WriterAppender; -import org.apache.log4j.spi.LoggingEvent; - -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.util.LinkedList; -import java.util.List; - -/** - * @author Sylvain Lletellier - */ -public class JAXXLog4jAppender extends WriterAppender { - - public static final String PROPERTY_LOGS = "logs"; - public static final String PROPERTY_LEVEL = "level"; - - protected List<LoggingEvent> events; - protected StringBuilder logs; - protected Level level; - - protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this); - - public JAXXLog4jAppender() { - events = new LinkedList<LoggingEvent>(); - logs = new StringBuilder(); - } - - public String getLogs() { - return logs.toString(); - } - - public void setLogs(String logs) { - String oldValue = getLogs(); - this.logs = new StringBuilder(logs); - firePropertyChange(PROPERTY_LOGS, oldValue, logs); - } - - public Level getLevel() { - if (level == null) { - level = Level.ALL; - } - return level; - } - - public void setLevel(Level level) { - Level oldValue = getLevel(); - this.level = level; - firePropertyChange(PROPERTY_LEVEL, oldValue, level); - updateLogs(); - } - - @Override - public void append(LoggingEvent event) { - super.append(event); - if (event != null) { - events.add(event); - updateLog(event); - } - } - - protected void updateLogs() { - String oldValue = getLogs(); - logs = new StringBuilder(); - for (LoggingEvent event : events) { - updateLog(event); - } - firePropertyChange(PROPERTY_LOGS, oldValue, getLogs()); - } - - protected void updateLog(LoggingEvent event) { - Level level = event.getLevel(); - if (getLevel() != null && level.isGreaterOrEqual(getLevel())) { - String log = this.layout.format(event); - appendLog(log); - if(layout.ignoresThrowable()) { - String[] errorLogs = event.getThrowableStrRep(); - if (errorLogs != null) { - for (String errorLog : errorLogs) { - appendLog(errorLog + "\n"); - } - } - } - } - } - - protected void appendLog(String log) { - String oldValue = getLogs(); - logs.append(log); - firePropertyChange(PROPERTY_LOGS, oldValue, getLogs()); - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - pcs.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { - pcs.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - pcs.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { - pcs.removePropertyChangeListener(propertyName, listener); - } - - protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { - pcs.firePropertyChange(propertyName, oldValue, newValue); - } - - protected void firePropertyChange(String propertyName, Object newValue) { - firePropertyChange(propertyName, null, newValue); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jHandler.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jHandler.java deleted file mode 100644 index c61492c..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jHandler.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.log; - -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.SwingUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.apache.log4j.PatternLayout; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JRootPane; -import javax.swing.KeyStroke; -import java.awt.Component; -import java.awt.Frame; -import java.awt.event.ActionEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -/** - * @author Sylvain Lletellier - */ -public class JAXXLog4jHandler { - - private static final Log log = LogFactory.getLog(JAXXLog4jHandler.class); - - protected JAXXLog4jUI ui; - - protected static JAXXLog4jAppender appender; - - public JAXXLog4jHandler(JAXXLog4jUI ui) { - this.ui = ui; - } - - /** - * Init {@link JAXXLog4jAppender} with level INFO and pattern : %5p [%t] (%F:%L) %M - %m%n - */ - public static void init() { - init("INFO", "%5p [%t] (%F:%L) %M - %m%n"); - } - - /** - * Init {@link JAXXLog4jAppender} with specific {@link Level} and {@link PatternLayout} - * - * @param level specify log4j {@link Level} - * @param patternLayout log4j {@link PatternLayout} to display - */ - public static void init(String level, String patternLayout) { - Logger logger = Logger.getRootLogger(); - - if (appender == null) { - appender = new JAXXLog4jAppender(); - logger.addAppender(appender); - } - appender.setLevel(Level.toLevel(level)); - appender.setLayout(new PatternLayout(patternLayout)); - } - - final protected Action closeAction = new AbstractAction("close") { - private static final long serialVersionUID = 1L; - - @Override - public void actionPerformed(ActionEvent e) { - JDialog container = ui.getParentContainer(JDialog.class); - if (container != null) { - container.dispose(); - } else { - ui.setVisible(false); - } - } - }; - - public JAXXLog4jAppender getAppender() { - return appender; - } - - public void showInDialog(Frame ui, boolean undecorated) { - JDialog f = new JDialog(ui, this.ui.getTitle(), false); - f.add(this.ui); - f.setResizable(true); - f.setSize(550, 450); - f.setUndecorated(undecorated); - JRootPane rootPane = f.getRootPane(); - rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ESCAPE"), "close"); - rootPane.getActionMap().put("close", closeAction); - f.addWindowListener(new WindowAdapter() { - @Override - public void windowClosed(WindowEvent e) { - Component ui = (Component) e.getSource(); - if (log.isInfoEnabled()) { - log.info("destroy ui " + ui); - } - JAXXUtil.destroy(ui); - JAXXUtil.destroy(JAXXLog4jHandler.this.ui); - } - }); - SwingUtil.center(ui, f); - f.setVisible(true); - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/renderer/DateCellRenderer.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/renderer/DateCellRenderer.java deleted file mode 100644 index 1bb370d..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/renderer/DateCellRenderer.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package jaxx.runtime.swing.renderer; - -import java.awt.Component; -import java.text.SimpleDateFormat; -import java.util.Date; -import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.table.TableCellRenderer; -import org.apache.commons.lang3.StringUtils; - -/** - * @author Sylvain Lletellier - */ -public class DateCellRenderer implements TableCellRenderer { - - protected TableCellRenderer delegate; - protected SimpleDateFormat dateFormat; - - public DateCellRenderer(TableCellRenderer renderer, String datePattern) { - this.delegate = renderer; - dateFormat = new SimpleDateFormat(); - if (datePattern != null) { - dateFormat.applyPattern(datePattern); - } - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - JLabel render = (JLabel) delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - Date date = (Date) value; - String formatedDate = StringUtils.EMPTY; - if (date != null) { - formatedDate = dateFormat.format(date); - } - render.setText(formatedDate); - return render; - - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/session/BeanDoubleListState.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/session/BeanDoubleListState.java deleted file mode 100644 index eb5354b..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/session/BeanDoubleListState.java +++ /dev/null @@ -1,90 +0,0 @@ -package jaxx.runtime.swing.session; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.swing.editor.bean.BeanDoubleList; -import jaxx.runtime.swing.editor.bean.BeanFilterableComboBox; - -/** - * @author Kevin Morin - morin@codelutin.com - * @since 2.5.21 - */ -public class BeanDoubleListState implements State { - - protected int index = 0; - - protected boolean reverseSort = false; - - public BeanDoubleListState() { - } - - public BeanDoubleListState(int index, boolean reverseSort) { - this.index = index; - this.reverseSort = reverseSort; - } - - public int getIndex() { - return index; - } - - public void setIndex(int index) { - this.index = index; - } - - public boolean isReverseSort() { - return reverseSort; - } - - public void setReverseSort(boolean reverseSort) { - this.reverseSort = reverseSort; - } - - protected BeanDoubleList checkComponent(Object o) { - if (o == null) { - throw new IllegalArgumentException("null component"); - } - if (!(o instanceof BeanDoubleList)) { - throw new IllegalArgumentException("invalid component"); - } - return (BeanDoubleList) o; - } - - @Override - public State getState(Object o) { - BeanDoubleList list = checkComponent(o); - return new BeanDoubleListState(list.getIndex(), list.isReverseSort()); - } - - @Override - public void setState(Object o, State state) { - if (!(state instanceof BeanDoubleListState)) { - throw new IllegalArgumentException("invalid state"); - } - BeanDoubleList list = checkComponent(o); - BeanDoubleListState beanDoubleListState = (BeanDoubleListState) state; - list.setIndex(beanDoubleListState.getIndex()); - list.setReverseSort(beanDoubleListState.isReverseSort()); - } - - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/session/BeanFilterableComboBoxState.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/session/BeanFilterableComboBoxState.java deleted file mode 100644 index e1e27be..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/session/BeanFilterableComboBoxState.java +++ /dev/null @@ -1,89 +0,0 @@ -package jaxx.runtime.swing.session; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import jaxx.runtime.swing.editor.bean.BeanFilterableComboBox; - -/** - * @author Kevin Morin - morin@codelutin.com - * @since 2.5.20 - */ -public class BeanFilterableComboBoxState implements State { - - protected int index = 0; - - protected boolean reverseSort = false; - - public BeanFilterableComboBoxState() { - } - - public BeanFilterableComboBoxState(int index, boolean reverseSort) { - this.index = index; - this.reverseSort = reverseSort; - } - - public int getIndex() { - return index; - } - - public void setIndex(int index) { - this.index = index; - } - - public boolean isReverseSort() { - return reverseSort; - } - - public void setReverseSort(boolean reverseSort) { - this.reverseSort = reverseSort; - } - - protected BeanFilterableComboBox checkComponent(Object o) { - if (o == null) { - throw new IllegalArgumentException("null component"); - } - if (!(o instanceof BeanFilterableComboBox)) { - throw new IllegalArgumentException("invalid component"); - } - return (BeanFilterableComboBox) o; - } - - @Override - public State getState(Object o) { - BeanFilterableComboBox combo = checkComponent(o); - return new BeanFilterableComboBoxState(combo.getIndex(), combo.isReverseSort()); - } - - @Override - public void setState(Object o, State state) { - if (!(state instanceof BeanFilterableComboBoxState)) { - throw new IllegalArgumentException("invalid state"); - } - BeanFilterableComboBox combo = checkComponent(o); - BeanFilterableComboBoxState bfcbState = (BeanFilterableComboBoxState) state; - combo.setIndex(bfcbState.getIndex()); - combo.setReverseSort(bfcbState.isReverseSort()); - } - - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/AbstractTableFilter.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/AbstractTableFilter.java deleted file mode 100644 index 918c2fd..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/AbstractTableFilter.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ - -package jaxx.runtime.swing.table.filter; - -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.ComparatorUtils; -import org.apache.commons.collections4.Transformer; -import org.apache.commons.lang3.ObjectUtils; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.swing.JTable; - -/** - * Partial implementation of table filter - * - * Created on Feb 10, 2011 - * @author Eugene Ryzhikov - * @author Kevin Morin - * - * @param <T> - */ -@SuppressWarnings("serial") -public abstract class AbstractTableFilter<T extends JTable> implements TableFilter<T> { - - private final Set<FilterChangeListener> listeners = Collections.synchronizedSet( new HashSet<FilterChangeListener>()); - - private final T table; - private final TableFilterState filterState = new TableFilterState(); - private Map<Integer, Integer> columnDistnctIntemNumbers = new HashMap<Integer, Integer>(); - - public AbstractTableFilter( T table ) { - this.table = table; - } - - @Override - public T getTable() { - return table; - } - - protected abstract boolean execute(int col, Collection<Object> items); - - @Override - public boolean apply(int col, Collection<Object> items) { - setFilterState(col, items); - boolean result; - if ( result = execute( col, items ) ) fireFilterChange(); - return result; - } - - @Override - public final void addChangeListener( FilterChangeListener listener ) { - if ( listener != null ) listeners.add(listener); - } - - @Override - public final void removeChangeListener( FilterChangeListener listener ) { - if ( listener != null ) listeners.remove(listener); - } - - public final void fireFilterChange() { - for( FilterChangeListener l: listeners ) { - l.filterChanged(AbstractTableFilter.this); - } - } - - @Override - public Collection<Object> getDistinctColumnItems( int column ) { - Collection<Object> result = collectDistinctColumnItems( column ); - columnDistnctIntemNumbers.put(column, result != null ? result.size() : 0); - return result; - - } - - private Collection<Object> collectDistinctColumnItems( final int column ) { -// Set<Object> set = new HashSet<Object>(); // to collect unique items -// int nullIndex = -1; -// for( int row=0; row<table.getModel().getRowCount(); row++) { -// Object value = table.getModel().getValueAt( row, column); -// // adding null to TreeSet will produce NPE, just remember we had it -// if ( value == null ) { -// nullIndex = row; -// } else { -// set.add( new DistinctColumnItem(value, row )); -// } -// } - Set<Object> set = distinctValuesForColumn(column); - List<Object> result = null; - if (set != null) { - result = new ArrayList<Object>(set); - // if ( nullIndex >= 0 ) result.add(0, null); // add null to resulting collection if we had it - - Collections.sort(result, new Comparator<Object>() { - @Override - public int compare(Object o1, Object o2) { - return ComparatorUtils.transformedComparator(ComparatorUtils.NATURAL_COMPARATOR, - new Transformer<Object, Comparable>() { - @Override - public Comparable transform(Object input) { - return AbstractTableFilter.this.toString(input); - } - }).compare(o1, o2); - } - }); - - } - return result; - } - - @Override - public Collection<Object> getFilterState( int column ) { - return filterState.getValues(column); - } - - @Override - public boolean isFiltered( int column ) { - Collection<Object> checks = getFilterState( column ); - return CollectionUtils.isNotEmpty(checks) && !ObjectUtils.equals(columnDistnctIntemNumbers.get(column), checks.size()); - } - - @Override - public boolean includeRow( TableFilter.Row row ) { - return filterState.include(row); - } - - public void setFilterState(int column, Collection<Object> values ) { - filterState.setValues(column, values); - } - - public void clear() { - filterState.clear(); - fireFilterChange(); - } - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/FilterChangeListener.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/FilterChangeListener.java deleted file mode 100644 index c676d17..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/FilterChangeListener.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ - -package jaxx.runtime.swing.table.filter; - -public interface FilterChangeListener { - - void filterChanged( TableFilter<?> filter ); -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/FilterTableHeaderRenderer.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/FilterTableHeaderRenderer.java deleted file mode 100644 index 1f95aea..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/FilterTableHeaderRenderer.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ - -package jaxx.runtime.swing.table.filter; - -import jaxx.runtime.swing.CompoundIcon; -import jaxx.runtime.swing.JAXXWidgetUtil; - -import java.awt.Component; -import java.awt.Image; - -import javax.swing.*; -import javax.swing.table.TableCellRenderer; - -/** - * Table header renderer to show the column filter state - * - * Created on Feb 10, 2011 - * @author Eugene Ryzhikov - * @author Kevin Morin - * - */ -class FilterTableHeaderRenderer extends JComponent implements TableCellRenderer { - - private static final long serialVersionUID = 1L; - - private ImageIcon icon; - private final TableFilter<?> tableFilter; - private boolean rendererInit = true; - private int originalHorizontalTextPosition; - - public FilterTableHeaderRenderer( TableFilter<?> tableFilter ) { - this.tableFilter = tableFilter; - } - - private Icon getFilterIcon() { - - if (icon == null) { - icon = JAXXWidgetUtil.createImageIcon("funnel.png"); - icon = new ImageIcon( icon.getImage().getScaledInstance( 12, 12, Image.SCALE_SMOOTH )); - } - return icon; - - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, - boolean hasFocus, int row, int column) { - - final JLabel label = (JLabel) table.getTableHeader().getDefaultRenderer() - .getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - if ( rendererInit ) { - originalHorizontalTextPosition = label.getHorizontalTextPosition(); - rendererInit = false; - } - - int modelColumn = table.convertColumnIndexToModel(column); - if ( tableFilter.isFiltered(modelColumn) ) { - - Icon originalIcon = label.getIcon(); - if ( originalIcon == null ) { - label.setIcon( getFilterIcon() ); - } else { - label.setIcon( new CompoundIcon( getFilterIcon(), originalIcon ) ); - } - label.setHorizontalTextPosition( JLabel.TRAILING ); - - } else { - label.setHorizontalTextPosition( originalHorizontalTextPosition ); - } - - return label; - } - - // following methods are overriden for performance reasons - - @Override - public void validate() {} - - @Override - public void revalidate() {} - - @Override - public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {} - - @Override - public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {} - -} \ No newline at end of file diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/JTableFilter.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/JTableFilter.java deleted file mode 100644 index 42d3bf2..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/JTableFilter.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ - -package jaxx.runtime.swing.table.filter; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Collections; -import java.util.Set; - -import javax.swing.DefaultRowSorter; -import javax.swing.JTable; -import javax.swing.RowFilter; -import javax.swing.RowSorter; -import javax.swing.table.TableModel; -import javax.swing.table.TableRowSorter; - -public class JTableFilter extends AbstractTableFilter<JTable> { - - private static final long serialVersionUID = 1L; - - private final TableRowFilter filter = new TableRowFilter(); - - public JTableFilter( JTable table) { - super(table); - } - - @Override - protected boolean execute(int col, Collection<Object> items) { - - RowSorter<?> rs = getTable().getRowSorter(); - - if (!( rs instanceof DefaultRowSorter )) return false; - - DefaultRowSorter<?, ?> drs = (DefaultRowSorter<?, ?>) rs; - - @SuppressWarnings("unchecked") - RowFilter<Object,Object> prevFilter = (RowFilter<Object, Object>) drs.getRowFilter(); - if ( !(prevFilter instanceof TableRowFilter)) { - filter.setParentFilter(prevFilter); - } - - drs.setRowFilter(filter); - return true; - - } - - class TableRowFilter extends RowFilter<Object,Object> implements Serializable { - - private static final long serialVersionUID = 1L; - - private RowFilter<Object, Object> parentFilter; - - public RowFilter<Object, Object> getParentFilter() { - return parentFilter; - } - - public void setParentFilter( RowFilter<Object, Object> parentFilter ) { - this.parentFilter = (parentFilter == null || parentFilter == this )? null: parentFilter; - } - - @Override - public boolean include( final RowFilter.Entry<? extends Object, ? extends Object> entry) { - - // use parent filter condition - if ( parentFilter != null && !parentFilter.include(entry)) return false; - - return includeRow( new TableFilter.Row() { - - @Override - public Object getValue(int column) { return entry.getValue(column); } - - @Override - public int getValueCount() { return entry.getValueCount(); } - - }); - - } - - } - - public void modelChanged( TableModel model ) { - getTable().setRowSorter( new TableRowSorter<TableModel>( model )); - } - - @Override - public Set<Object> distinctValuesForColumn(int i) { - //TODO - return null; - } - - @Override - public String toString(Object o) { - //TODO - return null; - } - - public void clear() { - super.clear(); - Collection<Object> items = Collections.emptyList(); - for( int column=0; column<getTable().getModel().getColumnCount(); column++) { - execute(column, items); - } - } -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableAwareCheckListRenderer.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableAwareCheckListRenderer.java deleted file mode 100644 index 1a9dc13..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableAwareCheckListRenderer.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ -package jaxx.runtime.swing.table.filter; - -import jaxx.runtime.JAXXUtil; -import jaxx.runtime.swing.list.CheckListAction; -import jaxx.runtime.swing.list.CheckListRenderer; -import org.nuiton.decorator.Decorator; - -import java.awt.Component; - -import javax.swing.JList; - -@SuppressWarnings("serial") -public class TableAwareCheckListRenderer extends CheckListRenderer { - - private final Decorator<Object> decorator; - - public TableAwareCheckListRenderer(Decorator<Object> decorator ) { - this.decorator = decorator; - } - - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - - super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - String text; - if (value != null && decorator != null) { - text = decorator.toString(value); - } else { - text = JAXXUtil.getStringValue(value); - } - setText(text); - return this; - - } - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableFilter.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableFilter.java deleted file mode 100644 index d3de44d..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableFilter.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ - - -package jaxx.runtime.swing.table.filter; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Set; - -import javax.swing.JTable; -import javax.swing.table.TableModel; - -public interface TableFilter<T extends JTable> extends Serializable { - - /** - * The table under filter - * @return - */ - T getTable(); - - /** - * - * @param column model column index - * @return - */ - Collection<Object> getDistinctColumnItems( int column ); - - /** - * - * @param column model column index - * @return - */ - Collection<Object> getFilterState( int column ); - - /** - * Checks if column is filtered - * @param column model column index - * @return true if column is filtered - */ - boolean isFiltered( int column ); - - boolean includeRow( Row entry ); - - /** - * Apply filter for specified column based on collection of distinct items - * @param col - * @param items - * @return - */ - boolean apply( int col, Collection<Object> items ); - - public interface Row { - int getValueCount(); - Object getValue( int column ); - } - - void addChangeListener( FilterChangeListener listener ); - void removeChangeListener( FilterChangeListener listener ); - - /** - * Clear the filter - */ - void clear(); - - /** - * Describes what filter has to do when table model changes - * @param model - */ - void modelChanged( TableModel model ); - - Set<Object> distinctValuesForColumn(int i); - - String toString(Object o); - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableFilterColumnPopup.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableFilterColumnPopup.java deleted file mode 100644 index 6d3d8ef..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableFilterColumnPopup.java +++ /dev/null @@ -1,586 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ - - -package jaxx.runtime.swing.table.filter; - -import jaxx.runtime.swing.JAXXWidgetUtil; -import jaxx.runtime.swing.JSearchTextField; -import jaxx.runtime.swing.list.ActionCheckListModel; -import jaxx.runtime.swing.list.CheckList; -import jaxx.runtime.swing.list.filter.CheckListFilterType; -import jaxx.runtime.swing.list.DefaultCheckListModel; -import jaxx.runtime.swing.list.CheckListModel; -import jaxx.runtime.swing.list.filter.DefaultFilterableCheckListModel; -import jaxx.runtime.swing.list.filter.FilterableActionCheckListModel; -import jaxx.runtime.swing.list.filter.FilterableCheckList; -import jaxx.runtime.swing.list.filter.FilterableCheckListModel; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.nuiton.decorator.Decorator; - -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.event.PopupMenuEvent; -import javax.swing.event.PopupMenuListener; -import javax.swing.table.JTableHeader; -import javax.swing.table.TableColumnModel; - -import static org.nuiton.i18n.I18n.t; - -class TableFilterColumnPopup extends MouseAdapter { - - static class ColumnAttrs { - public Dimension preferredSize; - } - - private boolean enabled = false; - - private final FilterableCheckList<Object> filterList = new FilterableCheckList(); - private final JSearchTextField searchField = new JSearchTextField(); - - private final Map<Integer, ColumnAttrs> colAttrs = new HashMap<Integer, ColumnAttrs>(); - private int mColumnIndex = -1; - - private final TableFilter<?> filter; - private boolean searchable; - private Decorator<Object> decorator; - private boolean actionsVisible = true; - private boolean useTableRenderers = false; - - private final JPopupMenu menu; - - private Dimension defaultSize = null; - - public TableFilterColumnPopup(TableFilter<?> filter) { - - menu = new ResizablePopupMenu() { - - private static final long serialVersionUID = 1L; - - @Override - public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - if (menu.getComponentCount() == 0) { - JComponent content = buildContent(); - if (defaultSize == null) { - defaultSize = content.getPreferredSize(); - } else { - content.setPreferredSize(defaultSize); - } - - menu.add(content); - - } - beforeShow(); - } - - @Override - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { - beforeHide(); - } - - }; - - this.filter = filter; - filterList.getList().setVisibleRowCount(8); - - setupTableHeader(); - filter.getTable().addPropertyChangeListener("tableHeader", new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent evt) { - setupTableHeader(); - } - } - ); - filter.getTable().addPropertyChangeListener("model", new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent evt) { - colAttrs.clear(); - } - } - ); - - searchField.getDocument().addDocumentListener(new DocumentListener() { - - @Override - public void removeUpdate(DocumentEvent e) { - perform(e); - } - - @Override - public void insertUpdate(DocumentEvent e) { - perform(e); - } - - @Override - public void changedUpdate(DocumentEvent e) { - perform(e); - } - - private void perform(DocumentEvent e) { - String text = searchField.getText(); - - //#3601 [TABLE FILTER] uncheck the "all" action when the user starts typing in the search field - if (actionsVisible) { - FilterableCheckListModel<Object> model = filterList.getModel(); - if (model.isCheckedIndex(0)) { - model.setCheckedIndex(0, false); - } - - } - filterList.filter(text, decorator, CheckListFilterType.CONTAINS); - } - - }); - - } - - public final Dimension getDefaultSize() { - return defaultSize; - } - - public final void setDefaultSize(Dimension dimension) { - defaultSize = dimension; - } - - public final Dimension getPreferredSize() { - return menu.getPreferredSize(); - } - - public final void setPreferredSize(Dimension preferredSize) { - menu.setPreferredSize(preferredSize); - } - - /** - * Shows Popup in predefined location - * - * @param invoker - * @param x - * @param y - */ - public void show(Component invoker, int x, int y) { - menu.show(invoker, x, y); - } - - /** - * Shows popup in predefined location - * - * @param invoker - * @param location - */ - public void show(Component invoker, Point location) { - show(invoker, location.x, location.y); - } - - /** - * Hides popup - */ - public final void hide() { - menu.setVisible(false); - } - - public void setSearchable(boolean searchable) { - this.searchable = searchable; - } - - public void searchDecorator(Decorator<Object> decorator) { - this.decorator = decorator; - } - - public void setActionsVisible(boolean actionsVisible) { - this.actionsVisible = actionsVisible; - } - - public void setUseTableRenderers(boolean reuseRenderers) { - this.useTableRenderers = reuseRenderers; - } - - private void setupTableHeader() { - JTableHeader header = filter.getTable().getTableHeader(); - if (header != null) header.addMouseListener(this); - } - - protected JComponent buildContent() { - - JPanel owner = new JPanel(new BorderLayout(3, 3)); - owner.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); - owner.setPreferredSize(new Dimension(250, 150)); // default popup size - - Box commands = new Box(BoxLayout.LINE_AXIS); - - JToolBar toolbar = new JToolBar(); - toolbar.setFloatable(false); - toolbar.setOpaque(false); - toolbar.add(new CommandAction( - t("jaxx.table.filter.popup.button.clearAll"), - JAXXWidgetUtil.createImageIcon("funnel_delete.png")) { - @Override - protected boolean perform() { - return clearAllFilters(); - } - }); - commands.add(toolbar); - - commands.add(Box.createHorizontalGlue()); - - commands.add(new JButton(new CommandAction(t("jaxx.table.filter.popup.button.apply")) { - @Override - protected boolean perform() { - return applyColumnFilter(); - } - }) - ); - commands.add(Box.createHorizontalStrut(5)); - commands.add(new JButton(new CommandAction(t("jaxx.table.filter.popup.button.cancel")))); - commands.setBorder(BorderFactory.createEmptyBorder(3, 0, 3, 0)); - commands.setBackground(UIManager.getColor("Panel.background")); - commands.setOpaque(true); - - if (searchable) { - owner.add(searchField, BorderLayout.NORTH); - } - owner.add(new JScrollPane(filterList.getList()), BorderLayout.CENTER); - owner.add(commands, BorderLayout.SOUTH); - - return owner; - - } - - private boolean applyColumnFilter() { - Collection<Object> checked = filterList.getCheckedItems(); - FilterableCheckListModel<Object> model = filterList.getModel(); - model.filter("", decorator, CheckListFilterType.CONTAINS); // clear filter to get true results - filter.apply(mColumnIndex, checked); - return true; - } - - private boolean clearAllFilters() { - filter.clear(); - return true; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - // Popup menus are triggered differently on different platforms - // Therefore, isPopupTrigger should be checked in both mousePressed and mouseReleased - // events for for proper cross-platform functionality - - @Override - public void mousePressed(MouseEvent e) { - if (enabled && e.isPopupTrigger()) showFilterPopup(e); - } - - @Override - public void mouseReleased(MouseEvent e) { - if (enabled && e.isPopupTrigger()) showFilterPopup(e); - } - - private void showFilterPopup(MouseEvent e) { - JTableHeader header = (JTableHeader) (e.getSource()); - TableColumnModel colModel = filter.getTable().getColumnModel(); - - // The index of the column whose header was clicked - int vColumnIndex = colModel.getColumnIndexAtX(e.getX()); - if (vColumnIndex < 0) return; - - - // Determine if mouse was clicked between column heads - Rectangle headerRect = filter.getTable().getTableHeader().getHeaderRect(vColumnIndex); - if (vColumnIndex == 0) { - headerRect.width -= 2; - } else { - headerRect.grow(-2, 0); - } - - // Mouse was clicked between column heads - if (!headerRect.contains(e.getX(), e.getY())) return; - - // restore popup's size for the column - mColumnIndex = filter.getTable().convertColumnIndexToModel(vColumnIndex); - setPreferredSize(getColumnAttrs(vColumnIndex).preferredSize); - - Collection<Object> distinctItems = filter.getDistinctColumnItems(mColumnIndex); - if (distinctItems != null) { - - DefaultFilterableCheckListModel<Object> model = new DefaultFilterableCheckListModel<Object>(distinctItems); - filterList.setModel(actionsVisible ? new FilterableActionCheckListModel<Object>(model) : model); - Collection<Object> checked = filter.getFilterState(mColumnIndex); - - // replace empty checked items with full selection - filterList.setCheckedItems(CollectionUtils.isEmpty(checked) ? distinctItems : checked); - - if (useTableRenderers) { - filterList.getList().setCellRenderer(new TableAwareCheckListRenderer(decorator)); - } - - // show pop-up - show(header, headerRect.x, header.getHeight()); - } - } - - private ColumnAttrs getColumnAttrs(int column) { - ColumnAttrs attrs = colAttrs.get(column); - if (attrs == null) { - attrs = new ColumnAttrs(); - colAttrs.put(column, attrs); - } - - return attrs; - } - - protected void beforeShow() { - if (searchable) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - searchField.setText(""); - searchField.requestFocusInWindow(); - } - }); - } - } - - public void beforeHide() { - // save pop-up's dimensions before pop-up becomes hidden - getColumnAttrs(mColumnIndex).preferredSize = getPreferredSize(); - } - - /** - * Simple action to for the popup window. - * To use - override perform method. - * - * Created on Feb 4, 2011 - * - * @author Eugene Ryzhikov - */ - protected class CommandAction extends AbstractAction { - - private static final long serialVersionUID = 1L; - - public CommandAction(String name, Icon icon) { - super(name, icon); - - if (icon != null) { - putValue(Action.SHORT_DESCRIPTION, name); - putValue(Action.NAME, null); - } - - } - - public CommandAction(String name) { - super(name); - } - - @Override - public final void actionPerformed(ActionEvent e) { - if (perform()) hide(); - } - - /** - * Preforms action - * - * @return true if popup should be closed - */ - protected boolean perform() { - return true; - } - } - - protected class ResizablePopupMenu extends JPopupMenu implements PopupMenuListener { - - private static final long serialVersionUID = 1L; - - private static final int DOT_SIZE = 2; - private static final int DOT_START = 2; - private static final int DOT_STEP = 4; - - public ResizablePopupMenu() { - super(); - new PopupMenuResizer(this); - addPopupMenuListener(this); - } - - @Override - public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - } - - @Override - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { - } - - @Override - public void popupMenuCanceled(PopupMenuEvent e) { - } - - @Override - public void paintChildren(Graphics g) { - super.paintChildren(g); - drawResizer(g); - } - - private void drawResizer(Graphics g) { - - int x = getWidth() - 2; - int y = getHeight() - 2; - - Graphics g2 = g.create(); - - try { - for (int dy = DOT_START, j = 2; j > 0; j--, dy += DOT_STEP) { - for (int dx = DOT_START, i = 0; i < j; i++, dx += DOT_STEP) { - drawDot(g2, x - dx, y - dy); - } - } - - } finally { - g2.dispose(); - } - }; - - private void drawDot(Graphics g, int x, int y) { - g.setColor(Color.WHITE); - g.fillRect(x, y, DOT_SIZE, DOT_SIZE); - g.setColor(Color.LIGHT_GRAY); - g.fillRect(x - 1, y - 1, DOT_SIZE, DOT_SIZE); - } - - } - - /** - * Allows to resize popup with the mouse. - * - * Created on Aug 6, 2010 - * - * @author exr0bs5 - */ - protected class PopupMenuResizer extends MouseAdapter { - - private final JPopupMenu menu; - - private static final int REZSIZE_SPOT_SIZE = 10; - - private Point mouseStart = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE); - - private Dimension startSize; - - private boolean isResizing = false; - - public PopupMenuResizer(JPopupMenu menu) { - this.menu = menu; - this.menu.setLightWeightPopupEnabled(true); - menu.addMouseListener(this); - menu.addMouseMotionListener(this); - } - - private boolean isInResizeSpot(Point point) { - - if (point == null) return false; - - Rectangle resizeSpot = new Rectangle( - menu.getWidth() - REZSIZE_SPOT_SIZE, - menu.getHeight() - REZSIZE_SPOT_SIZE, - REZSIZE_SPOT_SIZE, - REZSIZE_SPOT_SIZE); - - return resizeSpot.contains(point); - - } - - @Override - public void mouseMoved(MouseEvent e) { - - menu.setCursor( - Cursor.getPredefinedCursor( - isInResizeSpot(e.getPoint()) ? Cursor.SE_RESIZE_CURSOR : Cursor.DEFAULT_CURSOR)); - } - - private Point toScreen(MouseEvent e) { - - Point p = e.getPoint(); - SwingUtilities.convertPointToScreen(p, e.getComponent()); - return p; - - } - - @Override - public void mousePressed(MouseEvent e) { - mouseStart = toScreen(e); - startSize = menu.getSize(); - isResizing = isInResizeSpot(e.getPoint()); - } - - @Override - public void mouseReleased(MouseEvent e) { - mouseStart = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE); - isResizing = false; - } - - @Override - public void mouseDragged(MouseEvent e) { - - if (!isResizing) return; - - Point p = toScreen(e); - - int dx = p.x - mouseStart.x; - int dy = p.y - mouseStart.y; - - - Dimension minDim = menu.getMinimumSize(); - // Dimension maxDim = menu.getMaximumSize(); - Dimension newDim = new Dimension(startSize.width + dx, startSize.height + dy); - - if (newDim.width >= minDim.width && newDim.height >= minDim.height /*&& - newDim.width <= maxDim.width && newDim.height <= maxDim.height*/) { - menu.setPopupSize(newDim); - } - - } - } - -} - diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableFilterState.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableFilterState.java deleted file mode 100644 index b0dc942..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableFilterState.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ - -package jaxx.runtime.swing.table.filter; - -import org.apache.commons.collections4.CollectionUtils; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -class TableFilterState implements Serializable { - - private static final long serialVersionUID = 1L; - - // no set - filter cleared; set - some kind of filtering - private final Map<Integer,Set<Object>> data = new HashMap<Integer,Set<Object>>(); - - /** - * Clears filtering for specific column - */ - public void clear( int column ) { - data.remove(column); - } - - - /** - * Clears all filtering - */ - public void clear() { - data.clear(); - } - - private Set<Object> prepareValueSet( int column ) { - Set<Object> vals = data.get(column); - if ( vals == null ) { - vals = new HashSet<Object>(); - data.put(column, vals); - } - return vals; - } - - - /** - * Adds filter value for specified column - * @param column - * @param value - */ - public void addValue( int column, Object value ) { - prepareValueSet(column).add(value); - } - - - /** - * Adds a collection of filter values for specified column - * @param column - * @param values - */ - public void addValues( int column, Collection<Object> values ) { - prepareValueSet(column).addAll(values); - } - - /** - * Resets a collection of filter values for specified column - * @param column - * @param values - */ - public void setValues( int column, Collection<Object> values ) { - data.remove(column); - if (CollectionUtils.isNotEmpty(values)) { - prepareValueSet(column).addAll(values); - } - } - - public Collection<Object> getValues( int column ) { - Set<Object> vals = data.get(column); - return vals == null? Collections.<Object>emptySet(): vals; - } - - /** - * Standard test for row inclusion using current filter values - * @param entry - * @return true if row has to be included - */ - public boolean include( TableFilter.Row entry ) { - - for( int col=0; col< entry.getValueCount(); col++ ) { - Collection<Object> values = getValues(col); - if ( CollectionUtils.isEmpty(values) ) continue; // no filtering for this column - if ( !values.contains( entry.getValue(col) )) return false; - } - return true; - - } - - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableRowFilterSupport.java b/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableRowFilterSupport.java deleted file mode 100644 index a050ca9..0000000 --- a/jaxx-widgets/src/main/java/jaxx/runtime/swing/table/filter/TableRowFilterSupport.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2009-2011, EzWare - * 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 the - * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. - * - * %%Ignore-License%% - */ - -package jaxx.runtime.swing.table.filter; - -import org.nuiton.decorator.Decorator; - -import java.awt.*; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.Collections; - -import javax.swing.JTable; -import javax.swing.table.TableColumn; -import javax.swing.table.TableModel; - -public final class TableRowFilterSupport { - - private boolean searchable = false; - private Decorator<Object> decorator; - private final TableFilter<?> filter; - private boolean actionsVisible = true; - private boolean useTableRenderers = false; - private Dimension popupDefaultSize = null; - - private TableRowFilterSupport( TableFilter<?> filter ) { - if ( filter == null ) throw new NullPointerException(); - //this.table = table; - this.filter = filter; - } - - public static TableRowFilterSupport forFilter( TableFilter<?> filter ) { - return new TableRowFilterSupport(filter); - } - - /** - * Additional actions visible in column filter list - * @param visible - * @return - */ - public TableRowFilterSupport actions( boolean visible ) { - this.actionsVisible = visible; - return this; - } - - /** - * Comlumn filter list is searchable - * @param searchable - * @return - */ - public TableRowFilterSupport searchable( boolean searchable) { - this.searchable = searchable; - return this; - } - - public TableRowFilterSupport searchDecorator( Decorator<Object> decorator ) { - this.decorator = decorator; - return this; - } - - public TableRowFilterSupport useTableRenderers( boolean value ) { - this.useTableRenderers = value; - return this; - } - - public TableRowFilterSupport setPopupDefaultSize(Dimension popupDefaultSize) { - this.popupDefaultSize = popupDefaultSize; - return this; - } - - public JTable apply() { - - final TableFilterColumnPopup filterPopup = new TableFilterColumnPopup(filter); - filterPopup.setEnabled(true); - filterPopup.setActionsVisible(actionsVisible); - filterPopup.setSearchable(searchable); - filterPopup.searchDecorator(decorator); - filterPopup.setUseTableRenderers(useTableRenderers); - filterPopup.setDefaultSize(popupDefaultSize); - - setupTableHeader(); - - return filter.getTable(); - } - - private void setupTableHeader() { - - final JTable table = filter.getTable(); - - filter.addChangeListener(new FilterChangeListener() { - - @Override - public void filterChanged(TableFilter<?> filter) { - table.getTableHeader().repaint(); - - } - }); - - // make sure that search component is reset after table model changes - setupHeaderRenderers(table.getModel(), true ); -// table.addPropertyChangeListener("model", new PropertyChangeListener() { -// -// public void propertyChange(PropertyChangeEvent evt) { -// -// FilterTableHeaderRenderer headerRenderer = new FilterTableHeaderRenderer(filter); -// filter.modelChanged((TableModel) evt.getNewValue()); -// -// for( TableColumn c: Collections.list( filter.getTable().getColumnModel().getColumns()) ) { -// c.setHeaderRenderer( headerRenderer ); -// } -// }} -// -// ); - } - - private void setupHeaderRenderers( TableModel newModel, boolean fullSetup ) { - - final JTable table = filter.getTable(); - - FilterTableHeaderRenderer headerRenderer = new FilterTableHeaderRenderer(filter); - filter.modelChanged( newModel ); - - for( TableColumn c: Collections.list( table.getColumnModel().getColumns()) ) { - c.setHeaderRenderer( headerRenderer ); - } - - if ( !fullSetup ) return; - - PropertyChangeListener listener = new PropertyChangeListener() { - - public void propertyChange(PropertyChangeEvent e) { - setupHeaderRenderers(table.getModel(), false); - } - - }; - table.addPropertyChangeListener("model", listener); - table.addPropertyChangeListener("columnModel", listener); - - } - -} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/AboutPanel.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/AboutPanel.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/AboutPanel.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/AboutPanel.jaxx diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/AboutPanelHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/AboutPanelHandler.java new file mode 100644 index 0000000..cdcbfa5 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/AboutPanelHandler.java @@ -0,0 +1,189 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.Resource; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JRootPane; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import java.awt.Component; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.IOException; +import java.io.InputStream; + +import static org.nuiton.i18n.I18n.t; + +/** + * Handler of the ui {@link AboutPanel}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.4 + * @deprecated please use now jaxx-widgets-about module instead. + */ +@Deprecated +public class AboutPanelHandler { + + private static final Log log = LogFactory.getLog(AboutPanelHandler.class); + + protected final AboutPanel ui; + + public AboutPanelHandler(AboutPanel ui) { + this.ui = ui; + } + + final protected Action closeAction = new AbstractAction("close") { + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + JDialog container = ui.getParentContainer(JDialog.class); + if (container != null) { + container.dispose(); + } else { + ui.setVisible(false); + } + } + }; + + public void setLicenseFile(String filename) { + String load = load(filename); + ui.setLicenseText(load); + } + + public void setThirdpartyFile(String filename) { + String load = load(filename); + ui.setThirdpartyText(load); + } + + public void buildTopPanel() { + // image + JLabel labelIcon; + if (ui.iconPath != null) { + Icon logoIcon = Resource.getIcon(ui.iconPath); + labelIcon = new JLabel(logoIcon); + } else { + labelIcon = new JLabel(); + } + ui.topPanel.add(labelIcon); + } + + public void init() { + if (ui.getAboutText() == null) { + ui.tabs.remove(ui.aboutContent); + } + if (ui.getLicenseText() == null) { + ui.tabs.remove(ui.licenseContent); + } else { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + ui.licenseTextArea.setCaretPosition(0); + } + }); + + } + if (ui.getThirdpartyText() == null) { + ui.tabs.remove(ui.thirdpartyContent); + } else { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + ui.thirdpartyTextArea.setCaretPosition(0); + } + }); + } + } + + public void showInDialog(Frame ui, boolean undecorated) { + JDialog f = new JDialog(ui, true); + f.add(this.ui); + if (this.ui.iconPath != null) { + f.setIconImage(SwingUtil.createIcon(this.ui.iconPath).getImage()); + } + f.setResizable(false); + f.setSize(550, 450); + f.setUndecorated(undecorated); + JRootPane rootPane = f.getRootPane(); + rootPane.setDefaultButton(this.ui.close); + rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ESCAPE"), "close"); + rootPane.getActionMap().put("close", closeAction); + f.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + Component ui = (Component) e.getSource(); + if (log.isInfoEnabled()) { + log.info("destroy ui " + ui); + } + JAXXUtil.destroy(ui); + JAXXUtil.destroy(AboutPanelHandler.this.ui); + } + }); + SwingUtil.center(ui, f); + f.setVisible(true); + } + + protected String load(String filename) { + InputStream licenseStream = getClass().getResourceAsStream("/" + filename); + String result = null; + try { + if (licenseStream != null) { + result = IOUtils.toString(licenseStream); + } + } catch (IOException ex) { + // ignore it + } finally { + if (licenseStream != null) { + try { + licenseStream.close(); + } catch (IOException ex) { + log.error("could not close file " + filename); + } + } + } + if (result == null) { + result = "resource " + filename + " not found"; + } + return result; + } + + void $afterCompleteSetup() { + buildTopPanel(); + ui.close.setText(t("aboutframe.ok")); + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/BaseActionPanel.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/BaseActionPanel.java new file mode 100644 index 0000000..e6f9842 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/BaseActionPanel.java @@ -0,0 +1,75 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JPanel; + +/** + * TODO sletellier 15/06/2012 : find a better way to add onActionPerform on custom components + * + * @author Sylvain Lletellier + */ +public abstract class BaseActionPanel extends JPanel { + + /** + * Notifies all listeners that have registered interest for + * notification on this event type. + * + * @see javax.swing.event.EventListenerList + */ + protected void fireActionEvent() { + ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "actionPerformed"); + + // Guaranteed to return a non-null array + Object[] listeners = listenerList.getListenerList(); + // Process the listeners last to first, notifying + // those that are interested in this event + for (Object listener : listeners) { + if (ActionListener.class.isInstance(listener)) { + ((ActionListener)listener).actionPerformed(e); + } + } + } + + /** + * Adds an <code>ActionListener</code>. + * <p> + * The <code>ActionListener</code> will receive an <code>ActionEvent</code> + * when a selection has been made. If the combo box is editable, then + * an <code>ActionEvent</code> will be fired when editing has stopped. + * + * @param l the <code>ActionListener</code> that is to be notified + */ + public void addActionListener(ActionListener l) { + listenerList.add(ActionListener.class,l); + } + + /** Removes an <code>ActionListener</code>. + * + * @param l the <code>ActionListener</code> to remove + */ + public void removeActionListener(ActionListener l) { + listenerList.remove(ActionListener.class, l); + } +} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/ClockWidget.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ClockWidget.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/ClockWidget.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ClockWidget.jaxx diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/ComboToListSelector.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ComboToListSelector.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/ComboToListSelector.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ComboToListSelector.jaxx diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/CompoundIcon.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/CompoundIcon.java new file mode 100644 index 0000000..94fa52c --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/CompoundIcon.java @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ +package org.nuiton.jaxx.runtime.swing; + +import java.awt.*; +import javax.swing.*; + +/** + * The CompoundIcon will paint two, or more, Icons as a single Icon. The Icons + * are painted in the order in which they are added. + * + * The Icons can be laid out + * <ul> + * <li>Horizontally + * <li>Vertically + * <li>Stacked + * </ul> + * + */ +public class CompoundIcon implements Icon { + public enum Layout { + HORIZONTAL, VERTICAL, STACKED; + } + + public final static float TOP = 0.0f; + public final static float LEFT = 0.0f; + public final static float CENTER = 0.5f; + public final static float BOTTOM = 1.0f; + public final static float RIGHT = 1.0f; + + private Icon[] icons; + + private Layout layout; + + private int gap; + + private float alignmentX = CENTER; + private float alignmentY = CENTER; + + /** + * Convenience constructor for creating a CompoundIcon where the icons are + * laid out horizontally, the gap is 0 and the X/Y alignments will default + * to CENTER. + * + * @param icons + * the Icons to be painted as part of the CompoundIcon + */ + public CompoundIcon(Icon... icons) { + this(Layout.HORIZONTAL, icons); + } + + /** + * Convenience constructor for creating a CompoundIcon where the gap is 0 + * and the X/Y alignments will default to CENTER. + * + * @param layout + * the layout used to lay out the icons for painting. + * @param icons + * the Icons to be painted as part of the CompoundIcon + */ + public CompoundIcon(Layout layout, Icon... icons) { + this(layout, 0, icons); + } + + /** + * Convenience constructor for creating a CompoundIcon where the X/Y + * alignments will default to CENTER. + * + * @param layout + * the layout used to lay out the icons for painting + * @param gap + * the gap between the icons + * @param icons + * the Icons to be painted as part of the CompoundIcon + */ + public CompoundIcon(Layout layout, int gap, Icon... icons) { + this(layout, gap, CENTER, CENTER, icons); + } + + /** + * Create a CompoundIcon specifying all the properties. + * + * @param layout + * the layout used to lay out the icons for painting + * @param gap + * the gap between the icons + * @param alignmentX + * the X alignment of the icons. Common values are LEFT, CENTER, + * RIGHT. Can be any value between 0.0 and 1.0 + * @param alignmentY + * the Y alignment of the icons. Common values are TOP, CENTER, + * BOTTOM. Can be any value between 0.0 and 1.0 + * @param icons + * the Icons to be painted as part of the CompoundIcon + */ + public CompoundIcon(Layout layout, int gap, float alignmentX, + float alignmentY, Icon... icons) { + this.layout = layout; + this.gap = gap; + this.alignmentX = alignmentX > 1.0f ? 1.0f : alignmentX < 0.0f ? 0.0f + : alignmentX; + this.alignmentY = alignmentY > 1.0f ? 1.0f : alignmentY < 0.0f ? 0.0f + : alignmentY; + + for (int i = 0; i < icons.length; i++) { + if (icons[i] == null) { + throw new IllegalArgumentException("Icon (" + i + + ") cannot be null"); + } + } + + this.icons = icons; + } + + /** + * Get the layout along which each icon is painted. + * + * @return the layout + */ + public Layout getLayout() { + return layout; + } + + /** + * Get the gap between each icon + * + * @return the gap in pixels + */ + public int getGap() { + return gap; + } + + /** + * Get the alignment of the icon on the x-layout + * + * @return the alignment + */ + public float getAlignmentX() { + return alignmentX; + } + + /** + * Get the alignment of the icon on the y-layout + * + * @return the alignment + */ + public float getAlignmentY() { + return alignmentY; + } + + /** + * Get the number of Icons contained in this CompoundIcon. + * + * @return the total number of Icons + */ + public int getIconCount() { + return icons.length; + } + + /** + * Get the Icon at the specified index. + * + * @param index + * the index of the Icon to be returned + * @return the Icon at the specified index + * @exception IndexOutOfBoundsException + * if the index is out of range + */ + public Icon getIcon(int index) { + return icons[index]; + } + + // ///// Icon Interface ///////////////////////////// + + /** + * Gets the width of this icon. + * + * @return the width of the icon in pixels. + */ + @Override + public int getIconWidth() { + int width = 0; + + // Add the width of all Icons while also including the gap + if (layout == Layout.HORIZONTAL) { + width += (icons.length - 1) * gap; + for (Icon icon : icons) + width += icon.getIconWidth(); + } else { // Just find the maximum width + for (Icon icon : icons) + width = Math.max(width, icon.getIconWidth()); + } + + return width; + } + + /** + * Gets the height of this icon. + * + * @return the height of the icon in pixels. + */ + @Override + public int getIconHeight() { + int height = 0; + + // Add the height of all Icons while also including the gap + if (layout == Layout.VERTICAL) { + height += (icons.length - 1) * gap; + + for (Icon icon : icons) + height += icon.getIconHeight(); + } else // Just find the maximum height + { + for (Icon icon : icons) + height = Math.max(height, icon.getIconHeight()); + } + + return height; + } + + /** + * Paint the icons of this compound icon at the specified location + * + * @param c The component on which the icon is painted + * + * @param g the graphics context + * + * @param x the X coordinate of the icon's top-left corner + * + * @param y the Y coordinate of the icon's top-left corner + * + */ + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + if (layout == Layout.HORIZONTAL) { + int height = getIconHeight(); + + for (Icon icon : icons) { + int iconY = getOffset(height, icon.getIconHeight(), alignmentY); + icon.paintIcon(c, g, x, y + iconY); + x += icon.getIconWidth() + gap; + } + } else if (layout == Layout.VERTICAL) { + int width = getIconWidth(); + + for (Icon icon : icons) { + int iconX = getOffset(width, icon.getIconWidth(), alignmentX); + icon.paintIcon(c, g, x + iconX, y); + y += icon.getIconHeight() + gap; + } + } else {// must be Z_layout + + int width = getIconWidth(); + int height = getIconHeight(); + + for (Icon icon : icons) { + int iconX = getOffset(width, icon.getIconWidth(), alignmentX); + int iconY = getOffset(height, icon.getIconHeight(), alignmentY); + icon.paintIcon(c, g, x + iconX, y + iconY); + } + } + } + + /* + * When the icon value is smaller than the maximum value of all icons the + * icon needs to be aligned appropriately. Calculate the offset to be used + * when painting the icon to achieve the proper alignment. + */ + private int getOffset(int maxValue, int iconValue, float alignment) { + float offset = (maxValue - iconValue) * alignment; + return Math.round(offset); + } +} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/ErrorDialogUI.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ErrorDialogUI.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/ErrorDialogUI.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ErrorDialogUI.jaxx diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ErrorDialogUIHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ErrorDialogUIHandler.java new file mode 100644 index 0000000..cd2133e --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ErrorDialogUIHandler.java @@ -0,0 +1,95 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.SwingUtil; + +import javax.swing.InputMap; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JRootPane; +import javax.swing.KeyStroke; +import java.awt.Dialog; +import java.awt.Frame; +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * Handler of ui {@link ErrorDialogUI}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0 + */ +public class ErrorDialogUIHandler { + + protected final ErrorDialogUI ui; + + public ErrorDialogUIHandler(ErrorDialogUI ui) { + this.ui = ui; + } + + public static void init(Frame frame) { + disposeUI(); + ErrorDialogUI.instance = new ErrorDialogUI(frame); + ErrorDialogUI.instance.setModalityType(Dialog.ModalityType.TOOLKIT_MODAL); + } + + public static void showError(Exception e) { + ErrorDialogUI instance = ErrorDialogUI.instance; + if (instance == null) { + instance = new ErrorDialogUI(); + } + instance.getErrorMessage().setText(e.getMessage()); + StringWriter w = new StringWriter(); + PrintWriter writer = new PrintWriter(w); + try { + e.printStackTrace(writer); + instance.getErrorStack().setText(w.toString()); + } finally { + writer.close(); + } + instance.getErrorStack().setCaretPosition(0); + instance.pack(); + SwingUtil.center(instance.getContextValue(JFrame.class, "parent"), instance); + instance.setVisible(true); + } + + public static void disposeUI() { + ErrorDialogUI instance = ErrorDialogUI.instance; + if (instance != null) { + JAXXUtil.destroy(instance); + } + ErrorDialogUI.instance = null; + } + + void $afterCompleteSetup() { + JRootPane rootPane = ui.getRootPane(); + + JButton close = ui.close; + rootPane.setDefaultButton(close); + InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + inputMap.put(KeyStroke.getKeyStroke("ESCAPE"), "close"); + rootPane.getActionMap().put("close", close.getAction()); + } +} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/FontSizor.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/FontSizor.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/FontSizor.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/FontSizor.jaxx diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/FontSizorHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/FontSizorHandler.java new file mode 100644 index 0000000..48085c4 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/FontSizorHandler.java @@ -0,0 +1,81 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import org.nuiton.jaxx.runtime.binding.SimpleJAXXObjectBinding; + +/** + * Handler of ui {@link FontSizor}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0 + */ +public class FontSizorHandler { + + protected final FontSizor ui; + + public FontSizorHandler(FontSizor ui) { + this.ui = ui; + } + + public static final String BINDING_FONT_SIZE_CALL_BACK = "fontSize.callBack"; + + public static final String BINDING_DEFAULT_FONT_SIZE_CALL_BACK = "defaultFontSize.callBack"; + + public void init() { + if (ui.fontSize == null) { + ui.setFontSize(ui.defaultFontSize); + } + } + + boolean updateDefaultSizeEnabled(Float fontSize, + Float defaultFontSize, + boolean enabled) { + if (fontSize == null || defaultFontSize == null) { + return false; + } + return !fontSize.equals(defaultFontSize) && enabled; + } + + public void setCallBack(final Runnable action) { + ui.removeDataBinding(BINDING_FONT_SIZE_CALL_BACK); + ui.registerDataBinding(new SimpleJAXXObjectBinding(ui, BINDING_FONT_SIZE_CALL_BACK, true, "fontSize") { + + @Override + public void processDataBinding() { + action.run(); + } + }); + ui.applyDataBinding(BINDING_FONT_SIZE_CALL_BACK); + } + + void $afterCompleteSetup() { + ui.registerDataBinding(new SimpleJAXXObjectBinding(ui, BINDING_DEFAULT_FONT_SIZE_CALL_BACK, true, "defaultFontSize") { + + @Override + public void processDataBinding() { + ui.setFontSize(ui.defaultFontSize); + } + }); + //applyDataBinding(BINDING_DEFAULT_FONT_SIZE_CALL_BACK); + } +} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/HidorButton.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/HidorButton.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/HidorButton.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/HidorButton.jaxx diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/HidorButtonHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/HidorButtonHandler.java new file mode 100644 index 0000000..e65a7e4 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/HidorButtonHandler.java @@ -0,0 +1,92 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.Icon; +import javax.swing.JComponent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * Handler of ui {@link HidorButton}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0 + */ +public class HidorButtonHandler { + + private static final Log log = + LogFactory.getLog(HidorButtonHandler.class); + + protected final HidorButton ui; + + public HidorButtonHandler(HidorButton ui) { + this.ui = ui; + } + + void $afterCompleteSetup() { + + ui.addPropertyChangeListener("targetVisible", new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (log.isDebugEnabled()) { + log.debug("target visible changed <" + evt.getOldValue() + ":" + evt.getNewValue() + ">"); + } + boolean newValue = (Boolean) evt.getNewValue(); + if (ui.target != null) { + ui.target.setVisible(newValue); + } + } + }); + } + + public void setTarget(JComponent target) { + JComponent oldValue = ui.target; + ui.target = target; + ui.firePropertyChange("target", oldValue, target); + } + + public void setExpandIcon(Icon icon) { + ui.putClientProperty("expandIcon", icon); + } + + public void setHideIcon(Icon icon) { + ui.putClientProperty("hideIcon", icon); + } + + protected String updateToolTipText(boolean c) { + return c ? ui.hideTip : ui.showTip; + } + + protected String updateText(boolean c) { + return c ? ui.hideText : ui.showText; + } + + protected Icon updateIcon(boolean c) { + String key = c ? "hideIcon" : "showIcon"; + return (Icon) ui.getClientProperty(key); + } +} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/JAXXDatePicker.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXDatePicker.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/JAXXDatePicker.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXDatePicker.jaxx diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXRuntimeException.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXRuntimeException.java new file mode 100644 index 0000000..f7797ec --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXRuntimeException.java @@ -0,0 +1,48 @@ +package org.nuiton.jaxx.runtime.swing; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/** + * A special runtime exception to catch special errors fro + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.5.19 + */ +public class JAXXRuntimeException extends RuntimeException { + private static final long serialVersionUID = -2963740979386945340L; + + public JAXXRuntimeException() { + } + + public JAXXRuntimeException(String message) { + super(message); + } + + public JAXXRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public JAXXRuntimeException(Throwable cause) { + super(cause); + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXWidgetUtil.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXWidgetUtil.java new file mode 100644 index 0000000..696565d --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/JAXXWidgetUtil.java @@ -0,0 +1,61 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.swing.editor.cell.DateCellEditor; +import org.nuiton.jaxx.runtime.swing.editor.cell.FileCellEditor; +import org.nuiton.jaxx.runtime.swing.editor.cell.KeyStrokeCellEditor; +import org.nuiton.jaxx.runtime.swing.editor.cell.NumberCellEditor; +import org.nuiton.jaxx.runtime.swing.renderer.DateCellRenderer; + +/** + * @author Sylvain Lletellier + */ +public class JAXXWidgetUtil extends SwingUtil { + + public static TableCellRenderer newDateTableCellRenderer(TableCellRenderer renderer) { + return newDateTableCellRenderer(renderer, null); + } + + public static TableCellRenderer newDateTableCellRenderer(TableCellRenderer renderer, String datePattern) { + return new DateCellRenderer(renderer, datePattern); + } + + public static TableCellEditor newDateTableCellEditor() { + return new DateCellEditor(); + } + + public static TableCellEditor newFileTableCellEditor() { + return new FileCellEditor(); + } + + public static TableCellEditor newKeyStrokeTableCellEditor() { + return new KeyStrokeCellEditor(); + } + + public static <E extends Number> NumberCellEditor<E> newNumberTableCellEditor(Class<E> type, boolean useSign) { + return new NumberCellEditor<E>(type, useSign); + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/JSearchTextField.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/JSearchTextField.java new file mode 100644 index 0000000..1cdd7b6 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/JSearchTextField.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ +package org.nuiton.jaxx.runtime.swing; + +import java.awt.Graphics; +import java.awt.Image; + +import javax.swing.ImageIcon; +import javax.swing.JTextField; + +/** + * A text field with search symbol painted to indicate + * that it is used as search field + * + * @author Eugene Ryzhikov + * @since 2.13 + * + */ +public class JSearchTextField extends JTextField { + + private static final String ICON_NAME = "search.png"; + private static final long serialVersionUID = 1L; + + private static ImageIcon icon; + + private static Image getScaledImage( int size ) { + + if (icon == null) { + icon = JAXXWidgetUtil.createImageIcon(ICON_NAME); + } + return new ImageIcon(icon.getImage().getScaledInstance( size, size, Image.SCALE_SMOOTH )).getImage(); + } + + private static int PAD = 4; + private static int PAD2 = PAD*2; + + @Override + public void paint(Graphics g) { + super.paint(g); + int size = getHeight()-PAD2; + g.drawImage( getScaledImage(size), getWidth()-size-PAD, PAD, null); + } + +} + diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ListSelector.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ListSelector.jaxx new file mode 100644 index 0000000..e2819a6 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ListSelector.jaxx @@ -0,0 +1,77 @@ +<!-- + #%L + JAXX :: Widgets + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Table insets='0' genericType='B' abstract='true'> + + <import> + com.google.common.collect.Lists + java.util.List + javax.swing.DefaultComboBoxModel + javax.swing.DefaultListModel + javax.swing.DefaultListCellRenderer + java.beans.PropertyChangeEvent + java.beans.PropertyChangeListener + javax.swing.event.ListDataListener + org.nuiton.jaxx.runtime.swing.model.GenericListModel + org.nuiton.jaxx.runtime.swing.model.GenericListListener + java.util.Collection + java.util.Set + </import> + + <String id='addToolTip' javaBean='"+"'/> + + <String id='removeToolTip' javaBean='"-"'/> + + <ListSelectorModel id='model' + genericType='B' + javaBean='null'/> + + <ListCellRenderer id='renderer' javaBean='new DefaultListCellRenderer()'/> + + <script><![CDATA[ + +public void setValues(Collection<B> values) { + model.setValues(values); +} + +public Collection<B> getValues() { + return model.getValues(); +} + +public void setSelectedValues(Collection<B> selectedValues) { + model.setSelectedValues(selectedValues); +} + +public Collection<B> getSelectedValues() { + return model.getSelectedValues(); +} + +public void addGenericListListener(GenericListListener l) { + model.addGenericListListener(l); +} + +public void removeGenericListListener(GenericListListener l) { + model.removeGenericListListener(l); +} +]]> + </script> + +</Table> diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ListSelectorModel.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ListSelectorModel.java new file mode 100644 index 0000000..f6fb2b0 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ListSelectorModel.java @@ -0,0 +1,185 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import com.google.common.collect.Lists; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Collection; +import org.nuiton.jaxx.runtime.swing.model.GenericListListener; +import org.nuiton.jaxx.runtime.swing.model.GenericListModel; + +/** + * @author Sylvain Lletellier + */ +public class ListSelectorModel<B> { + + protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + + public static final String PROPERTY_ADD_ENABLED = "addEnabled"; + public static final String PROPERTY_REMOVE_ENABLED = "removeEnabled"; + + public static final String PROPERTY_SELECTED_VALUES = "selectedValues"; + public static final String PROPERTY_VALUES = "values"; + + protected boolean addEnabled; + protected boolean removeEnabled; + + protected GenericListModel<B> fromModel; + protected GenericListModel<B> toModel; + + protected ListSelectorModel() { + + fromModel = new GenericListModel<B>(); + fromModel.addPropertyChangeListener(GenericListModel.PROPERTY_SELECTED_VALUE, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + setAddEnabled(fromModel.hasSelectedIndex()); + } + }); + + toModel = new GenericListModel<B>(); + toModel.addPropertyChangeListener(GenericListModel.PROPERTY_SELECTED_VALUE, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + setRemoveEnabled(toModel.hasSelectedIndex()); + } + }); + } + + public boolean isAddEnabled() { + return addEnabled; + } + + public void setAddEnabled(boolean addEnabled) { + boolean oldValue = isAddEnabled(); + this.addEnabled = addEnabled; + firePropertyChange(PROPERTY_ADD_ENABLED, oldValue, addEnabled); + } + + public boolean isRemoveEnabled() { + return removeEnabled; + } + + public void setRemoveEnabled(boolean removeEnabled) { + boolean oldValue = isRemoveEnabled(); + this.removeEnabled = removeEnabled; + firePropertyChange(PROPERTY_REMOVE_ENABLED, oldValue, removeEnabled); + } + + public GenericListModel<B> getFromModel() { + return fromModel; + } + + public GenericListModel<B> getToModel() { + return toModel; + } + + public Collection<B> getValues() { + return fromModel.getElements(); + } + + public void setValues(Collection<B> values) { + Collection<B> oldValues = getValues(); + toModel.clearElements(); + fromModel.setElements(values); + firePropertyChange(PROPERTY_VALUES, oldValues, values); + } + + public void addValues(Collection<B> values) { + Collection<B> oldValues = getValues(); + toModel.removeElements(values); + fromModel.removeElements(values); + fromModel.addElements(values); + firePropertyChange(PROPERTY_VALUES, oldValues, values); + } + + public void removeValues(Collection<B> values) { + Collection<B> oldValues = getValues(); + toModel.removeElements(values); + fromModel.removeElements(values); + firePropertyChange(PROPERTY_VALUES, oldValues, values); + } + + public Collection<B> getSelectedValues() { + return toModel.getElements(); + } + + public void setSelectedValues(Collection<B> selectedValues) { + Collection<B> oldValue = getSelectedValues(); + fromModel.removeElements(selectedValues); + toModel.removeElements(selectedValues); + toModel.setElements(selectedValues); + firePropertyChange(PROPERTY_SELECTED_VALUES, oldValue, selectedValues); + } + + public void add() { + Collection<B> oldValues = getValues(); + Collection<B> oldSelectedValue = getSelectedValues(); + moveSelect(fromModel, toModel); + firePropertyChange(PROPERTY_VALUES, oldValues, getValues()); + firePropertyChange(PROPERTY_SELECTED_VALUES, oldSelectedValue, getSelectedValues()); + } + + public void remove() { + moveSelect(toModel, fromModel); + } + + protected void moveSelect(GenericListModel<B> from, GenericListModel<B> to) { + Collection<B> selectedValues = Lists.newArrayList(from.getSelectedValues()); + from.removeElements(selectedValues); + to.addElements(selectedValues); + } + + public void addGenericListListener(GenericListListener l) { + toModel.addGenericListListener(l); + } + + public void removeGenericListListener(GenericListListener l) { + toModel.removeGenericListListener(l); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + protected void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) { + pcs.fireIndexedPropertyChange(propertyName, index, oldValue, newValue); + } +} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListToListSelector.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ListToListSelector.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/ListToListSelector.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/ListToListSelector.jaxx diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/MemoryStatusWidget.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/MemoryStatusWidget.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/MemoryStatusWidget.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/MemoryStatusWidget.jaxx diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/MemoryStatusWidgetHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/MemoryStatusWidgetHandler.java new file mode 100644 index 0000000..aab2783 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/MemoryStatusWidgetHandler.java @@ -0,0 +1,98 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.JLabel; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.font.FontRenderContext; +import java.awt.font.LineMetrics; +import java.awt.geom.Rectangle2D; + +import static org.nuiton.i18n.I18n.t; + +/** + * Handler of ui {@link MemoryStatusWidget}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0 + */ +public class MemoryStatusWidgetHandler { + + private final static String memoryTestStr = "99999/99999Mb"; + + private FontRenderContext frc = new FontRenderContext(null, false, false); + + private LineMetrics lm = new JLabel().getFont().getLineMetrics(memoryTestStr, frc); + + protected final MemoryStatusWidget ui; + + public MemoryStatusWidgetHandler(MemoryStatusWidget ui) { + this.ui = ui; + } + + public void paintComponent(Graphics g) { + Insets insets = new Insets(0, 0, 0, 0); + Runtime runtime = Runtime.getRuntime(); + int freeMemory = (int) (runtime.freeMemory() / 1024L); + int totalMemory = (int) (runtime.totalMemory() / 1024L); + int usedMemory = totalMemory - freeMemory; + int width = ui.getWidth() - insets.left - insets.right; + int height = ui.getHeight() - insets.top - insets.bottom - 1; + float fraction = (float) usedMemory / (float) totalMemory; + g.setColor(ui.progressBackground); + g.fillRect(insets.left, insets.top, (int) ((float) width * fraction), height); + // No i18n string was : + // String str = usedMemory / 1024 + "/" + totalMemory / 1024 + "Mb"; + String str = t("memorywidget.memory", usedMemory / 1024, totalMemory / 1024); + //FontRenderContext frc = new FontRenderContext(null, false, false); + Rectangle2D bounds = g.getFont().getStringBounds(str, frc); + Graphics g2 = g.create(); + g2.setClip(insets.left, insets.top, + (int) ((float) width * fraction), height); + g2.setColor(ui.progressForeground); + g2.drawString(str, insets.left + + (int) ((double) width - bounds.getWidth()) / 2, + (int) ((float) insets.top + lm.getAscent())); + g2.dispose(); + g2 = g.create(); + g2.setClip(insets.left + (int) ((float) width * fraction), + insets.top, ui.getWidth() - insets.left + - (int) ((float) width * fraction), height); + g2.setColor(ui.getForeground()); + g2.drawString(str, insets.left + + (int) ((double) width - bounds.getWidth()) / 2, + (int) ((float) insets.top + lm.getAscent())); + g2.dispose(); + } + + + void $afterCompleteSetup() { + ui.setFont(new JLabel().getFont()); + Rectangle2D bounds = ui.getFont().getStringBounds(memoryTestStr, frc); + Dimension dim = new Dimension((int) bounds.getWidth(), (int) bounds.getHeight()); + ui.setPreferredSize(dim); + ui.setMaximumSize(dim); + } + +} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/StatusMessagePanel.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/StatusMessagePanel.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/StatusMessagePanel.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/StatusMessagePanel.jaxx diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/StatusMessagePanelHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/StatusMessagePanelHandler.java new file mode 100644 index 0000000..0d6cd38 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/StatusMessagePanelHandler.java @@ -0,0 +1,124 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.runtime.swing; + +import javax.swing.Timer; +import java.awt.Color; +import java.awt.Dimension; + +/** + * @author Tony Chemit - chemit@codelutin.com + * @since 1.6.0 + */ +public class StatusMessagePanelHandler { + + protected final StatusMessagePanel ui; + + protected Color statusForeground; + + protected String statusReferenceContent; + + protected Timer timer; + + public StatusMessagePanelHandler(StatusMessagePanel ui) { + this.ui = ui; + } + + void $afterCompleteSetup() { + init(); + } + + public void init() { + if (ui.isShowBusy()) { + Dimension dim = new Dimension(30, 15); + //Dimension dim = new Dimension(30, (int) statusLabel.getPreferredSize().getHeight()); + //log.info("dimension of busy = "+ dim); + //busyWidget.setPreferredSize(dim); + ui.busyWidget.setMaximumSize(dim); + ui.busyWidget.setMinimumSize(dim); + } + } + + public void clearStatus() { + stopStatusFader(ui); + ui.getStatusLabel().setText(StatusMessagePanel.EMPTY_STATUS); + //getStatusLabel().setString(EMPTY_STATUS); + } + + public void setStatus(String status) { + if (status != null) { + stopStatusFader(ui); + ui.getStatusLabel().setText(status); + //getStatusLabel().setString(status); + } + + if (!ui.isBusy()) { + startStatusFader(ui); + } + } + + protected void fadeStatus(StatusMessagePanel ui) { + for (int i = 0; i < 8; i++) { + // synchronized (this) { + if (!statusReferenceContent.equals(ui.getStatusLabel().getText())) { +// if (!statusReferenceContent.equals(ui.getStatusLabel().getString())) { + return; + } + Color currentForeground = ui.getStatusLabel().getForeground(); + Color newColor = new Color(currentForeground.getRed(), + currentForeground.getGreen(), + currentForeground.getBlue(), + currentForeground.getAlpha() - 25); + ui.getStatusLabel().setForeground(newColor); + ui.getStatusLabel().repaint(); + // } + // TC-2000311 je comprends pas a quoi ca sert, a part frizzer les ui ? + // si on utilise un Timer, pourquoi utiliser ça ? + /*try { + Thread.sleep(200); + } catch (InterruptedException eee) { + eee.printStackTrace(); + }*/ + } + } + + protected void startStatusFader(StatusMessagePanel ui) { + statusReferenceContent = ui.getStatusLabel().getText(); +// statusReferenceContent = ui.getStatusLabel().getString(); + + int millisecondsPerMinute = 5000; + timer = new Timer(millisecondsPerMinute, ui); + timer.setRepeats(false); + timer.setInitialDelay((int) ((long) millisecondsPerMinute - + System.currentTimeMillis() % + (long) millisecondsPerMinute) + 500); + timer.start(); + } + + protected void stopStatusFader(StatusMessagePanel ui) { + if (timer != null) { + timer.stop(); + ui.getStatusLabel().setForeground(statusForeground); + } + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/FileEditor.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/FileEditor.jaxx new file mode 100644 index 0000000..5f7ab2d --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/FileEditor.jaxx @@ -0,0 +1,111 @@ +<!-- + #%L + JAXX :: Widgets + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<BaseActionPanel layout='{new BorderLayout()}'> + <import> + org.nuiton.jaxx.runtime.swing.BaseActionPanel + + org.apache.commons.lang3.StringUtils + + javax.swing.JDialog + java.io.File + </import> + + <FileEditorHandler id='handler' constructorParams='this'/> + + <Boolean id='acceptAllFileFilterUsed' javaBean='Boolean.TRUE'/> + + <Boolean id='directoryEnabled' javaBean='Boolean.TRUE'/> + + <Boolean id='fileEnabled' javaBean='Boolean.TRUE'/> + + <String id='startPath' javaBean='null'/> + + <String id='title' javaBean='null'/> + + <String id='exts' javaBean='null'/> + + <String id='extsDescription' javaBean='null'/> + + <!-- show reset property --> + <Boolean id='showReset' javaBean='false'/> + + <script><![CDATA[ +protected File selectedFile; + +public void setSelectedFile(File selectedFile) { + this.selectedFile = selectedFile; + setStartPath(selectedFile == null ? null : selectedFile.getAbsolutePath()); + fireActionEvent(); +} + +public void setSelectedFilePath(String startPath) { + setSelectedFile(startPath == null ? null : new File(startPath)); +} + +/**public void setSelectedFile(String startPath) { + this.selectedFile = null; + setStartPath(startPath); + fireActionEvent(); +}*/ + +public File getSelectedFile() { + if (selectedFile == null) { + if (StringUtils.isNotEmpty(startPath)) { + selectedFile = new File(startPath); + } + } + return selectedFile; +} + +public void setDialogOwner(JDialog dialogOwner) { + handler.setDialogOwner(dialogOwner); +} + + ]]></script> + + <JToolBar id='toolbar' + floatable='false' + borderPainted='false' + visible='{isShowReset()}' + constraints='BorderLayout.WEST'> + <JButton id='resetButton' + actionIcon='fileeditor-reset' + toolTipText='fileeditor.action.reset.tip' + focusable='false' + focusPainted='false' + enabled='{isEnabled()}' + onActionPerformed='setSelectedFile(null)'/> + </JToolBar> + + + <JTextField id='pathField' + constraints='BorderLayout.CENTER' + enabled='{isEnabled()}' + text='{getStartPath()}' + onKeyReleased='setSelectedFilePath(pathField.getText())'/> + + <JButton id='boutonXslLocation' + constraints='BorderLayout.EAST' + enabled='{isEnabled()}' + actionIcon='open' + onActionPerformed='handler.openLocation()'/> +</BaseActionPanel> diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/FileEditorHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/FileEditorHandler.java new file mode 100644 index 0000000..be3652b --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/FileEditorHandler.java @@ -0,0 +1,188 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.editor; + +import com.google.common.io.Files; +import org.apache.commons.lang3.StringUtils; +import org.nuiton.jaxx.runtime.swing.editor.FileEditor; + +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; +import java.io.File; + +/** @author Sylvain Lletellier */ +public class FileEditorHandler { + + public static final String SEPARATOR_REGEX = "\\s*,\\s*"; + + public static File lastSelectedPath; + + protected FileEditor view; + + /** + * To set the dialog (see https://forge.nuiton.org/issues/2578). + * + * @since 2.5.12 + */ + protected JDialog dialogOwner; + + public FileEditorHandler(FileEditor view) { + this.view = view; + if (lastSelectedPath == null) { + lastSelectedPath = new File(System.getProperty("user.home")); + } + } + + public void openLocation() { + + // use last selected file + File startFile = view.getSelectedFile(); + String startPath = view.getStartPath(); + if (startFile == null && StringUtils.isNotEmpty(startPath)) { + + // else filed start path + startFile = new File(startPath); + } else if (startFile == null) { + + // else start with user home + startFile = lastSelectedPath; + } + JFileChooser fc = new JFileChooser(startFile); + + fc.setDialogTitle(view.getTitle()); + fc.setAcceptAllFileFilterUsed(view.getAcceptAllFileFilterUsed()); + + // TODO sletellier 14/06/2012 : activate multi selection +// boolean multiSelectionEnabled = view.isMultiSelectionEnabled(); +// fc.setMultiSelectionEnabled(multiSelectionEnabled); + + // used to enable directory selection + boolean directoryEnabled = view.isDirectoryEnabled(); + if (directoryEnabled) { + fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + } + + // used to enable file selection + boolean fileEnabled = view.isFileEnabled(); + if (fileEnabled) { + + if (directoryEnabled) { + + // both + fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + } else { + fc.setFileSelectionMode(JFileChooser.FILES_ONLY); + } + String extsAsString = view.getExts(); + if (extsAsString != null) { + + // extentions can be separted by comma + String[] exts = extsAsString.split(SEPARATOR_REGEX); + String extsDescription = view.getExtsDescription(); + + String[] descs = new String[0]; + if (extsDescription != null) { + descs = extsDescription.split(SEPARATOR_REGEX); + } + for (int i = 0;i<exts.length;i++) { + + // use ext if no desc found + String ext = exts[i]; + String desc = ext; + if (descs.length > i) { + desc = descs[i]; + } + + fc.addChoosableFileFilter(new ExtentionFileFiler(ext, desc)); + } + } + } + + // directory or/and file must be enabled + if (!directoryEnabled && !fileEnabled) { + throw new IllegalArgumentException("You must enable at least file or directory to open dialog"); + } + + // show dialog + // see https://forge.nuiton.org/issues/2578 + boolean hackDialog = dialogOwner != null && dialogOwner.isAlwaysOnTop(); + if (hackDialog) { + dialogOwner.setAlwaysOnTop(false); + } + int returnVal = fc.showOpenDialog(view); + if (hackDialog) { + dialogOwner.setAlwaysOnTop(true); + } + if (returnVal == JFileChooser.APPROVE_OPTION) { + + // get selected to display in ui + File file = fc.getSelectedFile(); + + setSelectedFile(file); + } + } + + public void setSelectedFile(String path) { + setSelectedFile(new File(path)); + } + + public void setSelectedFile(File file) { + view.setSelectedFile(file); + view.setStartPath(file.getPath()); + File dir = file; + if (dir.exists()) { + if (!dir.isDirectory()) { + dir = dir.getParentFile(); + } + lastSelectedPath = dir; + } + } + + protected void setDialogOwner(JDialog dialogOwner) { + this.dialogOwner = dialogOwner; + } + + public static class ExtentionFileFiler extends FileFilter { + protected String ext; + protected String desciption; + + public ExtentionFileFiler(String ext, String desciption) { + this.ext = ext; + this.desciption = desciption; + } + + @Override + public boolean accept(File file) { + if (file.isDirectory()) { + return true; + } + String fileExtension = Files.getFileExtension(file.getName()); + return ext.equals(fileExtension); + } + + @Override + public String getDescription() { + return desciption; + } + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/I18nEditor.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/I18nEditor.jaxx new file mode 100644 index 0000000..8b1a15b --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/I18nEditor.jaxx @@ -0,0 +1,144 @@ +<!-- + #%L + JAXX :: Widgets + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<JPanel implements='PropertyChangeListener, ActionListener' + id='content' + layout='{new BorderLayout()}' + onFocusGained='button.requestFocus()' + onFocusLost='setPopupVisible(false)'> + + <import> + + org.nuiton.jaxx.runtime.SwingUtil + + java.awt.BorderLayout + java.awt.event.ItemEvent + java.awt.event.ActionEvent + java.awt.event.ActionListener + javax.swing.border.TitledBorder + + java.beans.PropertyChangeListener + java.beans.PropertyChangeEvent + java.util.Locale + + org.nuiton.jaxx.runtime.swing.renderer.LocaleListCellRenderer + + static org.nuiton.i18n.I18n.n + </import> + + <I18nEditorHandler id='handler' constructorParams='this'/> + + <String id='selectedToolTipText' javaBean='null'/> + <String id='notSelectedToolTipText' javaBean='null'/> + + <Border id='popupBorder' + javaBean='new TitledBorder(t("i18neditor.popup.title"))'/> + + <Boolean id='showText' javaBean='Boolean.TRUE'/> + <Boolean id='showIcon' javaBean='Boolean.TRUE'/> + <Boolean id='showPopupText' javaBean='Boolean.TRUE'/> + <Boolean id='showPopupIcon' javaBean='Boolean.TRUE'/> + <Boolean id='popupVisible' javaBean='Boolean.FALSE'/> + + <java.util.List id='locales' javaBean='null' genericType='Locale'/> + + <Locale id='selectedLocale' javaBean='Locale.getDefault()'/> + + <LocaleListCellRenderer id='renderer' + showIcon='{isShowIcon()}' + showText='{isShowText()}' + javaBean='new LocaleListCellRenderer(showIcon , showText)'/> + + <!-- popup to change sorted property--> + <JPopupMenu id='popup' + border='{getPopupBorder()}' + onPopupMenuWillBecomeInvisible='button.setSelected(false)' + onPopupMenuCanceled='button.setSelected(false)'> + <JLabel id='popupLabel' enabled='false' text='i18neditor.empty.locales'/> + </JPopupMenu> + + <JToggleButton + id='button' + text='{SwingUtil.getStringValue(renderer.getText(getSelectedLocale()))}' + toolTipText='{getTip(getSelectedLocale())}' + icon='{renderer.getIcon(getSelectedLocale())}' + constraints='BorderLayout.CENTER' + selected='{popup.isVisible()}' + focusable='true' + focusPainted='false' + onItemStateChanged='if (event.getStateChange() == ItemEvent.SELECTED) { setPopupVisible(true); } else { popupVisible = false; }'/> + + <ButtonGroup id='indexes' + onStateChanged='log.info(indexes.getSelectedValue())'/> + + <script><![CDATA[ +public static final String DEFAULT_SELECTED_TOOLTIP = n("i18neditor.selected"); +public static final String DEFAULT_NOT_SELECTED_TOOLTIP = n("i18neditor.unselected"); + +public static final String LOCALES_PROPERTY = "locales"; +public static final String SELECTED_LOCALE_PROPERTY = "selectedLocale"; +public static final String SHOW_ICON_PROPERTY = "showIcon"; +public static final String SHOW_TEXT_PROPERTY = "showText"; +public static final String SHOW_POPUP_ICON_PROPERTY = "showPopupIcon"; +public static final String SHOW_POPUP_TEXT_PROPERTY = "showPopupText"; +public static final String POPUP_BORDER_PROPERTY = "popupBorder"; +public static final String POPUP_VISIBLE_PROPERTY = "popupVisible"; + + + +void $afterCompleteSetup() { + handler.$afterCompleteSetup(); +} + +@Override +public void propertyChange(PropertyChangeEvent evt) { + handler.propertyChange(evt); +} + +@Override +public void actionPerformed(ActionEvent event) { + handler.actionPerformed(event); +} + +public void loadI18nBundles() { + handler.loadI18nBundles(); +} + +protected void rebuildPopup() { + handler.rebuildPopup(); +} + +protected String getTip(Locale l) { + return handler.getTip(l); +} + +protected String getSelectedTip(Locale l) { + return handler.getSelectedTip(l); +} + +protected String getNotSelectedTip(Locale l) { + return handler.getNotSelectedTip(l); +} +]]> + </script> +</JPanel> diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/I18nEditorHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/I18nEditorHandler.java new file mode 100644 index 0000000..0ac142a --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/I18nEditorHandler.java @@ -0,0 +1,246 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.editor; + +import org.nuiton.jaxx.runtime.swing.JAXXButtonGroup; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.i18n.I18n; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JToggleButton; +import javax.swing.SwingUtilities; +import javax.swing.border.Border; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Arrays; +import java.util.Collection; +import java.util.Locale; + +import static org.nuiton.i18n.I18n.t; +import static org.nuiton.i18n.I18n.n; + +/** + * Handler of ui {@link I18nEditor}. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.0 + */ +public class I18nEditorHandler implements PropertyChangeListener, ActionListener { + + private static final Log log = LogFactory.getLog(I18nEditorHandler.class); + + protected final I18nEditor ui; + + public I18nEditorHandler(I18nEditor ui) { + this.ui = ui; + } + + public static final String DEFAULT_SELECTED_TOOLTIP = n("i18neditor.selected"); + + public static final String DEFAULT_NOT_SELECTED_TOOLTIP = n("i18neditor.unselected"); + + public static final String LOCALES_PROPERTY = "locales"; + + public static final String SELECTED_LOCALE_PROPERTY = "selectedLocale"; + + public static final String SHOW_ICON_PROPERTY = "showIcon"; + + public static final String SHOW_TEXT_PROPERTY = "showText"; + + public static final String SHOW_POPUP_ICON_PROPERTY = "showPopupIcon"; + + public static final String SHOW_POPUP_TEXT_PROPERTY = "showPopupText"; + + public static final String POPUP_BORDER_PROPERTY = "popupBorder"; + + public static final String POPUP_VISIBLE_PROPERTY = "popupVisible"; + + @Override + public void propertyChange(PropertyChangeEvent evt) { + String name = evt.getPropertyName(); + if (log.isDebugEnabled()) { + log.debug(name + " <old:" + evt.getOldValue() + " - new:" + evt.getNewValue() + ">"); + } + log.info(name + " <old:" + evt.getOldValue() + " - new:" + evt.getNewValue() + ">"); + if (LOCALES_PROPERTY.equals(name)) { + Collection<?> newLocales = (Collection<?>) evt.getNewValue(); + // mise a jour de la popup + boolean oldShowText = ui.renderer.isShowText(); + try { + ui.renderer.setShowText(true); + ui.popup.removeAll(); + for (Object o : newLocales) { + Locale l = (Locale) o; + boolean selected = l.equals(ui.selectedLocale); + String text = ui.isShowPopupText() ? ui.renderer.getText(l) : null; + Icon icon = ui.isShowPopupIcon() ? ui.renderer.getIcon(l) : null; + JRadioButtonMenuItem b = new JRadioButtonMenuItem(text, icon, selected); + ui.popup.add(b); + b.addActionListener(ui); + b.putClientProperty("locale", l); + b.setToolTipText(getTip(l)); + b.putClientProperty(JAXXButtonGroup.BUTTON8GROUP_CLIENT_PROPERTY, ui.getIndexes()); + b.putClientProperty(JAXXButtonGroup.VALUE_CLIENT_PROPERTY, l); + } + } finally { + ui.renderer.setShowText(oldShowText); + ui.popup.invalidate(); + } + return; + } + if (SHOW_ICON_PROPERTY.equals(name)) { + ui.renderer.setShowIcon((Boolean) evt.getNewValue()); + ui.processDataBinding("button.icon"); + return; + } + if (SHOW_TEXT_PROPERTY.equals(name)) { + ui.renderer.setShowText((Boolean) evt.getNewValue()); + ui.processDataBinding("button.text"); + return; + } + if (SHOW_POPUP_ICON_PROPERTY.equals(name)) { + rebuildPopup(); + return; + } + if (SHOW_POPUP_TEXT_PROPERTY.equals(name)) { + rebuildPopup(); + return; + } + if (POPUP_BORDER_PROPERTY.equals(name)) { + ui.popup.setBorder((Border) evt.getNewValue()); + return; + } + if (POPUP_VISIBLE_PROPERTY.equals(name)) { + Boolean newValue = (Boolean) evt.getNewValue(); + if (newValue == null || !newValue) { + if (ui.getPopup() != null && ui.getPopup().isVisible()) { + ui.getPopup().setVisible(false); + } + return; + } + if (!ui.getPopup().isVisible()) { + SwingUtilities.invokeLater(showPopupRunnable); + } + return; + } + if (SELECTED_LOCALE_PROPERTY.equals(name)) { + Locale newLocale = (Locale) evt.getNewValue(); + // mise a jour de la popup + try { + for (Component c : ui.popup.getComponents()) { + if (c instanceof JRadioButtonMenuItem) { + JRadioButtonMenuItem b = (JRadioButtonMenuItem) c; + Locale l = (Locale) b.getClientProperty("locale"); + b.setSelected(newLocale.equals(l)); + } + } + } finally { + ui.popup.invalidate(); + } + } + } + + @Override + public void actionPerformed(ActionEvent event) { + Locale value = (Locale) + ((JComponent) event.getSource()).getClientProperty("locale"); + if (log.isDebugEnabled()) { + log.debug("new locale : " + value); + } + ui.setSelectedLocale(value); + } + + public void loadI18nBundles() { + Locale[] locales = I18n.getStore().getLocales(); + ui.setLocales(Arrays.asList(locales)); + } + + protected void rebuildPopup() { + log.debug("start rebuild"); + try { + for (Component c : ui.popup.getComponents()) { + if (c instanceof JRadioButtonMenuItem) { + JRadioButtonMenuItem b = (JRadioButtonMenuItem) c; + Locale l = (Locale) b.getClientProperty("locale"); + String text = ui.isShowPopupText() ? ui.renderer.getSafeText(l) : null; + Icon icon = ui.isShowPopupIcon() ? ui.renderer.getSafeIcon(l) : null; + b.setIcon(icon); + b.setText(text); + log.debug("text=" + text); + log.debug("icon=" + icon); + } + } + } finally { + ui.popup.invalidate(); + } + } + + protected String getTip(Locale l) { + boolean selected = l.equals(ui.selectedLocale); + return selected ? getSelectedTip(l) : getNotSelectedTip(l); + } + + protected String getSelectedTip(Locale l) { + String selectedTip = ui.getSelectedToolTipText(); + if (selectedTip == null) { + // use default selected tip text + selectedTip = DEFAULT_SELECTED_TOOLTIP; + } + String tip = ui.renderer.getToolTipText(l); + tip = t(selectedTip, tip); + return tip; + } + + protected String getNotSelectedTip(Locale l) { + String selectedTip = ui.getNotSelectedToolTipText(); + if (selectedTip == null) { + // use default not selected tip text + selectedTip = DEFAULT_NOT_SELECTED_TOOLTIP; + } + String tip = ui.renderer.getToolTipText(l); + tip = t(selectedTip, tip); + return tip; + } + + protected Runnable showPopupRunnable = new Runnable() { + @Override + public void run() { + ui.getPopup().pack(); + JToggleButton invoker = ui.getButton(); + Dimension dim = ui.getPopup().getPreferredSize(); + Dimension invokerDim = invoker.getSize(); + ui.getPopup().show(invoker, (int) (invokerDim.getWidth() - dim.getWidth()), invoker.getHeight()); +// getPopup().setVisible(true); + } + }; + + void $afterCompleteSetup() { + ui.addPropertyChangeListener(this); + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/KeyStrokeEditor.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/KeyStrokeEditor.java new file mode 100644 index 0000000..9ed18bb --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/KeyStrokeEditor.java @@ -0,0 +1,80 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.editor; + +import java.awt.event.KeyEvent; +import javax.swing.JTextField; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Custom text field to disable default key events + * + * @author Sylvain Lletellier + */ +public class KeyStrokeEditor extends JTextField { + + private static final Log log = LogFactory.getLog(KeyStrokeEditor.class); + + protected KeyStroke keyStroke; + + public KeyStrokeEditor() { + enableEvents(KeyEvent.KEY_EVENT_MASK); + setFocusTraversalKeysEnabled(false); + } + + @Override + protected void processKeyEvent(KeyEvent e) { + if (e.getID() == KeyEvent.KEY_PRESSED) { + int keyCode = e.getKeyCode(); + if (keyCode == KeyEvent.VK_SHIFT || + keyCode == KeyEvent.VK_ALT || + keyCode == KeyEvent.VK_CONTROL || + keyCode == KeyEvent.VK_ALT_GRAPH || + keyCode == KeyEvent.VK_META) { + + return; + } + + setKeyStroke(KeyStroke.getKeyStroke(keyCode, e.getModifiers())); + } + } + + public KeyStroke getKeyStroke() { + return keyStroke; + } + + public void setKeyStroke(KeyStroke keyStroke) { + KeyStroke oldValue = getKeyStroke(); + this.keyStroke = keyStroke; + firePropertyChange("keyStroke", oldValue, keyStroke); + fireActionPerformed(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + setText(getKeyStroke().toString()); + } + }); + } +} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditor.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/NumberEditor.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditor.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/NumberEditor.jaxx diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/NumberEditorHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/NumberEditorHandler.java new file mode 100644 index 0000000..3c77a02 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/NumberEditorHandler.java @@ -0,0 +1,623 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.runtime.swing.editor; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.beans.BeanUtil; + +import javax.swing.JComponent; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.text.BadLocationException; +import java.awt.Dimension; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.nuiton.jaxx.runtime.swing.editor.NumberEditor.PROPERTY_MODEL; +import static org.nuiton.jaxx.runtime.swing.editor.NumberEditor.PROPERTY_POPUP_VISIBLE; + +/** + * Le handler de l'éditeur graphique de nombres. + * + * Note: Ce handler n'est pas staless, et chaque ui possède le sien. + * + * @author Tony Chemit - chemit@codelutin.com + * @see NumberEditor + */ +public class NumberEditorHandler { + /** Logger */ + public static final Log log = LogFactory.getLog(NumberEditorHandler.class); + + public static final String VALIDATE_PROPERTY = "validate"; + + /** editor ui */ + protected NumberEditor editor; + + /** the mutator method on the property of boxed bean in the editor */ + protected Method mutator; + + /** the getter method on the property */ + protected Method getter; + + /** a flag to known if mutator accept null value */ + protected Boolean acceptNull; + + protected Class<?> modelType; + + protected Pattern numberPattern; + + public NumberEditorHandler(NumberEditor ui) { + editor = ui; + } + + /** initialise l'ui et les listeners d'évènements. */ + public void init() { + try { +// if (editor.getBean() == null) { +// throw new NullPointerException("can not have a null bean in ui " + editor); +// } + + editor.addPropertyChangeListener(NumberEditor.PROPERTY_NUMBER_PATTERN, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + String newPattern = (String) evt.getNewValue(); + if (log.isInfoEnabled()) { + log.info("set new numberPattern" + newPattern); + } + if (StringUtils.isEmpty(newPattern)) { + numberPattern = null; + } else { + numberPattern = Pattern.compile(newPattern); + } + } + }); + + editor.addPropertyChangeListener(NumberEditor.PROPERTY_SHOW_POPUP_BUTTON, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (log.isDebugEnabled()) { + log.debug("set showPopupButton" + evt.getNewValue() + " for " + editor.getProperty()); + } + if (editor.getPopup().isVisible()) { + setPopupVisible(false); + } + } + }); + + editor.addPropertyChangeListener(NumberEditor.PROPERTY_AUTO_POPUP, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (log.isDebugEnabled()) { + log.debug("set auto popup " + evt.getNewValue() + " for " + editor.getProperty()); + } + if (editor.getPopup().isVisible()) { + setPopupVisible(false); + } + } + }); + + editor.addPropertyChangeListener(PROPERTY_MODEL, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (log.isDebugEnabled()) { + log.debug("set new model " + evt.getNewValue() + " for " + editor.getProperty()); + } + setModel((Number) evt.getOldValue(), (Number) evt.getNewValue()); + } + }); + editor.addPropertyChangeListener(PROPERTY_POPUP_VISIBLE, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + setPopupVisible((Boolean) evt.getNewValue()); + } + }); + editor.getTextField().addMouseListener(new PopupListener()); + + // Initialise le number pattern + if (StringUtils.isNotEmpty(editor.getNumberPattern())) { + numberPattern = Pattern.compile(editor.getNumberPattern()); + } + + // Determine si c'est un float + Class<?> type = editor.getModelType(); + if (editor.getModelType() == null) { + if (editor.getBean() != null) { + type = getGetter().getReturnType(); + } + } + modelType = type; + if (log.isDebugEnabled()) { + log.debug("model type to use = " + modelType); + } + //FIXME le test n'est pas assez fort (on peut avoir un long, short,...) + editor.setUseFloat(!type.equals(Integer.class) && !type.equals(int.class)); + + // Initialise le model + if (editor.getModel() == null) { + if (editor.getBean() != null) { + Number num = (Number) getGetter().invoke(editor.getBean()); + editor.setModel(num); + } + } + + /*if (editor.getResetButton().getIcon() == null) { + editor.getResetButton().setIcon(SwingUtil.createActionIcon("numbereditor-reset")); + } + if (editor.getButton().getIcon() == null) { + editor.getButton().setIcon(SwingUtil.createActionIcon("numbereditor-calculator")); + }*/ + } catch (IllegalAccessException ex) { + log.error(ex); + } catch (IllegalArgumentException ex) { + log.error(ex); + } catch (InvocationTargetException ex) { + log.error(ex); + } + } + + /** + * Affiche ou cache la popup. + * + * @param newValue la nouvelle valeur de visibilité de la popup. + */ + public void setPopupVisible(Boolean newValue) { + + if (log.isTraceEnabled()) { + log.trace(newValue); + } + + if (newValue == null || !newValue) { + editor.getPopup().setVisible(false); + return; + } + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + JComponent invoker = + editor.isShowPopupButton() ? + editor.getShowPopUpButton() : + editor; + Dimension dim = editor.getPopup().getPreferredSize(); + int x = (int) (invoker.getPreferredSize().getWidth() - dim.getWidth()); + editor.getPopup().show(invoker, + x, invoker.getHeight()); + editor.getTextField().requestFocus(); + } + }); + } + + protected String lastValidText; + + /** + * Modifie le modèle de la donnée à éditer à partir d'un evenement clavier + * + * TODO utiliser une filtre sur les donnes en entrees pour ne pas a avoir + * faire les tests ici. + * + * @param s la nouvelle valeur du modèle + */ + public void setModel(String s) { + + String text = editor.getModelText(); + if (text.equals(s)) { + // le modeèle n'a pas changé, rien a faire sur le modèle + if (log.isDebugEnabled()) { + log.debug("modelText is the same, skip !"); + } + return; + } + + if (StringUtils.isNotEmpty(s) && numberPattern != null) { + + // use given number pattern + Matcher matcher = numberPattern.matcher(s); + if (!matcher.matches()) { + + // the current text is not accepted... + if (log.isInfoEnabled()) { + log.info("Does not accept the new number " + s + + ", will reapply lastValidText : " + lastValidText); + } + + String oldText; + if (lastValidText != null) { + + // push back last valid text + oldText = lastValidText; + } else { + oldText = ""; + } + editor.getTextField().setText(oldText); + return; + } + } + + boolean canApply = false; + + boolean endWithDot = false; + + boolean isLess = false; + + Number newValue = null; + + // allow using ',' char + s = s.replaceAll(",", "."); + + if (s.trim().isEmpty()) { + // le champ est vide donc c'est la valeur null a reaffecter + s = null; + canApply = true; + } else if (s.endsWith(".")) { + s += "0"; + endWithDot = true; + } else if (editor.isUseSign() && s.length() == 1 && s.startsWith("-")) { + s = "0"; + isLess = true; + } + + //FIXME tchemit-2014-03-25 Need to bring that bug to commons-lang team + if (s != null && (s.startsWith("0.") && NumberUtils.isNumber(s.substring(1)) || NumberUtils.isNumber(s))) { + + // on a un nombre valide + + try { + Double f = Double.parseDouble(s); + if (!editor.isUseSign() && s.startsWith("-")) { + if (log.isDebugEnabled()) { + log.debug("will skip since can not allow sign on this editor but was " + f); + } + } else { + + if (!editor.isUseFloat() && s.contains(".")) { + if (log.isDebugEnabled()) { + log.debug("will skip since can not allow float on this editor but was " + f); + } + } else { + // ok on peut utilise ce modele + newValue = getRealValue(f); +// if (editor.isUseFloat()) { +// if (getMutator().getParameterTypes()[0] == BigDecimal.class) { +// newValue = BigDecimal.valueOf(f); +// } else { +// newValue = f; +// } +// } else { +// newValue = f.intValue(); +// } + canApply = true; + } + } + + } catch (NumberFormatException e) { + // rien a faire + log.debug(e); + } + } + JTextField field = editor.getTextField(); + + int oldPosition = field.getCaretPosition(); + + if (canApply) { + + if (log.isDebugEnabled()) { + log.debug("can apply new model value : " + newValue); + } + if (isLess) { + editor.setModelText("-"); + return; + } + // on peut mettre a jour le model + editor.setModel(newValue); + if (endWithDot) { + editor.setModelText(s.substring(0, s.length() - 1)); + field.setCaretPosition(oldPosition); + } + + lastValidText = editor.getModelText(); + return; + } + + // on ne peut pas appliquer, on repositionne l'ancien texte + // dans l'éditeur + + if (log.isDebugEnabled()) { + log.debug("invalid text " + s + " reput old text " + text); + } + + field.setText(text); + + lastValidText = text; + if (editor.isSelectAllTextOnError()) { + field.selectAll(); + } else { + if (oldPosition > 0) { + oldPosition--; + } + try { + field.setCaretPosition(oldPosition); + } catch (IllegalArgumentException ex) { + log.debug("CaretPosition is invalid for position : " + oldPosition, ex); + } + } + } + + private Number getRealValue(Double f) { + if (modelType == Integer.class) { + return f.intValue(); + } + if (modelType == Double.class) { + return f; + } + if (modelType == Long.class) { + return f.longValue(); + } + if (modelType == BigInteger.class) { + return new BigInteger(f.longValue() + ""); + } + if (modelType == BigDecimal.class) { + return new BigDecimal(f + ""); + } + if (modelType == Float.class || editor.isUseFloat()) { + return f.floatValue(); + } + return f.intValue(); + } + + /** + * Ajoute le caractère donné à l'endroit où est le curseur dans la zone de + * saisie et met à jour le modèle. + * + * @param s le caractère à ajouter. + */ + public void addChar(String s) { + char c = s.charAt(0); + try { + editor.getTextField().getDocument().insertString(editor.getTextField().getCaretPosition(), c + "", null); + setModel(editor.getTextField().getText()); + //setModel(editor.getModelText() + c); + + } catch (BadLocationException e) { + log.warn(e); + } + } + + /** + * Supprime le caractère juste avant le curseur du modèle (textuel) et + * met à jour la zone de saisie. + */ + public void removeChar() { + String s = editor.getModelText(); + int position = editor.getTextField().getCaretPosition(); + if (position < 1 || s.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("cannot remove when caret on first position or text empty"); + } + // on est au debut du doc, donc rien a faire + return; + } + try { + editor.getTextField().getDocument().remove(position - 1, 1); + } catch (BadLocationException ex) { + // ne devrait jamais arrive vu qu'on a fait le controle... + log.debug(ex); + return; + } + String newText = editor.getTextField().getText(); + if (log.isDebugEnabled()) { + log.debug("text updated : " + newText); + } + position--; + editor.getTextField().setCaretPosition(position); + setModel(newText); + } + + /** + * Permute le signe dans la zone de saisie et + * dans le modèle. + */ + public void toggleSign() { + String newValue = editor.getModelText(); + + if (newValue.startsWith("-")) { + setModel(newValue.substring(1)); + } else { + setModel("-" + newValue); + } + } + + /** @return l'éditeur au quel est rattaché le handler. */ + public NumberEditor getEditor() { + return editor; + } + + protected void setModel(Number oldValue, Number newValue) { + + if (log.isDebugEnabled()) { + log.debug(editor.getProperty() + " on " + editor.getBean().getClass() + " :: " + oldValue + " to " + newValue); + } + + String strValue; + if (newValue == null) { + strValue = ""; + } else { + strValue = newValue + ""; + if (editor.isUseFloat()) { + Float n = Float.parseFloat(strValue); + if ((float) n.intValue() == n) { + strValue = n.intValue() + ""; + } + } + } + + lastValidText = strValue; + editor.setModelText(strValue); + + if (editor.getBean() == null) { + return; + } + + try { + Method mutator = getMutator(); + if (newValue == null && !getAcceptNull()) { + // valeur nulle sur une propriete primitive + // on ne peut pas utiliser la valeur null, mais 0 à la place + newValue = getRealValue(0.0d); +// if (editor.isUseFloat()) { +// if (log.isInfoEnabled()) { +// log.info("use float, check mutator default type = " + mutator.getParameterTypes()[0]); +// } +// if (mutator.getParameterTypes()[0] == BigDecimal.class) { +// newValue = BigDecimal.valueOf(0); +// } else { +// newValue = 0.0f; +//// mutator.invoke(editor.getBean(), 0.0f); +// } +// } else { +// newValue = 0; +//// mutator.invoke(editor.getBean(), 0); +// } + + } //else { +// mutator.invoke(editor.getBean(), newValue); +// } + mutator.invoke(editor.getBean(), newValue); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + protected void validate() { + + setPopupVisible(false); + // fire validate property (to be able to notify listeners) + editor.firePropertyChange(VALIDATE_PROPERTY, null, true); + } + + protected class PopupListener extends MouseAdapter { + + @Override + public void mousePressed(MouseEvent e) { + maybeShowPopup(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + maybeShowPopup(e); + } + + protected void maybeShowPopup(MouseEvent e) { + if (!e.isPopupTrigger()) { + return; + } + if (editor.isAutoPopup()) { + if (editor.isPopupVisible()) { + if (!editor.getPopup().isVisible()) { + setPopupVisible(true); + } + // popup already visible + + } else { + // set popup auto + editor.setPopupVisible(true); + + } + } else { + if (editor.isPopupVisible()) { + setPopupVisible(true); + } + } + } + } + + protected Method getMutator() { + if (mutator == null) { + mutator = BeanUtil.getMutator(editor.getBean(), editor.getProperty()); + } + return mutator; + } + + protected Method getGetter() { + if (getter == null) { + Object bean = editor.getBean(); + if (bean == null) { + throw new NullPointerException("could not find bean in " + editor); + } + String property = editor.getProperty(); + if (property == null) { + throw new NullPointerException("could not find property in " + editor); + } + if (log.isDebugEnabled()) { + log.debug("searching accessor for property " + property + " on bean of type " + bean.getClass()); + } + if (log.isTraceEnabled()) { + PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(bean); + for (PropertyDescriptor p : descriptors) { + log.trace("property discover " + p.getName() + " reader = " + p.getWriteMethod()); + } + } + try { + PropertyDescriptor descriptor = PropertyUtils.getPropertyDescriptor(bean, property); + getter = descriptor.getReadMethod(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + return getter; + } + + public Boolean getAcceptNull() { + if (acceptNull == null) { + Method m = getMutator(); + if (m == null) { + // should never happens + throw new IllegalStateException("could not find the mutator"); + } + Class<?> returnType = m.getParameterTypes()[0]; + acceptNull = !returnType.isPrimitive(); + if (log.isDebugEnabled()) { + log.debug(acceptNull + " for mutator " + m.getName() + " type : " + returnType); + } + } + return acceptNull; + } +} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditorPopup.jcss b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/NumberEditorPopup.jcss similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditorPopup.jcss rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/NumberEditorPopup.jcss diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/SimpleTimeEditor.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/SimpleTimeEditor.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/SimpleTimeEditor.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/SimpleTimeEditor.jaxx diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/SimpleTimeEditor.jcss b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/SimpleTimeEditor.jcss similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/SimpleTimeEditor.jcss rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/SimpleTimeEditor.jcss diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/SimpleTimeEditorHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/SimpleTimeEditorHandler.java new file mode 100644 index 0000000..8602530 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/SimpleTimeEditorHandler.java @@ -0,0 +1,292 @@ +package org.nuiton.jaxx.runtime.swing.editor; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.beans.BeanUtil; + +import javax.swing.JFormattedTextField; +import javax.swing.JSpinner; +import javax.swing.SpinnerDateModel; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Method; +import java.util.Calendar; +import java.util.Date; + +/** + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class SimpleTimeEditorHandler { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(SimpleTimeEditorHandler.class); + + private static final KeyAdapter MOVE_TO_MINUTES_KEY_LISTENER = new KeyAdapter() { + + @Override + public void keyReleased(KeyEvent e) { + JFormattedTextField source = (JFormattedTextField) e.getSource(); + String text = source.getText(); + + // if the user typed 2 digits or if he typed an hour which cannot be the tens digit, + // then transfer the focus to the minute editor (cf #3833) + if (text.length() >= 2 || !text.equals("0") && !text.equals("1") && !text.equals("2")) { + source.transferFocus(); + } + } + + }; + + private final PropertyChangeListener propertyDateChanged; + + private final PropertyChangeListener propertyTimeChanged; + + private final SimpleTimeEditor editor; + + private final SimpleTimeEditorModel model; + + /** the mutator method on the property of boxed bean in the editor */ + protected Method mutator; + + protected final Calendar calendarMinute; + + protected final Calendar calendarHour; + + protected final Calendar calendarDate; + + public SimpleTimeEditorHandler(SimpleTimeEditor editor) { + this.editor = editor; + this.model = editor.getModel(); + this.calendarMinute = Calendar.getInstance(); + this.calendarHour = Calendar.getInstance(); + this.calendarDate = Calendar.getInstance(); + this.propertyDateChanged = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + Date date = (Date) evt.getNewValue(); + + if (date != null) { + calendarDate.setTime(date); + int hours = calendarDate.get(Calendar.HOUR_OF_DAY); + int minutes = calendarDate.get(Calendar.MINUTE); + if (log.isDebugEnabled()) { + log.debug("date changed : new value " + hours + ":" + minutes); + } + model.setTimeModel(hours * 60 + minutes); + + } else { + model.setTimeModel(null); + } + + } + }; + this.propertyTimeChanged = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + Integer time = (Integer) evt.getNewValue(); + + int hours = time / 60; + int minutes = time % 60; + + calendarDate.set(Calendar.HOUR_OF_DAY, hours); + calendarDate.set(Calendar.MINUTE, minutes); + + // push it back into the bean + + Date newValue = calendarDate.getTime(); + + if (log.isDebugEnabled()) { + log.debug(model.getProperty() + " on " + model.getBean().getClass() + " :: " + newValue); + } + + try { + getMutator().invoke(model.getBean(), newValue); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + public void init() { + + if (model.getBean() == null) { + throw new NullPointerException("can not have a null bean in ui " + editor); + } + + editor.getMinute().setEditor(new JSpinner.DateEditor(editor.getMinute(), "mm")); +// editor.getHour().setEditor(new JSpinner.DateEditor(editor.getHour(), "HH")); + + // listen to the typed text and automatically focus the minute when the user typed the hour + JSpinner.DefaultEditor hourEditor = (JSpinner.DefaultEditor) editor.getHour().getEditor(); + hourEditor.getTextField().addKeyListener(MOVE_TO_MINUTES_KEY_LISTENER); + +// TuttiUIUtil.autoSelectOnFocus(minuteEditor.getTextField()); +// JSpinner.NumberEditor hourEditor = (JSpinner.NumberEditor) editor.getHour().getEditor(); +// TuttiUIUtil.autoSelectOnFocus(hourEditor.getTextField()); + + // listen when date changes (should come from outside) + + model.addPropertyChangeListener(SimpleTimeEditorModel.PROPERTY_DATE, propertyDateChanged); + + // When time model change, let's push it back in bean + model.addPropertyChangeListener(SimpleTimeEditorModel.PROPERTY_TIME_MODEL, propertyTimeChanged); + } + + public SimpleTimeEditor getEditor() { + return editor; + } + + protected Date setMinuteModel(Date incomingDate) { + if (incomingDate == null) { + incomingDate = new Date(); + calendarMinute.setTime(incomingDate); + calendarMinute.set(Calendar.HOUR_OF_DAY, 0); + calendarMinute.set(Calendar.MINUTE, 0); + } else { + calendarMinute.setTime(incomingDate); + calendarMinute.set(Calendar.HOUR_OF_DAY, 0); + } + incomingDate = calendarMinute.getTime(); + return incomingDate; + } + + public void updateTimeModelFromHour(Integer hour) { + model.setTimeModel(hour * 60 + model.getMinute()); + } + + public void updateTimeModelFromMinute(Date minuteDate) { + + calendarMinute.setTime(minuteDate); + int newHour = calendarMinute.get(Calendar.HOUR_OF_DAY); + int newMinute = calendarMinute.get(Calendar.MINUTE); + + int oldHour = model.getHour(); + int oldMinute = model.getMinute(); + + if (oldHour == newHour && oldMinute == newMinute) { + + // do nothing, same data + if (log.isDebugEnabled()) { + log.debug("Do not update time model , stay on same time = " + oldHour + ":" + oldMinute); + } + return; + } + + // by default stay on same hour + int hour = oldHour; + + // by default, use the new minute data + + if (log.isDebugEnabled()) { + log.debug("hh:mm (old from dateModel) = " + oldHour + ":" + oldMinute); + log.debug("hh:mm (new from minuteModel) = " + newHour + ":" + newMinute); + } + + SpinnerDateModel minuteModel = editor.getMinuteModel(); + + if (newMinute == 0) { + + // minute pass to zero (check if a new hour is required) + if (newHour == 1) { + + if (oldHour == 23) { + + // can't pass from 23:59 to 0:00, stay on 23:59 + if (log.isDebugEnabled()) { + log.debug("Do not update time model , stay on hh:mm = " + oldHour + ":" + oldMinute); + } + minuteModel.setValue(minuteModel.getPreviousValue()); + return; + } + hour = (oldHour + 1) % 24; + } + } else if (newMinute == 59) { + + // minute pass to 59 (check if a new hour is required) + + if (newHour == 23) { + + if (oldHour == 0) { + + // can't pass from 0:00 to 23:59, stay on 0:00 + if (log.isDebugEnabled()) { + log.debug("Do not update time model , stay on hh:mm = " + oldHour + ":" + oldMinute); + } + minuteModel.setValue(minuteModel.getNextValue()); + return; + } + + // decrease hour + hour = (oldHour - 1) % 24; + } + } + + // date has changed + if (log.isDebugEnabled()) { + log.debug("Update time model to hh:mm = " + hour + ":" + newMinute); + } + model.setTimeModel(hour * 60 + newMinute); + } + + protected void setDate(Date oldValue, Date newValue) { + if (model.getBean() != null) { + + if (log.isDebugEnabled()) { + log.debug(model.getProperty() + " on " + model.getBean().getClass() + " :: " + oldValue + " to " + newValue); + } + + try { + getMutator().invoke(model.getBean(), newValue); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + protected Method getMutator() { + if (mutator == null) { + Object bean = model.getBean(); + if (bean == null) { + throw new NullPointerException("could not find bean in " + editor); + } + String property = model.getProperty(); + if (property == null) { + throw new NullPointerException("could not find property in " + editor); + } + + mutator = BeanUtil.getMutator(bean, property); + } + return mutator; + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/SimpleTimeEditorModel.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/SimpleTimeEditorModel.java new file mode 100644 index 0000000..ea8af6e --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/SimpleTimeEditorModel.java @@ -0,0 +1,109 @@ +package org.nuiton.jaxx.runtime.swing.editor; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.jdesktop.beans.AbstractSerializableBean; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class SimpleTimeEditorModel extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + public static final String PROPERTY_DATE = "date"; + + public static final String PROPERTY_TIME_MODEL = "timeModel"; + + public static final String PROPERTY_PROPERTY = "property"; + + public static final String PROPERTY_BEAN = "bean"; + + /** Bean where to push data. */ + protected Serializable bean; + + /** Property of the bean to use. */ + protected String property; + + /** Time model in minutes. */ + protected Integer timeModel = 0; + + /** Real date which contains the edited time. */ + protected Date date; + + public Serializable getBean() { + return bean; + } + + public void setBean(Serializable bean) { + Object oldValue = getBean(); + this.bean = bean; + firePropertyChange(PROPERTY_BEAN, oldValue, bean); + } + + public String getProperty() { + return property; + } + + public void setProperty(String property) { + Object oldValue = getProperty(); + this.property = property; + firePropertyChange(PROPERTY_PROPERTY, oldValue, property); + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + Object oldValue = getDate(); + this.date = date; + firePropertyChange(PROPERTY_DATE, oldValue, date); + } + + public Integer getTimeModel() { + return timeModel; + } + + public void setTimeModel(Integer timeModel) { + if (timeModel == null) { + timeModel = 0; + } + Object oldValue = getTimeModel(); + this.timeModel = timeModel; + firePropertyChange(PROPERTY_TIME_MODEL, oldValue, timeModel); + } + + public int getMinute() { + return timeModel % 60; + } + + public int getHour() { + return timeModel / 60; + } + +} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditor.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/TimeEditor.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditor.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/TimeEditor.jaxx diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditor.jcss b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/TimeEditor.jcss similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditor.jcss rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/TimeEditor.jcss diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/TimeEditorHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/TimeEditorHandler.java new file mode 100644 index 0000000..0d25c02 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/TimeEditorHandler.java @@ -0,0 +1,329 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.runtime.swing.editor; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JLabel; +import javax.swing.JSlider; +import javax.swing.plaf.basic.BasicSliderUI; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Method; +import java.util.Calendar; +import java.util.Date; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.Map; + +import org.nuiton.util.beans.BeanUtil; + +/** @author Tony Chemit - chemit@codelutin.com */ +public class TimeEditorHandler { + + public static final Log log = LogFactory.getLog(TimeEditorHandler.class); + + public static final String BEAN_PROPERTY = "bean"; + + public static final String PROPERTY_PROPERTY = "property"; + + public static final String DATE_PROPERTY = "date"; + + public static final String TIME_MODEL_PROPERTY = "timeModel"; + + /** editor ui */ + protected TimeEditor editor; + + /** the mutator method on the property of boxed bean in the editor */ + protected Method mutator; + + protected Calendar calendar; + + protected Calendar calendarMinute; + + public TimeEditorHandler(TimeEditor ui) { + editor = ui; + calendar = Calendar.getInstance(); + calendarMinute = Calendar.getInstance(); + } + + public void init() { + + if (editor.getBean() == null) { + throw new NullPointerException("can not have a null bean in ui " + editor); + } + + // create slider labels + Map<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>(); + for (int i = 0; i < 25; i += 2) { + labelTable.put(i * 60, new JLabel(i + "")); + } + JSlider slider = editor.getSlider(); + slider.setLabelTable((Dictionary<?, ?>) labelTable); + + MouseAdapter m = new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + // set the value + int value = getSliderValue(e); + JSlider slider = (JSlider) e.getComponent(); + slider.setValueIsAdjusting(true); + slider.setValue(value); + slider.setValueIsAdjusting(false); + showToolTip(e); + e.consume(); + } + + @Override + public void mouseDragged(MouseEvent e) { + showToolTip(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + showToolTip(e); + } + + @Override + public void mouseMoved(MouseEvent e) { + showToolTip(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + showToolTip(e); + } + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + JSlider slider = (JSlider) e.getComponent(); + + // compute new value + int nb = e.getWheelRotation(); + int value = slider.getValue() - nb; + + // set the value + slider.setValueIsAdjusting(true); + slider.setValue(value); + slider.setValueIsAdjusting(false); + e.consume(); + } + + int getSliderValue(MouseEvent e) { + JSlider slider = (JSlider) e.getSource(); + int value = -1; + if (slider.getUI() instanceof BasicSliderUI) { + BasicSliderUI ui = (BasicSliderUI) slider.getUI(); + value = slider.getOrientation() == JSlider.HORIZONTAL + ? ui.valueForXPosition(e.getX()) + : ui.valueForYPosition(e.getY()); + } + return value; + } + + void showToolTip(MouseEvent e) { + + int value = getSliderValue(e); + if (value == -1) { + return; + } + int h = value / 60; + int m = value % 60; + + String text = ""; + if (h < 10) { + text = "0"; + } + text += h + " : "; + if (m < 10) { + text += "0"; + } + text += m; + + JSlider slider = (JSlider) e.getSource(); + slider.setToolTipText(text); + + } + }; + slider.addMouseListener(m); + slider.addMouseMotionListener(m); + slider.addMouseWheelListener(m); + + // listen when date changes (should come from outside) + editor.addPropertyChangeListener(DATE_PROPERTY, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + Date date = (Date) evt.getNewValue(); + + if (date == null) { + return; + } + calendar.setTime(date); + int hours = calendar.get(Calendar.HOUR_OF_DAY); + int minutes = calendar.get(Calendar.MINUTE); + if (log.isDebugEnabled()) { + log.debug("date changed : new value " + hours + ":" + minutes); + } + getEditor().setTimeModel(hours * 60 + minutes); + } + }); + + // listen when time model changes (should come from editor) + editor.addPropertyChangeListener(TIME_MODEL_PROPERTY, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + Integer time = (Integer) evt.getNewValue(); + int hours = time / 60; + int minutes = time % 60; + calendar.set(Calendar.HOUR_OF_DAY, hours); + calendar.set(Calendar.MINUTE, minutes); + setDate(null, calendar.getTime()); + } + }); + } + + public TimeEditor getEditor() { + return editor; + } + + protected Date setMinuteModel(Date incomingDate) { + if (incomingDate == null) { + incomingDate = new Date(); + } + calendarMinute.setTime(incomingDate); + calendarMinute.set(Calendar.HOUR_OF_DAY, 0); + incomingDate = calendarMinute.getTime(); + return incomingDate; + } + + public int getMinute() { + return getEditor().getTimeModel() % 60; + } + + public int getHour() { + return getEditor().getTimeModel() / 60; + } + + public void updateTimeModelFromMinuteModel(Date minuteDate) { + + calendarMinute.setTime(minuteDate); + int newHour = calendarMinute.get(Calendar.HOUR_OF_DAY); + int newMinute = calendarMinute.get(Calendar.MINUTE); + + int oldHour = getHour(); + int oldMinute = getMinute(); + + if (oldHour == newHour && oldMinute == newMinute) { + + // do nothing, same data + if (log.isDebugEnabled()) { + log.debug("Do not update time model , stay on same time = " + oldHour + ":" + oldMinute); + } + return; + } + + // by default stay on same hour + int hour = oldHour; + + // by default, use the new minute data + + if (log.isDebugEnabled()) { + log.debug("hh:mm (old from dateModel) = " + oldHour + ":" + oldMinute); + log.debug("hh:mm (new from minuteModel) = " + newHour + ":" + newMinute); + } + + if (newMinute == 0) { + + // minute pass to zero (check if a new hour is required) + if (newHour == 1) { + + if (oldHour == 23) { + + // can't pass from 23:59 to 0:00, stay on 23:59 + if (log.isDebugEnabled()) { + log.debug("Do not update time model , stay on hh:mm = " + oldHour + ":" + oldMinute); + } + getEditor().getMinuteModel().setValue(getEditor().getMinuteModel().getPreviousValue()); + return; + } + hour = (oldHour + 1) % 24; + } + } else if (newMinute == 59) { + + // minute pass to 59 (check if a new hour is required) + + if (newHour == 23) { + + if (oldHour == 0) { + + // can't pass from 0:00 to 23:59, stay on 0:00 + if (log.isDebugEnabled()) { + log.debug("Do not update time model , stay on hh:mm = " + oldHour + ":" + oldMinute); + } + getEditor().getMinuteModel().setValue(getEditor().getMinuteModel().getNextValue()); + return; + } + + // decrease hour + hour = (oldHour - 1) % 24; + } + } + + // date has changed + if (log.isDebugEnabled()) { + log.debug("Update time model to hh:mm = " + hour + ":" + newMinute); + } + getEditor().setTimeModel(hour * 60 + newMinute); + } + + protected void setDate(Date oldValue, Date newValue) { + if (editor.getBean() == null) { + return; + } + + if (log.isDebugEnabled()) { + log.debug(editor.getProperty() + " on " + editor.getBean().getClass() + " :: " + oldValue + " to " + newValue); + } + + try { + getMutator().invoke(editor.getBean(), newValue); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + protected Method getMutator() { + if (mutator == null) { + mutator = BeanUtil.getMutator(editor.getBean(), editor.getProperty()); + } + return mutator; + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanComboBox.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanComboBox.jaxx new file mode 100644 index 0000000..b0fb71b --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanComboBox.jaxx @@ -0,0 +1,156 @@ +<!-- + #%L + JAXX :: Widgets + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<Table fill='both' insets='0' genericType='O' + implements='org.nuiton.jaxx.runtime.bean.BeanTypeAware<O>' + onFocusGained='handler.focusCombo()' onFocusLost='hidePopup()'> + + <import> + org.nuiton.jaxx.runtime.swing.model.JaxxDefaultComboBoxModel + org.nuiton.decorator.JXPathDecorator + javax.swing.border.TitledBorder + </import> + + <!-- bean type --> + <Class id='beanType' genericType='O' javaBean='null'/> + + <!-- auto complete property --> + <Boolean id='autoComplete' javaBean='false'/> + + <!-- flag to reverse the sort --> + <Boolean id='reverseSort' javaBean='false'/> + + <!-- show reset property --> + <Boolean id='showReset' javaBean='false'/> + + <!-- show decorator property --> + <Boolean id='showDecorator' javaBean='true'/> + + <!-- editable combo property --> + <Boolean id='editable' javaBean='true'/> + + <!-- sortable combo property --> + <Boolean id='sortable' javaBean='true'/> + + <!-- to transmit focus from table to combo property --> + <Boolean id='autoFocus' javaBean='true'/> + + <!-- bean property linked state --> + <String id='property' javaBean='""'/> + + <!-- model property --> + <Object id='bean' javaBean='null'/> + + <!-- selectedItem property --> + <Object id='selectedItem' javaBean='null'/> + + <!-- sort index property --> + <Integer id='index' javaBean='0'/> + + <!-- datas of the combo-box --> + <java.util.List id='data' genericType='O' javaBean='null'/> + + <Integer id="maximumRowCount" javaBean="null"/> + + <!-- model of sorted property --> + <ButtonGroup id='indexes' + onStateChanged='setIndex((Integer)indexes.getSelectedValue())'/> + + <ButtonGroup id='sortGroup' + onStateChanged='setReverseSort((Boolean)sortGroup.getSelectedValue())'/> + + <!-- ui handler --> + <BeanComboBoxHandler id='handler' genericType='O' constructorParams='this'/> + + <String id='selectedToolTipText' javaBean='null'/> + + <String id='notSelectedToolTipText' javaBean='null'/> + + <String id='popupTitleText' javaBean='null'/> + + <String id='i18nPrefix' javaBean='"entitycombobox.common."'/> + + <!-- popup to change sorted property--> + <JPopupMenu id='popup' + onPopupMenuWillBecomeInvisible='getChangeDecorator().setSelected(false)' + onPopupMenuCanceled='getChangeDecorator().setSelected(false)'> + <JLabel id='popupSortLabel'/> + + <JRadioButtonMenuItem id='sortUp'/> + + <JRadioButtonMenuItem id='sortDown'/> + + <JSeparator id='popupSeparator'/> + <JLabel id='popupLabel'/> + <JSeparator/> + </JPopupMenu> + + <script><![CDATA[ + +public static final String PROPERTY_EMPTY = "empty"; + +public void init(JXPathDecorator<O> decorator, List<O> data) { + handler.init(decorator, data); +} + +protected void hidePopup() { + if (popup.isVisible()) { + popup.setVisible(false); + } +} + +public boolean isEmpty() { return handler.isEmpty(); } + +public void addItem(O item) { handler.addItem(item); } + +public void addItems(Iterable<O> items) { handler.addItems(items); } + +public void removeItem(O item) { handler.removeItem(item); } + +public void removeItems(Iterable<O> items) { handler.removeItems(items); } + +public JaxxDefaultComboBoxModel<O> getComboBoxModel() { return (JaxxDefaultComboBoxModel<O>) combobox.getModel(); } + +]]> + </script> + <row> + <cell anchor='west'> + <!-- le boutton pour reinitialiser la valeur sélectionnée --> + <JToolBar id='toolbarLeft'> + <JButton id='resetButton' onActionPerformed='setSelectedItem(null)'/> + </JToolBar> + + </cell> + <cell weightx='1'> + <!-- la liste déroulante --> + <JComboBox id='combobox' + onFocusGained='hidePopup()'/> + </cell> + <cell anchor='east' fill='both' insets='0'> + <!-- le boutton pour changer le tri --> + <JToolBar id='toolbarRight'> + <JToggleButton id='changeDecorator' + onActionPerformed='getHandler().togglePopup()'/> + </JToolBar> + </cell> + </row> +</Table> diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanComboBox.jcss b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanComboBox.jcss similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanComboBox.jcss rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanComboBox.jcss diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanComboBoxHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanComboBoxHandler.java new file mode 100644 index 0000000..037e280 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanComboBoxHandler.java @@ -0,0 +1,556 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.runtime.swing.editor.bean; + +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.swing.JAXXButtonGroup; +import org.nuiton.jaxx.runtime.swing.renderer.DecoratorListCellRenderer; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.autocomplete.ObjectToStringConverter; +import org.nuiton.decorator.DecoratorUtil; +import org.nuiton.decorator.JXPathDecorator; +import org.nuiton.decorator.MultiJXPathDecorator; +import org.nuiton.util.beans.BeanUtil; + +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JPopupMenu; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; + +/** + * Le handler d'un {@link BeanComboBox}. + * + * Note: ce handler n'est pas stateless et n'est donc pas partageable entre plusieurs ui. + * + * @param <O> le type des objet contenus dans le modèle du composant. + * @author Tony Chemit - chemit@codelutin.com + * @see BeanComboBox + */ +public class BeanComboBoxHandler<O> implements PropertyChangeListener { + + public static final Log log = LogFactory.getLog(BeanComboBoxHandler.class); + + /** ui if the handler */ + protected BeanComboBox<O> ui; + + /** the mutator method on the property of boxed bean in the ui */ + protected Method mutator; + + /** the original document of the combbo box editor (keep it to make possible undecorate) */ + protected Document originalDocument; + + /** the convertor used to auto-complete */ + protected ObjectToStringConverter convertor; + + /** the decorator of data */ + protected MultiJXPathDecorator<O> decorator; + + protected boolean init; + + public BeanComboBoxHandler(BeanComboBox<O> ui) { + this.ui = ui; + } + + protected final FocusListener EDITOR_TEXT_COMP0NENT_FOCUSLISTENER = new FocusListener() { + + @Override + public void focusGained(FocusEvent e) { + if (log.isDebugEnabled()) { + log.debug("close popup from " + e); + } + ui.getPopup().setVisible(false); + } + + @Override + public void focusLost(FocusEvent e) { + } + }; + + private final BeanUIUtil.PopupHandler popupHandler = new BeanUIUtil.PopupHandler() { + + @Override + public JPopupMenu getPopup() { + return ui.getPopup(); + } + + @Override + public JComponent getInvoker() { + return ui.getChangeDecorator(); + } + }; + + /** + * Initialise le handler de l'ui + * + * @param decorator le decorateur a utiliser + * @param data la liste des données a gérer + */ + public void init(JXPathDecorator<O> decorator, List<O> data) { + + if (init) { + throw new IllegalStateException("can not init the handler twice"); + } + init = true; + + if (decorator == null) { + throw new NullPointerException("decorator can not be null (for type " + ui.getBeanType() + ")"); + } + + JAXXButtonGroup indexes = ui.getIndexes(); + + this.decorator = BeanUIUtil.createDecorator(decorator); + + final JComboBox combobox = ui.getCombobox(); + + // init combobox renderer base on given decorator + combobox.setRenderer(new DecoratorListCellRenderer(this.decorator)); + combobox.addPopupMenuListener(new PopupMenuListener() { + + private O selectedItem; + + boolean canceled = false; + + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + selectedItem = (O) combobox.getSelectedItem(); + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + O newSelectedItem = (O) combobox.getSelectedItem(); + if (canceled) { + ui.setSelectedItem(null); + + } else if ((newSelectedItem == null ^ selectedItem == null) + || (newSelectedItem != null + && !selectedItem.equals(newSelectedItem))) { + ui.setSelectedItem(newSelectedItem); + } + selectedItem = null; + canceled = false; + } + + public void popupMenuCanceled(PopupMenuEvent e) { + canceled = true; + } + }); + + convertor = BeanUIUtil.newDecoratedObjectToStringConverter(this.decorator); + + // keep a trace of original document (to make possible reverse autom-complete) + JTextComponent editorComponent = (JTextComponent) combobox.getEditor().getEditorComponent(); + originalDocument = editorComponent.getDocument(); + + // build popup + popupHandler.preparePopup(ui.getSelectedToolTipText(), + ui.getNotSelectedToolTipText(), + ui.getI18nPrefix(), + ui.getPopupTitleText(), + indexes, + ui.getPopupSeparator(), + ui.getPopupLabel(), + ui.getSortUp(), + ui.getSortDown(), + this.decorator); + + ui.autoComplete = true; + + ui.addPropertyChangeListener(this); + + // set datas + ui.setData(data); + + // select sort button + indexes.setSelectedButton(ui.getIndex()); + } + + /** Toggle the popup visible state. */ + public void togglePopup() { + popupHandler.togglePopup(); + } + + /** + * @return {@code true} if there is no data in comboBox, + * {@code false} otherwise. + * @since 2.5.9 + */ + public boolean isEmpty() { + return CollectionUtils.isEmpty(ui.getData()); + } + + /** + * Add the given items into the comboBox. + * + * <strong>Note:</strong> The item will be inserted at his correct following + * the selected ordering. + * + * @param items items to add in comboBox. + * @since 2.5.28 + */ + public void addItems(Iterable<O> items) { + + List<O> data = ui.getData(); + + boolean wasEmpty = CollectionUtils.isEmpty(data); + + for (O item : items) { + data.add(item); + } + + updateUI(ui.getIndex(), ui.isReverseSort()); + + fireEmpty(wasEmpty); + } + + /** + * Remove the given items from the comboBox model. + * + * <strong>Note:</strong> If this item was selected, then selection will be + * cleared. + * + * @param items items to remove from the comboBox model + * @since 2.5.28 + */ + public void removeItems(Iterable<O> items) { + + List<O> data = ui.getData(); + + boolean needUpdate = false; + for (O item : items) { + boolean remove = data.remove(item); + + if (remove) { + + // item was found in data + + Object selectedItem = ui.getSelectedItem(); + if (item == selectedItem) { + + // item was selected item, reset selected item then + ui.setSelectedItem(null); + } + + needUpdate = true; + + } + } + + if (needUpdate) { + + updateUI(ui.getIndex(), ui.isReverseSort()); + fireEmpty(false); + } + + } + + /** + * Add the given item into the comboBox. + * + * <strong>Note:</strong> The item will be inserted at his correct following + * the selected ordering. + * + * @param item item to add in comboBox. + * @since 2.5.9 + */ + public void addItem(O item) { + + addItems(Collections.singleton(item)); + } + + /** + * Remove the given item from the comboBox model. + * + * <strong>Note:</strong> If this item was selected, then selection will be + * cleared. + * + * @param item the item to remove from the comboBox model + * @since 2.5.9 + */ + public void removeItem(O item) { + + removeItems(Collections.singleton(item)); + } + + /** + * Sort data of the model. + * + * @since 2.5.10 + */ + public void sortData() { + + // just update UI should do the math of this + updateUI(ui.getIndex(), ui.isReverseSort()); + } + + /** + * Focus combo only if autoFocus ui property is on. + * + * @since 2.8.5 + */ + public void focusCombo() { + if (ui.isAutoFocus()) { + ui.combobox.requestFocusInWindow(); + } + } + + /** + * Modifie l'état autoComplete de l'ui. + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + protected void setAutoComplete(Boolean oldValue, Boolean newValue) { + oldValue = oldValue != null && oldValue; + newValue = newValue != null && newValue; + if (oldValue.equals(newValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("autocomplete state : <" + oldValue + " to " + newValue + ">"); + } + if (!newValue) { + JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); + editorComponent.removeFocusListener(EDITOR_TEXT_COMP0NENT_FOCUSLISTENER); + BeanUIUtil.undecorate(ui.getCombobox(), originalDocument); + } else { + BeanUIUtil.decorate(ui.getCombobox(), convertor); + JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); + editorComponent.addFocusListener(EDITOR_TEXT_COMP0NENT_FOCUSLISTENER); + } + } + + /** + * Modifie l'index du décorateur + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + protected void setIndex(Integer oldValue, Integer newValue) { + if (newValue == null || newValue.equals(oldValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("check state : <" + oldValue + " to " + newValue + ">"); + } + updateUI(newValue, ui.isReverseSort()); + } + + /** + * Modifie l'index du décorateur + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + + protected void setSortOrder(Boolean oldValue, Boolean newValue) { + + if (newValue == null || newValue.equals(oldValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("check state : <" + oldValue + " to " + newValue + ">"); + } + + updateUI(ui.getIndex(), newValue); + } + + protected void updateUI(int index, boolean reversesort) { + + // change decorator context + decorator.setContextIndex(index); + + // keep selected item + Object previousSelectedItem = ui.getSelectedItem(); + Boolean wasAutoComplete = ui.isAutoComplete(); + + if (wasAutoComplete) { + ui.setAutoComplete(false); + } + + // remove autocomplete + if (previousSelectedItem != null) { + ui.getCombobox().setSelectedItem(null); + ui.selectedItem = null; + } + + List<O> data = ui.getData(); + if (ui.isSortable()) { + try { + // Sort data with the decorator jxpath tokens. + DecoratorUtil.sort(decorator, + data, + index, + reversesort); + + } catch (Exception eee) { + log.warn(eee.getMessage(), eee); + } + } + + // reload the model + SwingUtil.fillComboBox(ui.getCombobox(), data, null); + + if (wasAutoComplete) { + ui.setAutoComplete(true); + } + + if (previousSelectedItem != null) { + ui.setSelectedItem(previousSelectedItem); + } + + ui.getCombobox().requestFocus(); + } + + /** + * Modifie la valeur sélectionnée dans la liste déroulante. + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + protected void setSelectedItem(O oldValue, O newValue) { + if (ui.getBean() == null) { + return; + } + + if (newValue == null) { + if (ui.getCombobox().getSelectedItem() == null) { + return; + } + ui.getCombobox().setSelectedItem(null); + + if (ui.isAutoComplete()) { + ui.setAutoComplete(false); + ui.setAutoComplete(true); + } + + if (oldValue == null) { + return; + } + } + if (log.isDebugEnabled()) { + log.debug(ui.getProperty() + " on " + getBeanType() + " :: " + oldValue + " to " + newValue); + } + + BeanUIUtil.invokeMethod(getMutator(), ui.getBean(), (O) newValue); + } + + /** @return le document de l'éditeur avant complétion. */ + public Document getOriginalDocument() { + return originalDocument; + } + + public MultiJXPathDecorator<O> getDecorator() { + return decorator; + } + + /** + * @return get the type of objects contained in the comboBox model. + * @since 2.5.9 + */ + public Class<O> getBeanType() { + Class<O> result = ui.getBeanType(); + if (result == null) { + result = decorator == null ? null : decorator.getType(); + } + return result; + } + + /** + * Obtain the type of objects contained in the comboBox using the model mutator. + * + * @return get the type of objects contained in the comboBox model. + * @deprecated since 2.5.9 (use now method {@link #getBeanType()}) + */ + @Deprecated + public Class<?> getTargetClass() { + Method m = getMutator(); + return m == null ? null : m.getParameterTypes()[0]; + } + + /** @return le mutateur a utiliser pour modifier le bean associé. */ + protected Method getMutator() { + if (mutator == null && ui.getBean() != null && ui.getProperty() != null) { + mutator = BeanUtil.getMutator(ui.getBean(), ui.getProperty()); + } + return mutator; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + String propertyName = evt.getPropertyName(); + + if (BeanComboBox.PROPERTY_SELECTED_ITEM.equals(propertyName)) { + setSelectedItem((O) evt.getOldValue(), (O) evt.getNewValue()); + return; + } + + if (BeanComboBox.PROPERTY_AUTO_COMPLETE.equals(propertyName)) { + + setAutoComplete((Boolean) evt.getOldValue(), + (Boolean) evt.getNewValue()); + return; + } + + if (BeanListHeader.PROPERTY_INDEX.equals(propertyName)) { + + // decorator index has changed, force reload of data in ui + setIndex((Integer) evt.getOldValue(), + (Integer) evt.getNewValue()); + return; + } + + if (BeanListHeader.PROPERTY_REVERSE_SORT.equals(propertyName)) { + + // sort order has changed, force reload of data in ui + setSortOrder((Boolean) evt.getOldValue(), + (Boolean) evt.getNewValue()); + return; + } + + if (BeanListHeader.PROPERTY_DATA.equals(propertyName)) { + + // list has changed, force reload of index + setIndex(-1, ui.getIndex()); + + // list has changed, fire empty property + List list = (List) evt.getOldValue(); + fireEmpty(CollectionUtils.isEmpty(list)); + } + } + + protected void fireEmpty(boolean wasEmpty) { + ui.firePropertyChange(BeanComboBox.PROPERTY_EMPTY, wasEmpty, + isEmpty()); + } + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanDoubleList.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanDoubleList.jaxx new file mode 100644 index 0000000..7035f6e --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanDoubleList.jaxx @@ -0,0 +1,164 @@ +<!-- + #%L + JAXX :: Widgets + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Table genericType='O' implements='org.nuiton.jaxx.runtime.bean.BeanTypeAware<O>'> + + <import> + org.nuiton.decorator.JXPathDecorator + </import> + + <!-- filterable list property --> + <Boolean id='filterable' javaBean='true'/> + + <!-- flag to reverse the sort --> + <Boolean id='reverseSort' javaBean='false'/> + + <!-- show decorator property --> + <Boolean id='showDecorator' javaBean='true'/> + + <!-- show reset property --> + <Boolean id='showReset' javaBean='true'/> + + <!-- to be able to select a same entry more than one time property --> + <Boolean id='useMultiSelect' javaBean='false'/> + + <!-- show showSelectPopupEnabled property --> + <Boolean id='showSelectPopupEnabled' javaBean='true'/> + + <!-- show highlightFilterText property --> + <Boolean id='highlightFilterText' javaBean='false'/> + + <!-- bean type --> + <Class id='beanType' genericType='O' javaBean='null'/> + + <!-- bean property linked state --> + <String id='property' javaBean='""'/> + + <!-- bean property --> + <Object id='bean' javaBean='null'/> + + <String id='i18nPrefix' javaBean='"beanlist.common."'/> + + <!-- model --> + <BeanDoubleListModel id='model' genericType='O' javaBean='new BeanDoubleListModel<O>()'/> + + <!-- handler --> + <BeanDoubleListHandler id='handler' genericType='O' constructorParams='this'/> + + <!-- sort index property --> + <Integer id='index' javaBean='0'/> + + <!-- model of sorted property --> + <ButtonGroup id='indexes' + onStateChanged='setIndex((Integer)indexes.getSelectedValue())'/> + + <ButtonGroup id='sortGroup' + onStateChanged='setReverseSort((Boolean)sortGroup.getSelectedValue())'/> + + <!-- popup to change sorted property--> + <JPopupMenu id='popup' + onPopupMenuWillBecomeInvisible='getChangeDecorator().setSelected(false)' + onPopupMenuCanceled='getChangeDecorator().setSelected(false)'> + <JLabel id='popupSortLabel'/> + + <JRadioButtonMenuItem id='sortUp'/> + + <JRadioButtonMenuItem id='sortDown'/> + + <JSeparator id='popupSeparator'/> + <JLabel id='popupLabel'/> + <JSeparator/> + </JPopupMenu> + + <!-- popup on the selected list --> + <JPopupMenu id='selectedListPopup'> + <JMenuItem id='selectedListMoveUpAction' + onActionPerformed='handler.moveUpSelected( (O) selectedList.getSelectedValue())'/> + <JMenuItem id='selectedListMoveDownAction' + onActionPerformed='handler.moveDownSelected( (O) selectedList.getSelectedValue())'/> + <JMenuItem id='selectedListRemoveAction' + onActionPerformed='model.removeFromSelected( (O) selectedList.getSelectedValue())'/> + </JPopupMenu> + + <row> + <cell columns='3' fill='both'> + <JPanel layout='{new BorderLayout()}' id='beforeFilterPanel'/> + </cell> + </row> + <row> + <cell columns='3' fill='both'> + <JPanel layout='{new BorderLayout()}' id='filterPanel'> + <JPanel layout='{new BorderLayout()}' constraints='BorderLayout.WEST'> + <JLabel id='filterFieldLabel' constraints='BorderLayout.WEST'/> + <JToolBar id='toolbarLeft' constraints='BorderLayout.EAST'> + <JButton id='resetButton' onActionPerformed='filterField.setText("")'/> + </JToolBar> + </JPanel> + <JTextField id='filterField' constraints='BorderLayout.CENTER'/> + <JToolBar id='toolbarRight' constraints='BorderLayout.EAST'> + <JToggleButton id='changeDecorator' + onActionPerformed='getHandler().togglePopup()'/> + </JToolBar> + </JPanel> + </cell> + </row> + <row> + <cell weightx='0.5' weighty='1' fill='both'> + <JScrollPane onFocusGained='universeList.requestFocus()'> + <!-- List of all the remaining available elements --> + <JList id='universeList' + onFocusGained='handler.selectFirstRowIfNoSelection(event)' + onMouseClicked='handler.onUniverseListClicked(event)' + onKeyPressed='handler.onKeyPressedOnUniverseList(event)'/> + </JScrollPane> + </cell> + + <cell anchor='north'> + <JPanel layout='{new GridLayout(0,1)}'> + <JButton id='addButton' onActionPerformed='handler.select()'/> + <JButton id='removeButton' onActionPerformed='handler.unselect()'/> + </JPanel> + </cell> + + <cell weightx='0.5' weighty='1' fill='both'> + <JScrollPane onFocusGained='selectedList.requestFocus()'> + <!-- List of the selected elements --> + <JList id='selectedList' + onFocusGained='handler.selectFirstRowIfNoSelection(event)' + onMouseClicked='handler.onSelectedListClicked(event)' + onKeyPressed='handler.onKeyPressedOnSelectedList(event)'/> + </JScrollPane> + </cell> + </row> + + <script><![CDATA[ + +public void init(JXPathDecorator<O> decorator, JXPathDecorator<O> decorator2, List<O> universe, List<O> selected) { + handler.init(decorator, decorator2, universe, selected); + } + +public void init(JXPathDecorator<O> decorator, List<O> universe, List<O> selected) { + handler.init(decorator, universe, selected); +} + +]]></script> + +</Table> diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanDoubleList.jcss b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanDoubleList.jcss similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanDoubleList.jcss rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanDoubleList.jcss diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanDoubleListHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanDoubleListHandler.java new file mode 100644 index 0000000..719ac02 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanDoubleListHandler.java @@ -0,0 +1,565 @@ +package org.nuiton.jaxx.runtime.swing.editor.bean; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Predicate; +import com.google.common.collect.Lists; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.swing.JAXXButtonGroup; +import org.nuiton.jaxx.runtime.swing.model.JaxxDefaultListModel; +import org.nuiton.jaxx.runtime.swing.model.JaxxFilterableListModel; +import org.nuiton.jaxx.runtime.swing.renderer.DecoratorListCellRenderer; +import org.nuiton.jaxx.runtime.swing.renderer.FilteredDecoratorListCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.decorator.DecoratorUtil; +import org.nuiton.decorator.JXPathDecorator; +import org.nuiton.decorator.MultiJXPathDecorator; +import org.nuiton.util.beans.BeanUtil; + +import javax.swing.AbstractButton; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JPopupMenu; +import javax.swing.ListSelectionModel; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; + +/** + * The handler of a {@link BeanDoubleList}. + * + * + * @param <O> the type of the objects contained in the list. + * @author Kevin Morin - kmorin@codelutin.com + * @see BeanDoubleList + * @since 2.5.8 + */ +public class BeanDoubleListHandler<O> implements PropertyChangeListener { + + private static final Log log = LogFactory.getLog(BeanDoubleListHandler.class); + + /** the mutator method on the property of boxed bean in the ui */ + protected Method mutator; + + /** ui of the handler */ + protected BeanDoubleList<O> ui; + + /** the decorator of data */ + protected MultiJXPathDecorator<O> decorator; + + public BeanDoubleListHandler(BeanDoubleList<O> ui) { + this.ui = ui; + } + + private final BeanUIUtil.PopupHandler popupHandler = new BeanUIUtil.PopupHandler() { + + @Override + public JPopupMenu getPopup() { + return ui.getPopup(); + } + + @Override + public JComponent getInvoker() { + return ui.getChangeDecorator(); + } + }; + + public JPopupMenu getSelectedListPopup(boolean showIt) { + JPopupMenu result; + if (showIt) { + result = ui.getSelectedListPopup(); + } else { + result = null; + } + return result; + } + + /** + * Initializes the handler of the UI + * + * @param decorator the decorator to use to display the data nicely + * @param universe the list of all the available items + * @param selected the list of selected items + */ + public void init(JXPathDecorator<O> decorator, List<O> universe, List<O> selected) { + init(decorator, decorator, universe, selected); + } + /** + * Initializes the handler of the UI + * + * @param decorator the decorator to use to display the data nicely + * @param decorator2 the selected decorator to use to display the selected data nicely (if none, then reuse the first one) + * @param universe the list of all the available items + * @param selected the list of selected items + */ + public void init(JXPathDecorator<O> decorator,JXPathDecorator<O> decorator2, List<O> universe, List<O> selected) { + + if (decorator == null) { + throw new NullPointerException("decorator can not be null (for type " + ui.getBeanType() + ")"); + } + + this.decorator = BeanUIUtil.createDecorator(decorator); + + final BeanDoubleListModel<O> uiModel = ui.getModel(); + + // make sure useMultiSelect is set before filling universe and select lists + uiModel.setUseMultiSelect(ui.getUseMultiSelect()); + + uiModel.setUniverse(universe); + uiModel.setSelected(selected); + + JList universeList = ui.getUniverseList(); + final JList selectedList = ui.getSelectedList(); + + uiModel.addCanRemoveItemsPredicate(new Predicate<List<O>>() { + + @Override + public boolean apply(List<O> o) { + return !o.isEmpty(); + } + }); + + final FilteredDecoratorListCellRenderer universeListCellRenderer + = new FilteredDecoratorListCellRenderer(this.decorator); + universeList.setCellRenderer(universeListCellRenderer); + + if (decorator2 != null) { + decorator2 = BeanUIUtil.createDecorator(decorator2); + } else { + decorator2 = this.decorator; + } + selectedList.setCellRenderer(new DecoratorListCellRenderer(decorator2)); + + // When universe list selection model changed, update the add button enabled property + universeList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + ListSelectionModel source = (ListSelectionModel) e.getSource(); + uiModel.setAddEnabled(!source.isSelectionEmpty()); + } + }); + + // When selected list selection model changed, update the add button enabled property + selectedList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + if (!e.getValueIsAdjusting()) { + recomputeButtonStates(); + } + } + }); + + // When selected list model changed, push back selected list to bean + selectedList.getModel().addListDataListener(new ListDataListener() { + + @Override + public void intervalAdded(ListDataEvent e) { + fireSelectionUpdate(); + } + + @Override + public void intervalRemoved(ListDataEvent e) { + fireSelectionUpdate(); + } + + @Override + public void contentsChanged(ListDataEvent e) { + fireSelectionUpdate(); + } + }); + + JAXXButtonGroup indexes = ui.getIndexes(); + + // build popup + popupHandler.preparePopup(null, + null, + ui.getI18nPrefix(), + null, + indexes, + ui.getPopupSeparator(), + ui.getPopupLabel(), + ui.getSortUp(), + ui.getSortDown(), + this.decorator); + + ui.addPropertyChangeListener(this); + + final JaxxFilterableListModel<O> filterModel = (JaxxFilterableListModel) uiModel.getUniverseModel(); + + filterModel.setDecorator(this.decorator); + + ui.getFilterField().getDocument().addDocumentListener(new DocumentListener() { + + @Override + public void insertUpdate(DocumentEvent e) { + String text = ui.getFilterField().getText(); + universeListCellRenderer.setFilterText(text); + filterModel.setFilterText(text); + } + + @Override + public void removeUpdate(DocumentEvent e) { + String text = ui.getFilterField().getText(); + universeListCellRenderer.setFilterText(text); + filterModel.setFilterText(text); + } + + @Override + public void changedUpdate(DocumentEvent e) { + String text = ui.getFilterField().getText(); + universeListCellRenderer.setFilterText(text); + filterModel.setFilterText(text); + } + }); + + // select sort button + indexes.setSelectedButton(ui.getIndex()); + + sortData(); + + // force to reload the showSelectPopup binding + ui.processDataBinding(BeanDoubleList.BINDING_SELECTED_LIST_COMPONENT_POPUP_MENU); + } + + public void recomputeButtonStates() { + JList selectedList = ui.getSelectedList(); + BeanDoubleListModel<O> uiModel = ui.getModel(); + + List<O> selectedItems = (List<O>) Lists.newArrayList(selectedList.getSelectedValues()); + boolean removeEnabled = uiModel.computeRemoveEnabled(selectedItems); + + ListSelectionModel selectionModel = selectedList.getSelectionModel(); + int minSelectionIndex = selectionModel.getMinSelectionIndex(); + int maxSelectionIndex = selectionModel.getMaxSelectionIndex(); + + boolean oneSelection = minSelectionIndex == maxSelectionIndex; + + boolean upEnabled = removeEnabled && + oneSelection && + minSelectionIndex > 0; + uiModel.setSelectedUpEnabled(upEnabled); + + boolean downEnabled = removeEnabled && + oneSelection && + minSelectionIndex + 1 < uiModel.getSelectedListSize(); + uiModel.setSelectedDownEnabled(downEnabled); + } + + public void setUniverse(List<O> selection) { + ui.getModel().setUniverse(selection); + sortData(); + } + + public void setSelected(List<O> selection) { + ui.getModel().setSelected(selection); + sortData(); + } + + /** Toggle the popup visible state. */ + public void togglePopup() { + popupHandler.togglePopup(); + } + + /** + * Sort data of the model. + * + * @since 2.5.10 + */ + public void sortData() { + + // just update UI should do the math of this + updateUI(ui.getIndex(), ui.isReverseSort()); + } + + /** + * Move up a selected item. + * + * @param item the selected item + * @since 2.5.26 + */ + public void moveUpSelected(O item) { + ui.getModel().moveUpSelected(item); + ui.getSelectedList().setSelectedValue(item, true); + } + + /** + * Move down a selected item. + * + * @param item the selected item + * @since 2.5.26 + */ + public void moveDownSelected(O item) { + ui.getModel().moveDownSelected(item); + ui.getSelectedList().setSelectedValue(item, true); + } + + /** + * Modifie l'index du décorateur + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + protected void setIndex(Integer oldValue, Integer newValue) { + if (newValue == null || newValue.equals(oldValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("check state : <" + oldValue + " to " + newValue + ">"); + } + AbstractButton button = ui.getIndexes().getButton(newValue); + if (button != null) { + button.setSelected(true); + } + updateUI(newValue, ui.isReverseSort()); + } + + /** + * Modifie l'index du décorateur + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + + protected void setSortOrder(Boolean oldValue, Boolean newValue) { + + if (newValue == null || newValue.equals(oldValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("check state : <" + oldValue + " to " + newValue + ">"); + } + + updateUI(ui.getIndex(), newValue); + } + + protected void setHighlightFilterText(Boolean newValue) { + FilteredDecoratorListCellRenderer universeListCellRenderer = + (FilteredDecoratorListCellRenderer) ui.getUniverseList().getCellRenderer(); + universeListCellRenderer.setHighlightFilterText(newValue); + ui.getUniverseList().repaint(); + } + + protected void updateUI(int index, boolean reversesort) { + + // change decorator context + decorator.setContextIndex(index); + + List<O> data = (List<O>) Arrays.asList(((JaxxDefaultListModel<O>) ui.getModel().getUniverseModel()).toArray()); + try { + // Sort data with the decorator jxpath tokens. + DecoratorUtil.sort(decorator, + data, + index, + reversesort + ); + + } catch (Exception eee) { + log.warn(eee.getMessage(), eee); + } + + // reload the model + SwingUtil.fillList(ui.getUniverseList(), data, null); + + ui.getUniverseList().requestFocus(); + } + + /** + * When universe list was double clicked, move selected items to selected list. + * + * @param event mouse event + */ + public void onUniverseListClicked(MouseEvent event) { + JList universeList = ui.getUniverseList(); + if (event.getClickCount() == 2) { + int index = universeList.locationToIndex(event.getPoint()); + if (index < 0) { + return; + } + if (!ui.getModel().isAddEnabled()) { + return; + } + O item = (O) universeList.getModel().getElementAt(index); + ui.getModel().addToSelected(item); + + sortData(); + } + } + + /** + * When selected list was double clicked, move selected items to universe list. + * + * @param event mouse event + */ + public void onSelectedListClicked(MouseEvent event) { + + JList selectedList = ui.getSelectedList(); + + if (event.getClickCount() == 2) { + int index = selectedList.locationToIndex(event.getPoint()); + if (index < 0) { + return; + } + if (!ui.getModel().isRemoveEnabled()) { + return; + } + O item = (O) selectedList.getModel().getElementAt(index); + ui.getModel().removeFromSelected(item); + + sortData(); + } + } + + /** When add button was hit, move selected items (from universe list) to selected list. */ + public void select() { + List<O> selection = (List<O>) Arrays.asList(ui.getUniverseList().getSelectedValues()); + ui.getModel().addToSelected(selection); + ui.getUniverseList().clearSelection(); + + sortData(); + } + + /** When remove button was hit, move selected items (from selected list) to universe list. */ + public void unselect() { + List<O> selection = (List<O>) Arrays.asList(ui.getSelectedList().getSelectedValues()); + ui.getModel().removeFromSelected(selection); + ui.getSelectedList().clearSelection(); + + sortData(); + } + + protected void fireSelectionUpdate() { + if (ui.getBean() != null) { + BeanUIUtil.invokeMethod(getMutator(), + ui.getBean(), + ui.getModel().getSelected()); + } + } + + public Method getMutator() { + if (mutator == null && ui.getBackground() != null && ui.getProperty() != null) { + mutator = BeanUtil.getMutator(ui.getBean(), ui.getProperty()); + } + return mutator; + } + + public MultiJXPathDecorator<O> getDecorator() { + return decorator; + } + + /** + * @return get the type of objects contained in the comboBox model. + * @since 2.5.9 + */ + public Class<O> getBeanType() { + Class<O> result = ui.getBeanType(); + if (result == null) { + result = decorator == null ? null : decorator.getType(); + } + return result; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + String propertyName = evt.getPropertyName(); + + if (BeanListHeader.PROPERTY_INDEX.equals(propertyName)) { + + // decorator index has changed, force reload of data in ui + setIndex((Integer) evt.getOldValue(), + (Integer) evt.getNewValue()); + + } else if (BeanDoubleList.PROPERTY_REVERSE_SORT.equals(propertyName)) { + + // sort order has changed, force reload of data in ui + setSortOrder((Boolean) evt.getOldValue(), + (Boolean) evt.getNewValue()); + + } else if (BeanDoubleList.PROPERTY_HIGHLIGHT_FILTER_TEXT.equals(propertyName)) { + + setHighlightFilterText((Boolean) evt.getNewValue()); + } else if (BeanDoubleList.PROPERTY_USE_MULTI_SELECT.equals(propertyName)) { + + ui.getModel().setUseMultiSelect((Boolean) evt.getNewValue()); + } + } + + public void addFilter(Predicate<O> filter) { + ((JaxxFilterableListModel) ui.getModel().getUniverseModel()).addFilter(filter); + } + + public void removeFilter(Predicate<O> filter) { + ((JaxxFilterableListModel) ui.getModel().getUniverseModel()).removeFilter(filter); + } + + public void clearFilters() { + ((JaxxFilterableListModel) ui.getModel().getUniverseModel()).clearFilters(); + } + + public void refreshFilteredElements() { + ((JaxxFilterableListModel) ui.getModel().getUniverseModel()).refreshFilteredElements(); + } + + public void onKeyPressedOnUniverseList(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + int lastIndice = ui.getUniverseList().getSelectionModel().getLeadSelectionIndex(); + select(); + JList source = (JList) e.getSource(); + if (source.getModel().getSize() > 0) { + source.setSelectedIndex(Math.min(lastIndice, source.getModel().getSize() - 1)); + } else { + ui.getSelectedList().requestFocus(); + } + } + } + + public void onKeyPressedOnSelectedList(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_DELETE) { + int lastIndice = ui.getSelectedList().getSelectionModel().getLeadSelectionIndex(); + unselect(); + JList source = (JList) e.getSource(); + if (source.getModel().getSize() > 0) { + source.setSelectedIndex(Math.min(lastIndice, source.getModel().getSize() - 1)); + ui.getSelectedList().requestFocus(); + } + } + } + + public void selectFirstRowIfNoSelection(FocusEvent event) { + JList list = (JList) event.getSource(); + if (list.isSelectionEmpty()) { + list.setSelectedIndex(0); + } + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanDoubleListModel.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanDoubleListModel.java new file mode 100644 index 0000000..bdead8c --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanDoubleListModel.java @@ -0,0 +1,350 @@ +package org.nuiton.jaxx.runtime.swing.editor.bean; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Predicate; +import com.google.common.collect.Lists; +import org.nuiton.jaxx.runtime.swing.model.JaxxDefaultListModel; +import org.nuiton.jaxx.runtime.swing.model.JaxxFilterableListModel; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.beans.AbstractSerializableBean; + +import javax.swing.ListModel; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +/** + * The model of the {@link BeanDoubleList} widget + * + * @param <O> the type of the object in the list + * @author Kevin Morin - kmorin@codelutin.com + * @see BeanDoubleList + * @since 2.5.8 + */ +public class BeanDoubleListModel<O> extends AbstractSerializableBean { + + private static final Log log = LogFactory.getLog(BeanDoubleListModel.class); + + public static final String PROPERTY_ADD_ENABLED = "addEnabled"; + + public static final String PROPERTY_REMOVE_ENABLED = "removeEnabled"; + + public static final String PROPERTY_SELECTED_UP_ENABLED = "selectedUpEnabled"; + + public static final String PROPERTY_SELECTED_DOWN_ENABLED = "selectedDownEnabled"; + + public static final String PROPERTY_USE_MULTI_SELECT = "useMultiSelect"; + + private static final long serialVersionUID = 1L; + + /** List of all the available items */ + protected List<O> universe = new ArrayList<O>(); + + /** Model containing the remaining available items */ + protected JaxxFilterableListModel<O> universeModel = new JaxxFilterableListModel<O>(); + + /** List of the selected items */ + protected List<O> selected = new ArrayList<O>(); + + /** Model containing the selected items */ + protected JaxxDefaultListModel<O> selectedModel = new JaxxDefaultListModel<O>(); + + protected boolean addEnabled; + + protected boolean removeEnabled; + + protected boolean selectedUpEnabled; + + protected boolean selectedDownEnabled; + + protected boolean useMultiSelect; + + protected Collection<Predicate<List<O>>> canRemoveItemsPredicates = new ArrayList<Predicate<List<O>>>(); + + /** + * To get the selected items. + * + * @return a list of O + */ + public List<O> getSelected() { + return selected; + } + + /** + * Sets the list of selected items. + * It fills the model of the list of the selected items with these items + * and removes them from the model of list of the universe. + * + * @param selected a list of O + */ + public void setSelected(List<O> selected) { + //reset all the universe in the universe list + resetUniverse(); + + if (selected == null) { + selected = Lists.newArrayList(); + } + this.selected.clear(); + selectedModel.clear(); + addToSelected(selected); + } + + /** + * To get all the available items. + * + * @return a list of O + */ + public List<O> getUniverse() { + return universe; + } + + /** + * Sets the list of the available items. + * It fills the model of the universe list with these items. + * + * @param universe a list of O + */ + public void setUniverse(List<O> universe) { + if (universe == null) { + this.universe = Lists.newArrayList(); + } else { + this.universe = Lists.newArrayList(universe); + } + resetUniverse(); + } + + protected void resetUniverse() { + universeModel.setAllElements(universe); + } + + public ListModel getSelectedModel() { + return selectedModel; + } + + public ListModel getUniverseModel() { + return universeModel; + } + + /** + * Adds an item to the selected items. + * + * @param item the item to select + */ + public void addToSelected(O item) { + selected.add(item); + selectedModel.addElement(item); + if (!useMultiSelect) { + universeModel.removeElement(item); + } + } + + /** + * Adds a list of items to the selected items. + * + * @param items the list of the items to select + */ + public void addToSelected(List<O> items) { + selected.addAll(items); + for (O item : items) { + + selectedModel.setValueIsAdjusting(true); + universeModel.setValueIsAdjusting(true); + + try { + selectedModel.addElement(item); + if (!useMultiSelect) { + universeModel.removeElement(item); + } + } finally { + selectedModel.setValueIsAdjusting(false); + universeModel.setValueIsAdjusting(false); + } + } + + selectedModel.refresh(); + universeModel.refresh(); + + } + + /** + * Removes an item from the selected items. + * + * @param item the item to unselect + */ + public void removeFromSelected(O item) { + selected.remove(item); + selectedModel.removeElement(item); + if (!useMultiSelect) { + addToUniverseList(item); + } + } + + /** + * Removes a list of items from the list of selected items. + * + * @param items the list of the items to unselect + */ + public void removeFromSelected(List<O> items) { + selected.removeAll(items); + for (O item : items) { + selectedModel.removeElement(item); + if (!useMultiSelect) { + addToUniverseList(item); + } + } + } + + /** + * Move up a selected item. + * + * @param item the selected item + * @since 2.5.26 + */ + public void moveUpSelected(O item) { + int i = selected.indexOf(item); + selected.remove(item); + selectedModel.removeElement(item); + selected.add(i - 1, item); + selectedModel.insertElementAt(item, i - 1); + } + + /** + * Move down a selected item. + * + * @param item the selected item + * @since 2.5.26 + */ + public void moveDownSelected(O item) { + int i = selected.indexOf(item); + selected.remove(item); + selectedModel.removeElement(item); + selected.add(i + 1, item); + selectedModel.insertElementAt(item, i + 1); + } + + public boolean isAddEnabled() { + return addEnabled; + } + + public void setAddEnabled(boolean addEnabled) { + boolean oldValue = isAddEnabled(); + this.addEnabled = addEnabled; + firePropertyChange(PROPERTY_ADD_ENABLED, oldValue, addEnabled); + } + + public boolean isRemoveEnabled() { + return removeEnabled; + } + + public void setRemoveEnabled(boolean removeEnabled) { + boolean oldValue = isRemoveEnabled(); + this.removeEnabled = removeEnabled; + firePropertyChange(PROPERTY_REMOVE_ENABLED, oldValue, removeEnabled); + } + + public boolean isSelectedUpEnabled() { + return selectedUpEnabled; + } + + public void setSelectedUpEnabled(boolean selectedUpEnabled) { + boolean oldValue = isSelectedUpEnabled(); + this.selectedUpEnabled = selectedUpEnabled; + firePropertyChange(PROPERTY_SELECTED_UP_ENABLED, oldValue, selectedUpEnabled); + } + + public boolean isSelectedDownEnabled() { + return selectedDownEnabled; + } + + public void setSelectedDownEnabled(boolean selectedDownEnabled) { + boolean oldValue = isSelectedDownEnabled(); + this.selectedDownEnabled = selectedDownEnabled; + firePropertyChange(PROPERTY_SELECTED_DOWN_ENABLED, oldValue, selectedDownEnabled); + } + + + public boolean isUseMultiSelect() { + return useMultiSelect; + } + + public void setUseMultiSelect(boolean useMultiSelect) { + boolean oldValue = isUseMultiSelect(); + this.useMultiSelect = useMultiSelect; + firePropertyChange(PROPERTY_USE_MULTI_SELECT, oldValue, useMultiSelect); + } + + /** + * Adds an item to the available items list at the right index + * to keep always the same order. + * + * @param item the item to add to the universe list + */ + protected void addToUniverseList(O item) { + // the maximum index where we should insert the item is its index + // in the list of all the available items + int index = universe.indexOf(item); + if (index!=-1) { + // if the index is upper than the size of the list of the remaining available items, + // get the size of this list + int insertionIndex = Math.min(index, universeModel.getSize()); + + // we decrease the index to insert until we meet an item whose index + // in the list of all the available index is lower than the one of the item + // we want to insert + while (insertionIndex > 0) { + O o = universeModel.get(--insertionIndex); + int oIndex = universe.indexOf(o); + if (oIndex < index) { + insertionIndex++; + break; + } + } + universeModel.add(insertionIndex, item); + } + } + + public int getSelectedListSize() { + return selected.size(); + } + + public void addCanRemoveItemsPredicate(Predicate<List<O>> canRemoveItemsPredicate) { + canRemoveItemsPredicates.add(canRemoveItemsPredicate); + } + + public void removeCanRemoveItemsPredicate(Predicate<List<O>> canRemoveItemsPredicate) { + canRemoveItemsPredicates.remove(canRemoveItemsPredicate); + } + + public boolean computeRemoveEnabled(List<O> toRemoveItems) { + boolean result = true; + Iterator<Predicate<List<O>>> iterator = canRemoveItemsPredicates.iterator(); + while (result && iterator.hasNext()) { + result = iterator.next().apply(toRemoveItems); + } + setRemoveEnabled(result); + return result; + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanFilterableComboBox.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanFilterableComboBox.jaxx new file mode 100644 index 0000000..d9260dd --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanFilterableComboBox.jaxx @@ -0,0 +1,160 @@ +<!-- + #%L + JAXX :: Widgets + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<Table fill='both' insets='0' genericType='O' + implements='org.nuiton.jaxx.runtime.bean.BeanTypeAware<O>' + onFocusGained='handler.focusCombo()' onFocusLost='hidePopup()'> + + <import> + org.nuiton.jaxx.runtime.swing.model.JaxxFilterableComboBoxModel + org.nuiton.decorator.JXPathDecorator + javax.swing.border.TitledBorder + </import> + + <!-- bean type --> + <Class id='beanType' genericType='O' javaBean='null'/> + + <!-- filterable property --> + <Boolean id='filterable' javaBean='true'/> + + <!-- flag to reverse the sort --> + <Boolean id='reverseSort' javaBean='false'/> + + <!-- show reset property --> + <Boolean id='showReset' javaBean='false'/> + + <!-- show decorator property --> + <Boolean id='showDecorator' javaBean='true'/> + + <!-- editable combo property --> + <Boolean id='editable' javaBean='true'/> + + <!-- sortable combo property --> + <Boolean id='sortable' javaBean='true'/> + + <!-- to transmit focus from table to combo property --> + <Boolean id='autoFocus' javaBean='true'/> + + <!-- to select using enter key when there is only one selection --> + <Boolean id='enterToSelectUniqueUniverse' javaBean='true'/> + + <!-- bean property linked state --> + <String id='property' javaBean='""'/> + + <!-- model property --> + <Object id='bean' javaBean='null'/> + + <!-- selectedItem property --> + <Object id='selectedItem' javaBean='null'/> + + <!-- sort index property --> + <Integer id='index' javaBean='0'/> + + <java.awt.Color id='invalidComboEditorTextColor' javaBean='null'/> + + <!-- datas of the combo-box --> + <java.util.List id='data' genericType='O' javaBean='null'/> + + <Integer id="maximumRowCount" javaBean="null"/> + + <!-- model of sorted property --> + <ButtonGroup id='indexes' + onStateChanged='setIndex((Integer)indexes.getSelectedValue())'/> + + <ButtonGroup id='sortGroup' + onStateChanged='setReverseSort((Boolean)sortGroup.getSelectedValue())'/> + + <!-- ui handler --> + <BeanFilterableComboBoxHandler id='handler' genericType='O' constructorParams='this'/> + + <String id='selectedToolTipText' javaBean='null'/> + + <String id='notSelectedToolTipText' javaBean='null'/> + + <String id='popupTitleText' javaBean='null'/> + + <String id='i18nPrefix' javaBean='"entitycombobox.common."'/> + + <!-- popup to change sorted property--> + <JPopupMenu id='popup' + onPopupMenuWillBecomeInvisible='getChangeDecorator().setSelected(false)' + onPopupMenuCanceled='getChangeDecorator().setSelected(false)'> + <JLabel id='popupSortLabel'/> + + <JRadioButtonMenuItem id='sortUp'/> + + <JRadioButtonMenuItem id='sortDown'/> + + <JSeparator id='popupSeparator'/> + <JLabel id='popupLabel'/> + <JSeparator/> + </JPopupMenu> + + <script><![CDATA[ + +public static final String PROPERTY_EMPTY = "empty"; + +public void init(JXPathDecorator<O> decorator, List<O> data) { + handler.init(decorator, data); +} + +protected void hidePopup() { + if (popup.isVisible()) { + popup.setVisible(false); + } +} + +public boolean isEmpty() { return handler.isEmpty(); } + +public void addItem(O item) { handler.addItem(item); } + +public void addItems(Iterable<O> items) { handler.addItems(items); } + +public void removeItem(O item) { handler.removeItem(item); } + +public void removeItems(Iterable<O> items) { handler.removeItems(items); } + +public void reset() { handler.reset(); } + +public JaxxFilterableComboBoxModel<O> getComboBoxModel() { return (JaxxFilterableComboBoxModel<O>) combobox.getModel(); } + +]]> + </script> + <row> + <cell anchor='west'> + <!-- le boutton pour reinitialiser la valeur sélectionnée --> + <JToolBar id='toolbarLeft'> + <JButton id='resetButton' onActionPerformed='handler.reset()'/> + </JToolBar> + + </cell> + <cell weightx='1'> + <!-- la liste déroulante --> + <JComboBox id='combobox'/> + </cell> + <cell anchor='east' fill='both' insets='0'> + <!-- le boutton pour changer le tri --> + <JToolBar id='toolbarRight'> + <JToggleButton id='changeDecorator' + onActionPerformed='getHandler().togglePopup()'/> + </JToolBar> + </cell> + </row> +</Table> diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanFilterableComboBox.jcss b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanFilterableComboBox.jcss similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanFilterableComboBox.jcss rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanFilterableComboBox.jcss diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanFilterableComboBoxHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanFilterableComboBoxHandler.java new file mode 100644 index 0000000..39abf17 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanFilterableComboBoxHandler.java @@ -0,0 +1,736 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.editor.bean; + +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.nuiton.jaxx.runtime.swing.JAXXButtonGroup; +import org.nuiton.jaxx.runtime.swing.model.JaxxFilterableComboBoxModel; +import org.nuiton.jaxx.runtime.swing.renderer.DecoratorListCellRenderer; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.decorator.DecoratorUtil; +import org.nuiton.decorator.JXPathDecorator; +import org.nuiton.decorator.MultiJXPathDecorator; +import org.nuiton.util.beans.BeanUtil; + +import javax.swing.AbstractButton; +import javax.swing.ComboBoxEditor; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JPopupMenu; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.JTextComponent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +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.lang.reflect.Method; +import java.util.Collections; +import java.util.List; + +/** + * Le handler d'un {@link BeanFilterableComboBox}. + * + * Note: ce handler n'est pas stateless et n'est donc pas partageable entre + * plusieurs ui. + * + * @param <O> le type des objet contenus dans le modèle du composant. + * @author Kevin Morin - morin@codelutin.com + * @see BeanFilterableComboBox + * @since 2.5.12 + */ +public class BeanFilterableComboBoxHandler<O> implements PropertyChangeListener { + + public static final Log log = LogFactory.getLog(BeanFilterableComboBoxHandler.class); + + /** ui if the handler */ + protected BeanFilterableComboBox<O> ui; + + /** the mutator method on the property of boxed bean in the ui */ + protected Method mutator; + + /** the decorator of data */ + protected MultiJXPathDecorator<O> decorator; + + protected boolean init; + + public BeanFilterableComboBoxHandler(BeanFilterableComboBox<O> ui) { + this.ui = ui; + } + + protected final FocusListener EDITOR_TEXT_COMP0NENT_FOCUSLISTENER = new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + if (log.isDebugEnabled()) { + log.debug("close popup from " + e); + } + ui.getPopup().setVisible(false); + } + + @Override + public void focusLost(FocusEvent e) { + } + }; + + protected final DocumentListener EDITOR_TEXT_COMPONENT_DOCUMENTLISTENER = new DocumentListener() { + public void insertUpdate(DocumentEvent e) { + updateFilter(); + } + + public void removeUpdate(DocumentEvent e) { + updateFilter(); + } + + public void changedUpdate(DocumentEvent e) { + updateFilter(); + } + + protected void updateFilter() { + JComboBox comboBox = ui.getCombobox(); + JaxxFilterableComboBoxModel model = (JaxxFilterableComboBoxModel) comboBox.getModel(); + JTextComponent editorComponent = (JTextComponent) comboBox.getEditor().getEditorComponent(); + // hide the popup before setting the filter, otherwise the popup height does not fit + boolean wasPopupVisible = comboBox.isShowing() && comboBox.isPopupVisible(); + if (wasPopupVisible) { + comboBox.hidePopup(); + } + String text = editorComponent.getText(); + if (ui.getSelectedItem() != null) { + text = ""; + } + if (log.isDebugEnabled()) { + log.debug("updateFilter " + text); + } + model.setFilterText(text); + if (wasPopupVisible) { + comboBox.showPopup(); + } + } + + }; + + private final BeanUIUtil.PopupHandler popupHandler = new BeanUIUtil.PopupHandler() { + @Override + public JPopupMenu getPopup() { + return ui.getPopup(); + } + + @Override + public JComponent getInvoker() { + return ui.getChangeDecorator(); + } + }; + + /** + * Initialise le handler de l'ui + * + * @param decorator le decorateur a utiliser + * @param data la liste des données a gérer + */ + public void init(JXPathDecorator<O> decorator, List<O> data) { + + if (init) { + throw new IllegalStateException("can not init the handler twice"); + } + init = true; + + if (decorator == null) { + throw new NullPointerException("decorator can not be null (for type " + ui.getBeanType() + ")"); + } + + JAXXButtonGroup indexes = ui.getIndexes(); + + this.decorator = BeanUIUtil.createDecorator(decorator); + + final JComboBox combobox = ui.getCombobox(); + final JAXXFilterableComboBoxEditor editor = + new JAXXFilterableComboBoxEditor(ui.getCombobox().getEditor()); + combobox.setEditor(editor); + + editor.getEditorComponent().addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + if (ui.isEnabled()) { + combobox.showPopup(); + } + } + + }); + editor.getEditorComponent().addKeyListener(new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + if (!ui.isEnabled()) { + e.consume(); + return; + } + if (log.isDebugEnabled()) { + log.debug("keyPressed: " + e.getKeyCode()); + } + if (combobox.isPopupVisible() && ui.isEnterToSelectUniqueUniverse()) { + if (KeyEvent.VK_ENTER == e.getKeyCode() && combobox.getItemCount() == 1) { + // we don't want any other action for this one + if (log.isDebugEnabled()) { + log.debug("ENTER + only one selected item, consume"); + } + combobox.hidePopup(); + e.consume(); + return; + } + } + } + + @Override + public void keyReleased(KeyEvent e) { + if (log.isDebugEnabled()) { + log.debug("keyReleased: " + e.getKeyCode()); + } + if (combobox.isPopupVisible() && KeyEvent.VK_ESCAPE == e.getKeyCode()) { + if (log.isDebugEnabled()) { + log.debug("ESC , hide popup"); + } + e.consume(); + combobox.hidePopup(); + return; + } + if (!combobox.isPopupVisible() && KeyEvent.VK_ESCAPE != e.getKeyCode() && KeyEvent.VK_ENTER != e.getKeyCode()) { + if (log.isDebugEnabled()) { + log.debug("Will show popup, keycode: " + e.getKeyCode()); + } + combobox.showPopup(); + } + // if the typed text does not match the selected item, + // set the selected item to null + Object selectedItem = ui.getSelectedItem(); + String text = editor.getEditorComponent().getText(); + if (log.isDebugEnabled()) { + log.debug("keycode: " + e.getKeyCode() + ", editorText: " + text); + } + if (KeyEvent.VK_ENTER == e.getKeyCode() && ui.isEnterToSelectUniqueUniverse() && combobox.getItemCount() == 1) { + + // auto-select the + if (log.isDebugEnabled()) { + log.debug("Auto-select unique result with *ENTER* key"); + } + combobox.setSelectedIndex(0); + e.consume(); + // edition is done + combobox.hidePopup(); + return; + } + final String selectedItemString; + if (getBeanType().isInstance(selectedItem)) { + selectedItemString = BeanFilterableComboBoxHandler.this.decorator.toString(selectedItem); + } else { + selectedItemString = JAXXUtil.getStringValue(selectedItem); + } + if (selectedItem == null || !selectedItemString.equals(text)) { + unselectItem(); + } + } + + }); + + // init combobox renderer base on given decorator + combobox.setRenderer(new DecoratorListCellRenderer(this.decorator)); + ((JaxxFilterableComboBoxModel) combobox.getModel()).setDecorator(this.decorator); + combobox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE); + combobox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + Object item = e.getItem(); + if (e.getStateChange() == ItemEvent.SELECTED) { + if (log.isDebugEnabled()) { + log.debug("itemStateChanged selected " + item + " - " + (item != null ? item.getClass() : null)); + } + combobox.getEditor().getEditorComponent().setForeground(null); + ui.setSelectedItem(item); + + } else { + if (log.isDebugEnabled()) { + log.debug("itemStateChanged deselected " + item + " - " + (item != null ? item.getClass() : null)); + } + combobox.getEditor().getEditorComponent().setForeground(ui.getInvalidComboEditorTextColor()); + } + } + }); + + // build popup + popupHandler.preparePopup(ui.getSelectedToolTipText(), + ui.getNotSelectedToolTipText(), + ui.getI18nPrefix(), + ui.getPopupTitleText(), + indexes, + ui.getPopupSeparator(), + ui.getPopupLabel(), + ui.getSortUp(), + ui.getSortDown(), + this.decorator); + + setFilterable(false, ui.getFilterable()); + + ui.addPropertyChangeListener(this); + + // set datas + ui.setData(data); + + // select sort button + indexes.setSelectedButton(ui.getIndex()); + } + + /** Toggle the popup visible state. */ + public void togglePopup() { + popupHandler.togglePopup(); + } + + /** + * @return {@code true} if there is no data in comboBox, {@code false} + * otherwise. + */ + public boolean isEmpty() { + return CollectionUtils.isEmpty(ui.getData()); + } + + /** + * Add the given items into the comboBox. + * + * <strong>Note:</strong> The item will be inserted at his correct following + * the selected ordering. + * + * @param items items to add in comboBox. + * @since 2.5.28 + */ + public void addItems(Iterable<O> items) { + + List<O> data = ui.getData(); + + boolean wasEmpty = CollectionUtils.isEmpty(data); + + for (O item : items) { + data.add(item); + } + + updateUI(ui.getIndex(), ui.isReverseSort()); + + fireEmpty(wasEmpty); + } + + /** + * Remove the given items from the comboBox model. + * + * <strong>Note:</strong> If this item was selected, then selection will be + * cleared. + * + * @param items items to remove from the comboBox model + * @since 2.5.28 + */ + public void removeItems(Iterable<O> items) { + + List<O> data = ui.getData(); + + boolean needUpdate = false; + for (O item : items) { + boolean remove = data.remove(item); + + if (remove) { + + // item was found in data + + Object selectedItem = ui.getSelectedItem(); + if (item == selectedItem) { + + // item was selected item, reset selected item then + ui.setSelectedItem(null); + } + + needUpdate = true; + } + } + + if (needUpdate) { + + updateUI(ui.getIndex(), ui.isReverseSort()); + fireEmpty(false); + } + + } + + /** + * Add the given item into the comboBox. + * + * <strong>Note:</strong> The item will be inserted at his correct following + * the selected ordering. + * + * @param item item to add in comboBox. + * @since 2.5.9 + */ + public void addItem(O item) { + + addItems(Collections.singleton(item)); + } + + /** + * Remove the given item from the comboBox model. + * + * <strong>Note:</strong> If this item was selected, then selection will be + * cleared. + * + * @param item the item to remove from the comboBox model + * @since 2.5.9 + */ + public void removeItem(O item) { + + removeItems(Collections.singleton(item)); + } + + /** Sort data of the model. */ + public void sortData() { + + // just update UI should do the math of this + updateUI(ui.getIndex(), ui.isReverseSort()); + } + + /** + * Reset the combo-box; says remove any selected item and filter text. + */ + public void reset() { + if (ui.getSelectedItem() != null) { + ui.setSelectedItem(null); + } else { + JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); + editorComponent.setText(""); + } + + JComboBox comboBox = ui.getCombobox(); + if (comboBox.isShowing()) { + comboBox.hidePopup(); + } + } + + /** + * Focus combo only if autoFocus ui property is on. + * + * @since 2.8.5 + */ + public void focusCombo() { + if (ui.isAutoFocus()) { + ui.combobox.requestFocusInWindow(); + } + } + + /** + * Modifie l'état filterable de l'ui. + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + protected void setFilterable(Boolean oldValue, Boolean newValue) { + oldValue = oldValue != null && oldValue; + newValue = newValue != null && newValue; + if (oldValue.equals(newValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("filterable state : <" + oldValue + " to " + newValue + ">"); + } + if (!newValue) { + JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); + editorComponent.removeFocusListener(EDITOR_TEXT_COMP0NENT_FOCUSLISTENER); + editorComponent.getDocument().removeDocumentListener(EDITOR_TEXT_COMPONENT_DOCUMENTLISTENER); + ((JaxxFilterableComboBoxModel) ui.getCombobox().getModel()).setFilterText(null); + + } else { + JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); + editorComponent.addFocusListener(EDITOR_TEXT_COMP0NENT_FOCUSLISTENER); + editorComponent.getDocument().addDocumentListener(EDITOR_TEXT_COMPONENT_DOCUMENTLISTENER); + EDITOR_TEXT_COMPONENT_DOCUMENTLISTENER.changedUpdate(null); + } + } + + /** + * Modifie l'index du décorateur + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + protected void setIndex(Integer oldValue, Integer newValue) { + if (newValue == null || newValue.equals(oldValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("check state : <" + oldValue + " to " + newValue + ">"); + } + AbstractButton button = ui.getIndexes().getButton(newValue); + if (button != null) { + button.setSelected(true); + } + updateUI(newValue, ui.isReverseSort()); + } + + /** + * Modifie l'index du décorateur + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + protected void setSortOrder(Boolean oldValue, Boolean newValue) { + + if (newValue == null || newValue.equals(oldValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("check state : <" + oldValue + " to " + newValue + ">"); + } + + updateUI(ui.getIndex(), newValue); + } + + protected void updateUI(int index, boolean reversesort) { + + // change decorator context + decorator.setContextIndex(index); + + // keep selected item + Object previousSelectedItem = ui.getSelectedItem(); + + // remove autocomplete + if (previousSelectedItem != null) { + ui.getCombobox().setSelectedItem(null); + ui.selectedItem = null; + } + + List<O> data = ui.getData(); + + if (ui.isSortable() && CollectionUtils.isNotEmpty(data)) { + try { + // Sort data with the decorator jxpath tokens. + DecoratorUtil.sort(decorator, + data, + index, + reversesort); + + } catch (Exception eee) { + log.warn(eee.getMessage(), eee); + } + } + + // reload the model + SwingUtil.fillComboBox(ui.getCombobox(), data, null); + + if (previousSelectedItem != null) { + ui.setSelectedItem(previousSelectedItem); + } + + ui.getCombobox().requestFocus(); + } + + protected void unselectItem() { + if (ui.selectedItem == null) { + return; + } + + ui.selectedItem = null; + BeanUIUtil.invokeMethod(getMutator(), + ui.getBean(), + (O) null); + } + + /** + * Modifie la valeur sélectionnée dans la liste déroulante. + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + protected void setSelectedItem(O oldValue, O newValue) { + if (oldValue == null && newValue == null) { + return; + } + + if (!getBeanType().isInstance(newValue)) { + newValue = null; + } + + JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); + editorComponent.setText(""); + + if (log.isDebugEnabled()) { + log.debug(ui.getProperty() + " on " + getBeanType() + " :: " + oldValue + " to " + newValue); + } + + BeanUIUtil.invokeMethod(getMutator(), + ui.getBean(), + newValue); + } + + public MultiJXPathDecorator<O> getDecorator() { + return decorator; + } + + /** @return get the type of objects contained in the comboBox model. */ + public Class<O> getBeanType() { + Class<O> result = ui.getBeanType(); + if (result == null) { + result = decorator == null ? null : decorator.getType(); + } + return result; + } + + /** @return le mutateur a utiliser pour modifier le bean associé. */ + protected Method getMutator() { + if (mutator == null && ui.getBean() != null && ui.getProperty() != null) { + mutator = BeanUtil.getMutator(ui.getBean(), ui.getProperty()); + } + return mutator; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + String propertyName = evt.getPropertyName(); + + if (BeanFilterableComboBox.PROPERTY_SELECTED_ITEM.equals(propertyName)) { + setSelectedItem((O) evt.getOldValue(), (O) evt.getNewValue()); + return; + } + + if (BeanFilterableComboBox.PROPERTY_FILTERABLE.equals(propertyName)) { + + setFilterable((Boolean) evt.getOldValue(), + (Boolean) evt.getNewValue()); + return; + } + + if (BeanFilterableComboBox.PROPERTY_INDEX.equals(propertyName)) { + + // decorator index has changed, force reload of data in ui + setIndex((Integer) evt.getOldValue(), + (Integer) evt.getNewValue()); + return; + } + + if (BeanFilterableComboBox.PROPERTY_REVERSE_SORT.equals(propertyName)) { + + // sort order has changed, force reload of data in ui + setSortOrder((Boolean) evt.getOldValue(), + (Boolean) evt.getNewValue()); + return; + } + + if (BeanFilterableComboBox.PROPERTY_DATA.equals(propertyName)) { + + // list has changed, force reload of index + setIndex(null, ui.getIndex()); + + // list has changed, fire empty property + List list = (List) evt.getOldValue(); + fireEmpty(CollectionUtils.isEmpty(list)); + } + } + + protected void fireEmpty(boolean wasEmpty) { + ui.firePropertyChange(BeanComboBox.PROPERTY_EMPTY, wasEmpty, + isEmpty()); + } + + /** Editor for the Combobox of the UI - uses the decorator */ + class JAXXFilterableComboBoxEditor implements ComboBoxEditor { + + Object oldItem; + + ComboBoxEditor wrapped; + + public JAXXFilterableComboBoxEditor(ComboBoxEditor wrapped) { + this.wrapped = wrapped; + } + + @Override + public JTextComponent getEditorComponent() { + return (JTextComponent) wrapped.getEditorComponent(); + } + + @Override + public void setItem(Object anObject) { + if (log.isDebugEnabled()) { + log.debug("setItem " + anObject + " - " + (anObject != null ? anObject.getClass() : null)); + } + Object item = anObject; + if (anObject != null) { + if (getBeanType().isInstance(anObject)) { + item = decorator.toString(anObject); + oldItem = anObject; + } + try { + wrapped.setItem(item); + + } catch (IllegalStateException e) { + // fail silently + } + } + } + + @Override + public Object getItem() { + JTextComponent editor = getEditorComponent(); + Object newValue = editor.getText(); + if (log.isDebugEnabled()) { + log.debug("getItem " + newValue + " - " + (newValue != null ? newValue.getClass() : null)); + } + + if (oldItem != null && getBeanType().isInstance(oldItem)) { + // The original value is not a string. Should return the value in it's + // original type. + if (newValue.equals(decorator.toString(oldItem))) { + newValue = oldItem; + } + } + if (log.isDebugEnabled()) { + log.debug("getItem 2 " + newValue + " - " + (newValue != null ? newValue.getClass() : null)); + } + return newValue; + } + + @Override + public void selectAll() { + wrapped.selectAll(); + } + + @Override + public void addActionListener(ActionListener l) { + wrapped.addActionListener(l); + } + + @Override + public void removeActionListener(ActionListener l) { + wrapped.removeActionListener(l); + } + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanListHeader.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanListHeader.jaxx new file mode 100644 index 0000000..b38b826 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanListHeader.jaxx @@ -0,0 +1,117 @@ +<!-- + #%L + JAXX :: Widgets + %% + Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + %% + This program 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 General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JPanel id='top' layout='{new BorderLayout()}' genericType='O' + implements='org.nuiton.jaxx.runtime.bean.BeanTypeAware<O>'> + + <import> + org.nuiton.decorator.JXPathDecorator + javax.swing.border.TitledBorder + </import> + + <!-- show reset property --> + <Boolean id='showReset' javaBean='false'/> + + <!-- show decorator property --> + <Boolean id='showDecorator' javaBean='true'/> + + <!-- flag to reverse the sort --> + <Boolean id='reverseSort' javaBean='false'/> + + <!-- editable combo property --> + <Boolean id='editable' javaBean='true'/> + + <!-- bean type --> + <Class id='beanType' genericType='O' javaBean='null'/> + + <!-- label --> + <String id='labelText' javaBean='null'/> + + <!-- sort index property --> + <Integer id='index' javaBean='0'/> + + <!-- datas of the combo-box --> + <java.util.List id='data' genericType='O' javaBean='null'/> + + <!-- model of sorted property --> + <ButtonGroup id='indexes' + onStateChanged='setIndex((Integer)indexes.getSelectedValue())'/> + + <ButtonGroup id='sortGroup' + onStateChanged='setReverseSort((Boolean)sortGroup.getSelectedValue())'/> + + <!-- ui handler --> + <BeanListHeaderHandler id='handler' genericType='O' constructorParams='this'/> + + <String id='selectedToolTipText' javaBean='null'/> + + <String id='notSelectedToolTipText' javaBean='null'/> + + <String id='popupTitleText' javaBean='null'/> + + <String id='i18nPrefix' javaBean='"beanlist.common."'/> + + <!-- popup to change sorted property--> + <JPopupMenu id='popup' + onPopupMenuWillBecomeInvisible='getChangeDecorator().setSelected(false)' + onPopupMenuCanceled='getChangeDecorator().setSelected(false)'> + + <JLabel id='popupSortLabel'/> + + <JRadioButtonMenuItem id='sortUp'/> + + <JRadioButtonMenuItem id='sortDown'/> + + <JSeparator id='popupSeparator'/> + <JLabel id='popupLabel'/> + + </JPopupMenu> + + <JList id='list' javaBean="new JList()"/> + + <script><![CDATA[ + +public void init(JXPathDecorator<O> decorator, List<O> data) { + handler.init(decorator, data); +} + +public O getSelectedValue() { + return handler.getSelectedValue(); +} + +]]> + </script> + + <JLabel id="label" constraints='BorderLayout.CENTER'/> + + <JToolBar id='toolbar' constraints='BorderLayout.EAST'> + + <!-- le boutton pour reinitialiser la valeur sélectionnée --> + <JButton id='resetSelection' + onActionPerformed='getList().getSelectionModel().clearSelection()'/> + + <!-- le boutton pour changer le tri --> + <JToggleButton id='changeDecorator' + onActionPerformed='getHandler().togglePopup()'/> + </JToolBar> +</JPanel> + diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanListHeader.jcss b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanListHeader.jcss similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanListHeader.jcss rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanListHeader.jcss diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanListHeaderHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanListHeaderHandler.java new file mode 100644 index 0000000..513be37 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanListHeaderHandler.java @@ -0,0 +1,291 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.runtime.swing.editor.bean; + +import org.nuiton.jaxx.runtime.swing.JAXXButtonGroup; +import org.nuiton.jaxx.runtime.swing.renderer.DecoratorListCellRenderer; +import org.apache.commons.collections.primitives.ArrayIntList; +import org.apache.commons.collections.primitives.IntList; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.decorator.DecoratorUtil; +import org.nuiton.decorator.JXPathDecorator; +import org.nuiton.decorator.MultiJXPathDecorator; + +import javax.swing.DefaultListModel; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JPopupMenu; +import javax.swing.ListModel; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.List; + +/** + * Le handler d'un {@link BeanListHeader}. + * + * Note: ce handler n'est pas stateless et n'est donc pas partageable entre + * plusieurs ui. + * + * @param <O> le type des objet contenus dans le modèle du composant. + * @author Tony Chemit - chemit@codelutin.com + * @see BeanListHeader + * @since 2.2 + */ +public class BeanListHeaderHandler<O> implements PropertyChangeListener { + + public static final Log log = + LogFactory.getLog(BeanListHeaderHandler.class); + + /** ui if the handler */ + protected BeanListHeader<O> ui; + + /** the decorator of data */ + protected MultiJXPathDecorator<O> decorator; + + /** flag to mark when handler was init (it can be init only once). */ + protected boolean init; + + private final BeanUIUtil.PopupHandler popupHandler = new BeanUIUtil.PopupHandler() { + + @Override + public JPopupMenu getPopup() { + return ui.getPopup(); + } + + @Override + public JComponent getInvoker() { + return ui.getChangeDecorator(); + } + }; + + public BeanListHeaderHandler(BeanListHeader<O> ui) { + this.ui = ui; + } + + /** + * Initialise le handler de l'ui + * + * @param decorator le decorateur a utiliser + * @param data la liste des données a gérer + */ + public void init(JXPathDecorator<O> decorator, List<O> data) { + + if (init) { + throw new IllegalStateException("can not init the handler twice"); + } + init = true; + + if (decorator == null) { + throw new NullPointerException("decorator can not be null (for type " + ui.getBeanType() + ")"); + } + + // list could have changed and the complex binding is not registred... + ui.removeDataBinding(BeanListHeader.BINDING_RESET_SELECTION_ENABLED); + ui.applyDataBinding(BeanListHeader.BINDING_RESET_SELECTION_ENABLED); + + JAXXButtonGroup indexes = ui.getIndexes(); + + this.decorator = BeanUIUtil.createDecorator(decorator); + + // init combobox renderer base on given decorator + ui.getList().setCellRenderer(new DecoratorListCellRenderer(this.decorator)); + + // build popup + popupHandler.preparePopup(ui.getSelectedToolTipText(), + ui.getNotSelectedToolTipText(), + ui.getI18nPrefix(), + ui.getPopupTitleText(), + indexes, + ui.getPopupSeparator(), + ui.getPopupLabel(), + ui.getSortUp(), + ui.getSortDown(), + this.decorator); + + ui.addPropertyChangeListener(this); + + // set datas + ui.setData(data); + + // select sort button + indexes.setSelectedButton(ui.getIndex()); + } + + /** Toggle the popup visible state. */ + public void togglePopup() { + popupHandler.togglePopup(); + } + + /** + * Modifie l'index du décorateur + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + protected void setIndex(Integer oldValue, Integer newValue) { + if (newValue == null || newValue.equals(oldValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("check state : <" + oldValue + " to " + newValue + ">"); + } + updateUI(newValue, ui.isReverseSort()); + } + + /** + * Modifie l'index du décorateur + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + + protected void setSortOrder(Boolean oldValue, Boolean newValue) { + + if (newValue == null || newValue.equals(oldValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("check state : <" + oldValue + " to " + newValue + ">"); + } + + updateUI(ui.getIndex(), newValue); + } + + @SuppressWarnings({"unchecked"}) + protected void updateUI(int index, boolean reverseSort) { + + // change decorator context + decorator.setContextIndex(index); + + String expression = decorator.getExpression(); + if (log.isDebugEnabled()) { + log.debug("will use expression (index = " + index + ") : " + + expression); + } + + // get the current selection in list + Object[] selection = ui.getList().getSelectedValues(); + + List<O> datas = ui.getData(); + try { + + // Sort data with the decorator jxpath tokens. + DecoratorUtil.sort(decorator, + datas, + index, + reverseSort); + } catch (Exception e) { + log.warn(e.getMessage(), e); + } + + ui.getList().setValueIsAdjusting(true); + try { + + // reload the model + ListModel listModel = ui.getList().getModel(); + + if (listModel instanceof DefaultListModel) { + DefaultListModel model = (DefaultListModel) listModel; + model.removeAllElements(); + for (O data : datas) { + model.addElement(data); + } + + } else { + + ui.getList().setListData(datas.toArray(new Object[datas.size()])); + } + + // re-apply selection + if (selection.length > 0) { + + // re compute selection (the new data could not contains some + // previously selected items) + IntList newSelection = new ArrayIntList(); + for (Object o : selection) { + if (datas.contains(o)) { + + newSelection.add(datas.indexOf(o)); + } + } + + if (!newSelection.isEmpty()) { + + // there is still a selection to re-apply + int[] ints = newSelection.toArray(new int[newSelection.size()]); + newSelection.clear(); + ui.getList().setSelectedIndices(ints); + } + } + + } finally { + ui.getList().setValueIsAdjusting(false); + } + + ui.getList().requestFocus(); + } + + public MultiJXPathDecorator<O> getDecorator() { + return decorator; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + String propertyName = evt.getPropertyName(); + + if (BeanListHeader.PROPERTY_INDEX.equals(propertyName)) { + + // decorator index has changed, force reload of data in ui + setIndex((Integer) evt.getOldValue(), + (Integer) evt.getNewValue()); + return; + } + + if (BeanListHeader.PROPERTY_REVERSE_SORT.equals(propertyName)) { + + // sort order has changed, force reload of data in ui + setSortOrder((Boolean) evt.getOldValue(), + (Boolean) evt.getNewValue()); + return; + } + + if (BeanListHeader.PROPERTY_DATA.equals(propertyName)) { + + // list has changed, force reload of index + setIndex(-1, ui.getIndex()); + } + + if (BeanListHeader.PROPERTY_LIST.equals(propertyName)) { + + // ui list has changed, replace binding + ui.removeDataBinding(BeanListHeader.BINDING_RESET_SELECTION_ENABLED); + ui.applyDataBinding(BeanListHeader.BINDING_RESET_SELECTION_ENABLED); + } + } + + public O getSelectedValue() { + JList list = ui.getList(); + return list == null ? null : (O) list.getSelectedValue(); + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanUIUtil.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanUIUtil.java new file mode 100644 index 0000000..b8a3d97 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/BeanUIUtil.java @@ -0,0 +1,428 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.editor.bean; + +import org.nuiton.jaxx.runtime.swing.JAXXButtonGroup; +import org.nuiton.jaxx.runtime.swing.JAXXRuntimeException; +import org.apache.commons.beanutils.MethodUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.autocomplete.AutoCompleteComboBoxEditor; +import org.jdesktop.swingx.autocomplete.AutoCompleteDecorator; +import org.jdesktop.swingx.autocomplete.AutoCompleteDocument; +import org.jdesktop.swingx.autocomplete.ComboBoxAdaptor; +import org.jdesktop.swingx.autocomplete.ObjectToStringConverter; +import org.nuiton.decorator.Decorator; +import org.nuiton.decorator.DecoratorUtil; +import org.nuiton.decorator.JXPathDecorator; +import org.nuiton.decorator.MultiJXPathDecorator; + +import javax.swing.AbstractButton; +import javax.swing.ActionMap; +import javax.swing.ButtonGroup; +import javax.swing.ComboBoxEditor; +import javax.swing.InputMap; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JSeparator; +import javax.swing.SwingUtilities; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionListener; +import java.awt.event.FocusListener; +import java.awt.event.KeyListener; +import java.beans.Introspector; +import java.beans.PropertyChangeListener; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Date; +import java.util.List; + +import static java.util.Arrays.asList; +import static java.util.Collections.unmodifiableList; +import static org.nuiton.i18n.I18n.t; +import static org.nuiton.i18n.I18n.n; + +/** + * Class with usefull methods used in bean uis. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.2 + */ +public class BeanUIUtil { + + public static final String DEFAULT_POPUP_LABEL = n("bean.popup.label"); + + public static final String DEFAULT_SELECTED_TOOLTIP = n("bean.sort.on"); + + public static final String DEFAULT_NOT_SELECTED_TOOLTIP = n("bean.sort.off"); + + public static final Object[] EMPTY_CLASS_ARRAY = new Object[0]; + + public static void invokeMethod(Method mut, Object source, Object... params) { + + if (mut != null) { + try { + mut.invoke(source, params); + } catch (IllegalAccessException e) { + throw new JAXXRuntimeException(e); + } catch (InvocationTargetException e) { + throw new JAXXRuntimeException(e.getCause()); + } + } + } + + /** + * Encapsule un {@link Decorator} dans un {@link ObjectToStringConverter}. + * + * @param decorator le decorateur a encapsuler. + * @return le converter encapsule dans un {@link ObjectToStringConverter} + */ + public static ObjectToStringConverter newDecoratedObjectToStringConverter(final Decorator<?> decorator) { + + return new ObjectToStringConverter() { + + @Override + public String getPreferredStringForItem(Object item) { + return item instanceof String ? (String) item : item == null ? "" : decorator.toString(item); + } + }; + } + + /** + * Ajout l'auto-complétion sur une liste déroulante, en utilisant le + * converteur donné pour afficher les données. + * + * @param combo la combo à décorer + * @param convertor le converter utilisé pour afficher les données. + */ + public static void decorate(JComboBox combo, ObjectToStringConverter convertor) { + + // tchemit 2010-10-05 since swingx 1.6.2, undecorate stuff is no more + // public and we want to use it, so hack it... + combo.putClientProperty("oldEditor", combo.getEditor()); + combo.putClientProperty("oldDocument", combo.getEditor().getEditorComponent()); + + AutoCompleteDecorator.decorate(combo, convertor); + } + + /** + * Désactive l'aut-complétion sur une liste déroulante, en y repositionnant + * le modèle du document d'édition d'avant auto-complétion. + * + * @param comboBox la liste déroulante à décorer + * @param originalDocument le document original de l'édtieur de la + * liste déroulante. + */ + public static void undecorate(JComboBox comboBox, Document originalDocument) { + + // has not to be editable + comboBox.setEditable(false); + + // configure the text component=editor component + Component c = comboBox.getEditor().getEditorComponent(); + JTextComponent editorComponent = (JTextComponent) c; + editorComponent.setDocument(originalDocument); + editorComponent.setText(null); + //undecorate(comboBox); + + //remove old property change listener + //for (PropertyChangeListener l : c.getPropertyChangeListeners("editor")) { + // if (l instanceof AutoCompletePropertyChangeListener) { + // c.removePropertyChangeListener("editor", l); + // } + //} + + ComboBoxEditor oldEditor = (ComboBoxEditor) comboBox.getClientProperty("oldEditor"); + + if (editorComponent.getDocument() instanceof AutoCompleteDocument) { + AutoCompleteDocument doc = (AutoCompleteDocument) editorComponent.getDocument(); + + if (doc.isStrictMatching()) { + ActionMap map = comboBox.getActionMap(); + + for (String key : COMBO_BOX_ACTIONS) { + map.put(key, null); + } + } + + //remove old property change listener + for (PropertyChangeListener l : comboBox.getPropertyChangeListeners("editor")) { + //if (l instanceof AutoComplete.PropertyChangeListener) { + if (l.getClass().getName().contains("AutoComplete")) { + comboBox.removePropertyChangeListener("editor", l); + } + } + + for (PropertyChangeListener l : comboBox.getPropertyChangeListeners("enabled")) { + //if (l instanceof AutoComplete.PropertyChangeListener) { + if (l.getClass().getName().contains("AutoComplete")) { + comboBox.removePropertyChangeListener("enabled", l); + } + } + + AutoCompleteComboBoxEditor editor = (AutoCompleteComboBoxEditor) comboBox.getEditor(); + comboBox.setEditor(oldEditor); + + //remove old key listener + for (KeyListener l : editorComponent.getKeyListeners()) { + //if (l instanceof AutoComplete.KeyAdapter) { + if (l.getClass().getName().contains("AutoComplete")) { + editorComponent.removeKeyListener(l); + break; + } + } + + undecorate(editorComponent, originalDocument); + + for (ActionListener l : comboBox.getActionListeners()) { + if (l instanceof ComboBoxAdaptor) { + comboBox.removeActionListener(l); + break; + } + } + + //TODO remove aqua fix + + //TODO reset editibility + } + } + + static void undecorate(JTextComponent textComponent, Document originalDocument) { + Document doc = textComponent.getDocument(); + + if (doc instanceof AutoCompleteDocument) { + //remove autocomplete key/action mappings + InputMap map = textComponent.getInputMap(); + + while (map.getParent() != null) { + InputMap parent = map.getParent(); + + //if (parent instanceof AutoComplete.InputMap) { + if (parent.getClass().getName().contains("AutoComplete")) { + map.setParent(parent.getParent()); + } + + map = parent; + } + + textComponent.getActionMap().put("nonstrict-backspace", null); + + //remove old focus listener + for (FocusListener l : textComponent.getFocusListeners()) { + //if (l instanceof AutoComplete.FocusAdapter) { + if (l.getClass().getName().contains("AutoComplete")) { + textComponent.removeFocusListener(l); + break; + } + } + + //reset to original document + //textComponent.setDocument(((AutoCompleteDocument) doc).delegate); + textComponent.setDocument(originalDocument); + } + } + + public static <O> MultiJXPathDecorator<O> createDecorator(JXPathDecorator<O> decorator) { + if (decorator == null) { + throw new NullPointerException( + "can not have a null decorator as parameter"); + } + String separator; + String separatorReplacement; + + if (decorator instanceof Cloneable) { + Cloneable cloneable = (Cloneable) decorator; + + try { + Object clone = MethodUtils.invokeExactMethod(cloneable, + "clone", + EMPTY_CLASS_ARRAY + ); + return (MultiJXPathDecorator<O>) clone; + } catch (Exception e) { + throw new IllegalStateException("Could not clone decorator " + decorator, e); + } + + } + if (decorator instanceof MultiJXPathDecorator<?>) { + + separator = ((MultiJXPathDecorator<?>) decorator).getSeparator(); + separatorReplacement = ((MultiJXPathDecorator<?>) decorator).getSeparatorReplacement(); + + } else { + + separator = "??" + new Date().getTime(); + separatorReplacement = " - "; + } + + return DecoratorUtil.newMultiJXPathDecorator( + decorator.getType(), + decorator.getInitialExpression(), + separator, + separatorReplacement + ); + } + + public static abstract class PopupHandler implements Runnable { + + public static final Log log = LogFactory.getLog(PopupHandler.class); + + public abstract JPopupMenu getPopup(); + + public abstract JComponent getInvoker(); + + @Override + public void run() { + + updatePopup(); + + Dimension dim = getPopup().getPreferredSize(); + + JComponent invoker = getInvoker(); + getPopup().show( + invoker, + (int) (invoker.getPreferredSize().getWidth() - dim.getWidth()), + invoker.getHeight() + ); + } + + /** Toggle the popup visible state. */ + public void togglePopup() { + boolean newValue = !getPopup().isVisible(); + + if (log.isTraceEnabled()) { + log.trace(newValue); + } + + if (!newValue) { + if (getPopup() != null) { + getPopup().setVisible(false); + } + return; + } + SwingUtilities.invokeLater(this); + } + + protected void updatePopup() { + getPopup().pack(); + } + + /** + * Creation de l'ui pour modifier le décorateur. + * + * @param selectedTip + * @param notSelectedTip + * @param i18nPrefix + * @param title + * @param indexes + * @param popupLabel + * @param sortUp + * @param sortDown + * @param decorator le decorateur a utiliser + */ + public void preparePopup(String selectedTip, + String notSelectedTip, + String i18nPrefix, + String title, + ButtonGroup indexes, + JSeparator popupSeparator, + JLabel popupLabel, + AbstractButton sortUp, + AbstractButton sortDown, + MultiJXPathDecorator<?> decorator) { + if (selectedTip == null) { + // use default selected tip text + selectedTip = DEFAULT_SELECTED_TOOLTIP; + } + if (notSelectedTip == null) { + // use default selected tip text + notSelectedTip = DEFAULT_NOT_SELECTED_TOOLTIP; + } + JPopupMenu popup = getPopup(); + + //Container container = ui.getIndexesContainer(); + + int nbContext = decorator.getNbContext(); + if (nbContext > 1) { + for (int i = 0; i < nbContext; i++) { + String property = i18nPrefix + decorator.getProperty(i); + String propertyI18n = t(property); + JRadioButtonMenuItem button = new JRadioButtonMenuItem(propertyI18n); + button.putClientProperty(JAXXButtonGroup.BUTTON8GROUP_CLIENT_PROPERTY, indexes); + button.putClientProperty(JAXXButtonGroup.VALUE_CLIENT_PROPERTY, i); + popup.add(button); + if (selectedTip != null) { + button.putClientProperty(JAXXButtonGroup.SELECTED_TIP_CLIENT_PROPERTY, t(selectedTip, propertyI18n)); + } + if (notSelectedTip != null) { + button.putClientProperty(JAXXButtonGroup.NOT_SELECTED_TIP_CLIENT_PROPERTY, t(notSelectedTip, propertyI18n)); + } + button.setSelected(false); + indexes.add(button); + } + } + if (title == null) { + // use default popup title + title = DEFAULT_POPUP_LABEL; + + Class<?> type = decorator.getType(); + String beanI18nKey; + if (type == null) { + beanI18nKey = n("bean.unknown.type"); + } else { + beanI18nKey = i18nPrefix + Introspector.decapitalize(type.getSimpleName()); + } + String beanI18n = t(beanI18nKey); + title = t(title, beanI18n); + } else { + title = t(title); + } + + sortDown.putClientProperty(JAXXButtonGroup.SELECTED_TIP_CLIENT_PROPERTY, t("bean.sort.down.tip")); + sortDown.putClientProperty(JAXXButtonGroup.NOT_SELECTED_TIP_CLIENT_PROPERTY, t("bean.sort.down.toSelect.tip")); + + sortUp.putClientProperty(JAXXButtonGroup.SELECTED_TIP_CLIENT_PROPERTY, t("bean.sort.up.tip")); + sortUp.putClientProperty(JAXXButtonGroup.NOT_SELECTED_TIP_CLIENT_PROPERTY, t("bean.sort.up.toSelect.tip")); + + if (nbContext < 2) { + getPopup().remove(popupSeparator); + getPopup().remove(popupLabel); + } + popupLabel.setText(title); + getPopup().setLabel(title); + getPopup().invalidate(); + } + } + + + //these keys were pulled from BasicComboBoxUI from Sun JDK 1.6.0_20 + + private static final List<String> COMBO_BOX_ACTIONS = unmodifiableList(asList("selectNext", + "selectNext2", "selectPrevious", "selectPrevious2", "pageDownPassThrough", + "pageUpPassThrough", "homePassThrough", "endPassThrough")); +} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/package.html b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/package.html similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/package.html rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/bean/package.html diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/cell/DateCellEditor.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/cell/DateCellEditor.java new file mode 100644 index 0000000..168a7f0 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/cell/DateCellEditor.java @@ -0,0 +1,53 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.editor.cell; + +import java.awt.Component; +import java.util.Date; +import javax.swing.AbstractCellEditor; +import javax.swing.JTable; +import javax.swing.table.TableCellEditor; +import org.nuiton.jaxx.runtime.swing.JAXXDatePicker; + +/** + * @author Sylvain Lletellier + */ +public class DateCellEditor extends AbstractCellEditor + implements TableCellEditor { + + protected JAXXDatePicker datePicker; + + public DateCellEditor() { + datePicker = new JAXXDatePicker(); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + datePicker.setDate((Date) value); + return datePicker; + } + + @Override + public Object getCellEditorValue() { + return datePicker.getDate(); + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/cell/FileCellEditor.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/cell/FileCellEditor.java new file mode 100644 index 0000000..89bb70a --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/cell/FileCellEditor.java @@ -0,0 +1,71 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.editor.cell; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import javax.swing.AbstractCellEditor; +import javax.swing.JTable; +import javax.swing.table.TableCellEditor; +import org.nuiton.jaxx.runtime.swing.editor.FileEditor; + +/** + * @author Sylvain Lletellier + */ +public class FileCellEditor extends AbstractCellEditor + implements TableCellEditor { + + protected FileEditor fileEditor; + + public FileCellEditor() { + setFileEditor(new FileEditor()); + } + + public FileCellEditor(FileEditor editor) { + setFileEditor(editor); + } + + public void setFileEditor(FileEditor fileEditor) { + this.fileEditor = fileEditor; + fileEditor.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + fireEditingStopped(); + } + }); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + File file = (File) value; + fileEditor.setSelectedFile(file); + return fileEditor; + } + + @Override + public Object getCellEditorValue() { + return fileEditor.getSelectedFile(); + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/cell/KeyStrokeCellEditor.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/cell/KeyStrokeCellEditor.java new file mode 100644 index 0000000..6d13ee4 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/cell/KeyStrokeCellEditor.java @@ -0,0 +1,62 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.editor.cell; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.AbstractCellEditor; +import javax.swing.JTable; +import javax.swing.KeyStroke; +import javax.swing.table.TableCellEditor; +import org.nuiton.jaxx.runtime.swing.editor.KeyStrokeEditor; + +/** + * @author Sylvain Lletellier + */ +public class KeyStrokeCellEditor extends AbstractCellEditor + implements TableCellEditor { + + protected KeyStrokeEditor keyStrokeEditor; + + public KeyStrokeCellEditor() { + keyStrokeEditor = new KeyStrokeEditor(); + keyStrokeEditor.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + fireEditingStopped(); + } + }); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + keyStrokeEditor.setKeyStroke((KeyStroke) value); + return keyStrokeEditor; + } + + @Override + public Object getCellEditorValue() { + return keyStrokeEditor.getKeyStroke(); + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/cell/NumberCellEditor.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/cell/NumberCellEditor.java new file mode 100644 index 0000000..cacc83b --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/cell/NumberCellEditor.java @@ -0,0 +1,131 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.editor.cell; + +import java.awt.Component; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import javax.swing.AbstractCellEditor; +import javax.swing.JTable; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; +import javax.swing.table.TableCellEditor; +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.swing.editor.NumberEditor; + +/** + * @author Sylvain Lletellier + * @deprecated since 2.17, prefer use {@code org.nuiton.jaxx.widgets.editor.cell.NumberCellEditor}. + */ +@Deprecated +public class NumberCellEditor<E extends Number> extends AbstractCellEditor + implements TableCellEditor, FocusListener, AncestorListener { + + private static final long serialVersionUID = 1L; + + protected final NumberEditor numberEditor; + + /** constructor */ + public NumberCellEditor(Class<E> type, boolean useSign) { + numberEditor = new NumberEditor(); + numberEditor.getTextField().setHorizontalAlignment(SwingConstants.RIGHT); + numberEditor.getTextField().setBorder(null); + numberEditor.getTextField().addFocusListener(this); + numberEditor.getTextField().addAncestorListener(this); + + numberEditor.setModelType(type); + + numberEditor.setUseSign(useSign); + numberEditor.init(); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, + boolean isSelected, int row, int column) { + + E number = (E) value; + numberEditor.setModel(number); + numberEditor.setModelText(JAXXUtil.getStringValue(number)); + return numberEditor; + } + + public NumberEditor getNumberEditor() { + return numberEditor; + } + + @Override + public E getCellEditorValue() { + return (E)numberEditor.getModel(); + } + + @Override + public void focusGained(FocusEvent e) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + numberEditor.getTextField().requestFocus(); + numberEditor.getTextField().selectAll(); + } + }); + } + + @Override + public void focusLost(FocusEvent e) { + // commenting the next line fixes http://www.nuiton.org/issues/3517 and http://www.nuiton.org/issues/3518 +// cancelCellEditing(); + } + + @Override + public void ancestorAdded(AncestorEvent event) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + numberEditor.getTextField().requestFocus(); + numberEditor.getTextField().selectAll(); + } + }); + } + + @Override + public void ancestorRemoved(AncestorEvent event) { + } + + @Override + public void ancestorMoved(AncestorEvent event) { + } + + @Override + public boolean stopCellEditing() { + boolean result = super.stopCellEditing(); + // Reset previous data to avoid keeping it on other cell edition + if (result) { + numberEditor.setModel(null); + // Use empty string, otherwise there is a NPE in NumberEditorHandler + numberEditor.setModelText(""); + // force binding, I do not know why the textfield text is not emptied + // if we do not force it + numberEditor.applyDataBinding(NumberEditor.BINDING_TEXT_FIELD_TEXT); + } + return result; + } + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinate.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinate.java new file mode 100644 index 0000000..62b3fb9 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinate.java @@ -0,0 +1,336 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.jdesktop.beans.AbstractSerializableBean; + +import java.util.regex.Pattern; + +/** + * Geo coordinate in degree decimal, minute format. + * + * Created on 10/23/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class DmdCoordinate extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + public static final String COORDINATE_STRING_PATTERN = "%s%s°%s'%s"; + + public static final Pattern COORDINATE_PATTERN = + Pattern.compile("(.*)°(.*)'(.*)"); + + public static final String PROPERTY_SIGN = "sign"; + + public static final String PROPERTY_DEGREE = "degree"; + + public static final String PROPERTY_MINUTE = "minute"; + + public static final String PROPERTY_DECIMAL = "decimal"; + + protected boolean sign; + + protected Integer degree; + + protected Integer minute; + + protected Integer decimal; + + public static DmdCoordinate empty() { + return new DmdCoordinate(); + } + + /** + * Methode statique de fabrique de position a partir d'un autre {@link DmdCoordinate}. + * + * Note : Si la valeur vaut <code>null</code>, alors on + * reinitialise les composants de la position a <code>null</code> et la + * methode {@link #isNull()} vaudra alors {@code true}. + * + * @param decimal la valeur au format decimal + * @return une nouvelle instance de position convertie + */ + public static DmdCoordinate valueOf(DmdCoordinate decimal) { + DmdCoordinate r = empty(); + if (decimal != null) { + r.setSign(decimal.isSign()); + r.setDegree(decimal.getDegree()); + r.setMinute(decimal.getMinute()); + r.setDecimal(decimal.getDecimal()); + } + return r; + } + + /** + * Methode statique de fabrique de position a partir d'une valeur du format + * decimal. + * + * Note : Si la valeur (au format decimal) vaut <code>null</code>, alors on + * reinitialise les composants de la position a <code>null</code> et la + * methode {@link #isNull()} vaudra alors {@code true}. + * + * @param decimal la valeur au format decimal + * @return une nouvelle instance de position convertie + */ + public static DmdCoordinate valueOf(Float decimal) { + DmdCoordinate r = new DmdCoordinate(); + r.fromDecimal(decimal); + return r; + } + + /** + * Methode statique de fabrique de position a partir d'une valeur du format + * degre décimale minute. + * + * @param d la valeur des degres + * @param m la valeur des minutes + * @param dc la valeur des décimales de minutes + * @return une nouvelle instance de position convertie + */ + public static DmdCoordinate valueOf(boolean sign, + Integer d, + Integer m, + Integer dc) { + DmdCoordinate r = new DmdCoordinate(); + r.setSign(sign); + r.setDegree(d); + r.setMinute(m); + r.setDecimal(dc); + return r; + } + + public boolean isSign() { + return sign; + } + + public Integer getDegree() { + return degree; + } + + public Integer getMinute() { + return minute; + } + + public Integer getDecimal() { + return decimal; + } + + public void setSign(boolean sign) { + Object oldValue = isSign(); + this.sign = sign; + firePropertyChange(PROPERTY_SIGN, oldValue, sign); + } + + public void setDegree(Integer degree) { + Object oldValue = getDegree(); + this.degree = degree; + firePropertyChange(PROPERTY_DEGREE, oldValue, degree); + } + + public void setMinute(Integer minute) { + Object oldValue = getMinute(); + this.minute = minute; + firePropertyChange(PROPERTY_MINUTE, oldValue, minute); + } + + public void setDecimal(Integer decimal) { + Object oldValue = getDecimal(); + this.decimal = decimal; + firePropertyChange(PROPERTY_DECIMAL, oldValue, decimal); + } + + /** + * @return {@code true} si aucune composante n'est renseignée, + * {@code false} autrement. + */ + public boolean isNull() { + return degree == null && minute == null && decimal == null; + } + + public boolean isDegreeNull() { + return degree == null || degree == 0; + } + + public boolean isMinuteNull() { + return minute == null || minute == 0; + } + + public boolean isDecimalNull() { + return decimal == null || decimal == 0; + } + + /** + * Mets a jour les composants de la position a partir d'une valeur decimal. + * + * Note : Si la valeur (au format decimal) vaut <code>null</code>, alors on + * reinitialise les composants de la position a <code>null</code> et la + * methode {@link #isNull()} vaudra alors {@code true}. + * + * @param decimalValue la valeur decimale a convertir (qui peut etre nulle). + */ + public void fromDecimal(Float decimalValue) { + Integer d = null; + Integer m = null; + Integer dc = null; + boolean si = false; + if (decimalValue != null) { + si = decimalValue < 0; + + float absDecimal = Math.abs(decimalValue); + + d = (int) (Math.round(absDecimal + 0.5) - 1); + int rest = Math.round(100 * 60.0f * (absDecimal - d)); + if (rest > 0) { + m = rest / 100; + dc = (rest - m * 100); + } + } + + degree = d; + minute = m; + decimal = dc; + sign = si; + + if (decimal != null) { + removeTrailingZero(); + } + } + + public Float toDecimal() { + if (isNull()) { + return null; + } + Integer d = getNotNullDegree(); + Integer m = getNotNullMinute(); + Integer dc = getNotNullDecimal(); + Float result = Float.valueOf(d); + result += (m + (dc / 100f)) / 60.0f; + if (sign) { + result *= -1; + } + return result; + } + + public void addTrailingZero() { + + if (degree == null) { + degree = 0; + } + if (minute == null) { + minute = 0; + } + if (decimal == null) { + decimal = 0; + } + } + + public void removeTrailingZero() { + if (degree != null && degree == 0) { + degree = null; + } + if (minute != null && minute == 0) { + minute = null; + } + if (decimal != null && decimal == 0) { + decimal = null; + } + } + + public Integer getSignedDegree() { + Integer result = null; + if (!isDegreeNull()) { + result = degree; + if (isSign()) { + result *= -1; + } + } + return result; + } + + public int getNotNullDegree() { + return isDegreeNull() ? 0 : degree; + } + + public int getNotNullMinute() { + return isMinuteNull() ? 0 : minute; + } + + public int getNotNullDecimal() { + return isDecimalNull() ? 0 : decimal; + } + + public boolean isLatitudeDegreeValid() { + return isDegreeValid(false); + } + + public boolean isLongitudeDegreeValid() { + return isDegreeValid(true); + } + + public boolean isMinuteValid() { + boolean result = true; + if (!isMinuteNull()) { + if (minute == 60) { + + // can not have decimal + result = isDecimalNull(); + } else { + result = 0 <= minute && minute < 60; + } + } + return result; + } + + public boolean isDecimalValid() { + return isDecimalNull() || (0 <= decimal && decimal < 100); + } + + @Override + public String toString() { + return "DmdCoordinateComponent{" + + "sign=" + sign + + ", degree=" + degree + + ", minute=" + minute + + ", decimal=" + decimal + + '}'; + } + + protected boolean isDegreeValid(boolean longitude) { + boolean result = true; + if (!isDegreeNull()) { + int bound = longitude ? 180 : 90; + if (bound == degree) { + + // can not have minute nor decimal + result = isMinuteNull() && isDecimalNull(); + } else { + result = 0 <= degree && degree < bound; + } + } + return result; + } + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateConverter.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateConverter.java new file mode 100644 index 0000000..7fd3e2d --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateConverter.java @@ -0,0 +1,143 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.beanutils.ConversionException; +import org.apache.commons.lang3.StringUtils; +import org.nuiton.converter.NuitonConverter; + +import java.util.regex.Matcher; + +import static org.nuiton.i18n.I18n.t; + +/** + * Created on 11/25/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class DmdCoordinateConverter implements NuitonConverter<DmdCoordinate> { + + protected boolean useSign; + + protected boolean forLongitude; + + public void setUseSign(boolean useSign) { + this.useSign = useSign; + } + + public void setForLongitude(boolean forLongitude) { + this.forLongitude = forLongitude; + } + + @Override + public <T> T convert(Class<T> aClass, Object value) { + + if (!isEnabled(aClass)) { + throw new ConversionException( + t("jaxx.error.no.convertor.coordinateDmd", value)); + } + + Object result = null; + + if (value == null) { + + if (aClass.equals(String.class)) { + + result = String.format( + DmdCoordinate.COORDINATE_STRING_PATTERN, + useSign ? "-" : "", + StringUtils.leftPad("", forLongitude ? 3 : 2, ' '), + StringUtils.leftPad("", 2, ' '), + StringUtils.leftPad("", 2, ' ')); + } + } else { + + if (aClass.equals(value.getClass())) { + + // same class, no convertion to do + result = value; + } else if (value instanceof String) { + + // String to Value + + Matcher matcher = DmdCoordinate.COORDINATE_PATTERN.matcher((String) value); + + if (matcher.matches()) { + + String degresStr = matcher.group(1).replaceAll("\\s", ""); + String minutesStr = matcher.group(2).replaceAll("\\s", ""); + String decimalesStr = matcher.group(3).replaceAll("\\s", ""); + + Integer degre = degresStr.isEmpty() || "-".equals(degresStr) ? null : Math.abs(Integer.valueOf(degresStr)); + Integer minutes = minutesStr.isEmpty() ? null : Integer.valueOf(minutesStr); + Integer decimal = decimalesStr.isEmpty() ? null : Integer.valueOf(decimalesStr); + + boolean signed = degresStr.contains("-"); + result = DmdCoordinate.valueOf(signed, + degre, + minutes, + decimal); + } + + } else if (value instanceof DmdCoordinate) { + + // Value to String + + DmdCoordinate coordinate = (DmdCoordinate) value; + + boolean sign = coordinate.isSign(); + String signStr = sign ? "-" : ""; + + Integer degree = coordinate.getDegree(); + String degreeStr = degree == null ? "" : degree.toString(); + + Integer minute = coordinate.getMinute(); + String minuteStr = minute == null ? "" : minute.toString(); + + Integer decimal = coordinate.getDecimal(); + String decimalStr = decimal == null ? "" : decimal.toString(); + + result = String.format( + DmdCoordinate.COORDINATE_STRING_PATTERN, + signStr, + StringUtils.leftPad(degreeStr, forLongitude ? 3 : 2, ' '), + StringUtils.leftPad(minuteStr, 2, ' '), + StringUtils.leftPad(decimalStr, 2, ' ')); + } + } + return aClass.cast(result); + } + + protected boolean isEnabled(Class<?> aClass) { + return String.class.isAssignableFrom(aClass) || + DmdCoordinate.class.isAssignableFrom(aClass); + } + + @Override + public Class<DmdCoordinate> getType() { + return DmdCoordinate.class; + } + +} + diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.jaxx diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.jcss b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.jcss similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.jcss rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.jcss diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorHandler.java new file mode 100644 index 0000000..aba20a5 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorHandler.java @@ -0,0 +1,306 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.beans.BeanUtil; + +import javax.swing.JFormattedTextField; +import javax.swing.text.DefaultFormatterFactory; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Method; +import java.text.ParseException; + +/** + * Created on 10/16/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class DmdCoordinateEditorHandler implements UIHandler<DmdCoordinateEditor> { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(DmdCoordinateEditorHandler.class); + + private DmdCoordinateEditor ui; + + protected Method signMutator; + + protected Method degreMutator; + + protected Method minuteMutator; + + protected Method decimalMutator; + + protected boolean valueIsAdjusting; + + protected boolean valueModelIsAdjusting; + + protected DmdCoordinateConverter signedConverter; + + protected DmdCoordinateConverter unsignedConverter; + + protected DefaultFormatterFactory signedFormatterFactory; + + protected DefaultFormatterFactory unsignedFormatterFactory; + + @Override + public void beforeInit(DmdCoordinateEditor ui) { + this.ui = ui; + // can't use the one from ConverterUtil since we deal with some internal states + this.signedConverter = new DmdCoordinateConverter(); + this.signedConverter.setUseSign(true); + this.unsignedConverter = new DmdCoordinateConverter(); + } + + @Override + public void afterInit(DmdCoordinateEditor ui) { + // nothing special to do here + } + + public void init(boolean longitudeEditor) { + + final DmdCoordinateEditorModel model = ui.getModel(); + + Preconditions.checkNotNull(model.getBean(), "could not find bean in " + ui); + Preconditions.checkNotNull(model.getPropertySign(), "could not find propertySign in " + ui); + Preconditions.checkNotNull(model.getPropertyDegree(), "could not find propertyDegree in " + ui); + Preconditions.checkNotNull(model.getPropertyMinute(), "could not find propertyMinute in " + ui); + Preconditions.checkNotNull(model.getPropertyDecimal(), "could not find propertyDecimal in " + ui); + + Object bean = model.getBean(); + signMutator = BeanUtil.getMutator(bean, model.getPropertySign()); + Preconditions.checkNotNull(signMutator, "could not find mutator for " + model.getPropertySign()); + + degreMutator = BeanUtil.getMutator(bean, model.getPropertyDegree()); + Preconditions.checkNotNull(degreMutator, "could not find mutator for " + model.getPropertyDegree()); + + minuteMutator = BeanUtil.getMutator(bean, model.getPropertyMinute()); + Preconditions.checkNotNull(minuteMutator, "could not find mutator for " + model.getPropertyMinute()); + + decimalMutator = BeanUtil.getMutator(bean, model.getPropertyDecimal()); + Preconditions.checkNotNull(decimalMutator, "could not find mutator for " + model.getPropertyDecimal()); + + signedConverter.setForLongitude(longitudeEditor); + unsignedConverter.setForLongitude(longitudeEditor); + + { + // prepare unsigned formatter factory + String pattern = getMaskFormatterPattern(longitudeEditor, false); + MaskFormatterFromConverter<DmdCoordinate> maskFormatter; + try { + maskFormatter = MaskFormatterFromConverter.newFormatter( + DmdCoordinate.class, + pattern, unsignedConverter); + maskFormatter.setValidCharacters(" 01234567890"); + maskFormatter.setCommitsOnValidEdit(true); + unsignedFormatterFactory = new DefaultFormatterFactory(maskFormatter); + } catch (ParseException e) { + // can't happen here + throw new RuntimeException(e); + } + } + { + // prepare signed formatter factory + String pattern = getMaskFormatterPattern(longitudeEditor, true); + MaskFormatterFromConverter<DmdCoordinate> maskFormatter; + try { + maskFormatter = MaskFormatterFromConverter.newFormatter( + DmdCoordinate.class, + pattern, signedConverter); + maskFormatter.setValidCharacters(" 01234567890"); + maskFormatter.setCommitsOnValidEdit(true); + signedFormatterFactory = new DefaultFormatterFactory(maskFormatter); + } catch (ParseException e) { + // can't happen here + throw new RuntimeException(e); + } + } + + JFormattedTextField editor = ui.getEditor(); + editor.setFormatterFactory(model.isSign() ? + signedFormatterFactory : + unsignedFormatterFactory); + editor.setFocusLostBehavior(JFormattedTextField.COMMIT); + + // When editor changes his value, propagate it to model + editor.addPropertyChangeListener("value", new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + DmdCoordinate newValue = (DmdCoordinate) evt.getNewValue(); + if (log.isDebugEnabled()) { + log.debug("Value has changed: " + newValue); + } + model.setValue(newValue); + } + }); + + // When model sign changed, let's push it back in bean + model.addPropertyChangeListener( + DmdCoordinateEditorModel.PROPERTY_SIGN, + new ModelPropertyChangeListener(model, signMutator)); + + // When model degre changed, let's push it back in bean + model.addPropertyChangeListener( + DmdCoordinateEditorModel.PROPERTY_DEGREE, + new ModelPropertyChangeListener(model, degreMutator)); + + // When model minute changed, let's push it back in bean + model.addPropertyChangeListener( + DmdCoordinateEditorModel.PROPERTY_MINUTE, + new ModelPropertyChangeListener(model, minuteMutator)); + + // When model decimal changed, let's push it back in bean + model.addPropertyChangeListener( + DmdCoordinateEditorModel.PROPERTY_DECIMAL, + new ModelPropertyChangeListener(model, decimalMutator)); + } + + public void setValue(DmdCoordinate value, boolean pushToModel) { + + if (valueModelIsAdjusting) { + // avoid re-entrant code + return; + } + + valueIsAdjusting = !pushToModel; + + try { + ui.getEditor().setValue(value); + } finally { + valueIsAdjusting = false; + } + } + + public void resetEditor() { + // set null value to model + setValue(null, true); + + // use back unsigned format + ui.getEditor().setFormatterFactory(unsignedFormatterFactory); + } + + public void onKeyReleased(KeyEvent e) { + + JFormattedTextField source = (JFormattedTextField) e.getSource(); + + char keyChar = e.getKeyChar(); + int caretPosition = source.getCaretPosition(); + if (log.isDebugEnabled()) { + log.debug("Key pressed: " + keyChar + " (caret position: " + caretPosition + ")"); + } + + if (keyChar == '-') { + + DmdCoordinate value = (DmdCoordinate) source.getValue(); + + DefaultFormatterFactory newFactory; + + // try to switch unsigned to signed + + boolean useSign = ui.getModel().isSign(); + + if (useSign) { + + if (log.isDebugEnabled()) { + log.debug("Switch to unsigned"); + } + + newFactory = unsignedFormatterFactory; + + // remove a sign + caretPosition--; + } else { + // switch to signed + if (log.isDebugEnabled()) { + log.debug("Switch to signed"); + } + newFactory = signedFormatterFactory; + + // add a sign + caretPosition++; + } + + DmdCoordinate newValue = DmdCoordinate.valueOf(value); + newValue.setSign(!useSign); + + source.setFormatterFactory(newFactory); + source.setValue(newValue); + + e.consume(); + + source.setCaretPosition(caretPosition); + } + } + + protected String getMaskFormatterPattern(boolean longitudeEditor, boolean useSign) { + String pattern = "**°**''**"; + if (longitudeEditor) { + // add one more degre + pattern = "*" + pattern; + } + if (useSign) { + pattern = "-" + pattern; + } + return pattern; + } + + private class ModelPropertyChangeListener implements PropertyChangeListener { + + private final DmdCoordinateEditorModel model; + + private final Method mutator; + + private ModelPropertyChangeListener(DmdCoordinateEditorModel model, + Method mutator) { + this.model = model; + this.mutator = mutator; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (!valueIsAdjusting) { + Object newValue = evt.getNewValue(); + + try { + + valueModelIsAdjusting = true; + try { + mutator.invoke(model.getBean(), newValue); + } finally { + valueModelIsAdjusting = false; + } + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorModel.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorModel.java new file mode 100644 index 0000000..e3a84db --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorModel.java @@ -0,0 +1,122 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import java.io.Serializable; + +/** + * Created on 10/16/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class DmdCoordinateEditorModel extends DmdCoordinate { + + public static final String PROPERTY_BEAN = "bean"; + + public static final String PROPERTY_PROPERTY_SIGN = "propertySign"; + + public static final String PROPERTY_PROPERTY_DEGREE = "propertyDegree"; + + public static final String PROPERTY_PROPERTY_MINUTE = "propertyMinute"; + + public static final String PROPERTY_PROPERTY_DECIMAL = "propertyDecimal"; + + private static final long serialVersionUID = 1L; + + /** Bean where to push data. */ + protected Serializable bean; + + /** Name of the property of the bean to fire the change of the {@link #sign}. */ + protected String propertySign; + + /** Name of the property of the bean to fire the change of the {@link #degree}. */ + protected String propertyDegre; + + /** Name of the property of the bean to fire the change of the {@link #minute}. */ + protected String propertyMinute; + + /** Name of the property of the bean to fire the change of the {@link #decimal}. */ + protected String propertyDecimal; + + public Serializable getBean() { + return bean; + } + + public void setBean(Serializable bean) { + Object oldValue = getBean(); + this.bean = bean; + firePropertyChange(PROPERTY_BEAN, oldValue, bean); + } + + public String getPropertySign() { + return propertySign; + } + + public void setPropertySign(String propertySign) { + Object oldValue = getPropertySign(); + this.propertySign = propertySign; + firePropertyChange(PROPERTY_PROPERTY_SIGN, oldValue, propertySign); + } + + public String getPropertyDegree() { + return propertyDegre; + } + + public void setPropertyDegree(String propertyDegree) { + Object oldValue = getPropertyDegree(); + this.propertyDegre = propertyDegree; + firePropertyChange(PROPERTY_PROPERTY_DEGREE, oldValue, propertyDegree); + } + + public String getPropertyMinute() { + return propertyMinute; + } + + public void setPropertyMinute(String propertyMinute) { + Object oldValue = getPropertyMinute(); + this.propertyMinute = propertyMinute; + firePropertyChange(PROPERTY_PROPERTY_MINUTE, oldValue, propertyMinute); + } + + public String getPropertyDecimal() { + return propertyDecimal; + } + + public void setPropertyDecimal(String propertyDecimal) { + Object oldValue = getPropertyDecimal(); + this.propertyDecimal = propertyDecimal; + firePropertyChange(PROPERTY_PROPERTY_DECIMAL, oldValue, propertyDecimal); + } + + public void setValue(DmdCoordinate value) { + setSign(value != null && value.isSign()); + setDegree(value == null ? null : value.getDegree()); + setMinute(value == null ? null : value.getMinute()); + setDecimal(value == null ? null : value.getDecimal()); + } + + public String getStringPattern() { + return COORDINATE_STRING_PATTERN; + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinate.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinate.java new file mode 100644 index 0000000..51615ec --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinate.java @@ -0,0 +1,364 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.jdesktop.beans.AbstractSerializableBean; + +import java.util.regex.Pattern; + +/** + * Geo coordinate in degree, minute, second format. + * + * Created on 10/23/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class DmsCoordinate extends AbstractSerializableBean { + + public static final String COORDINATE_STRING_PATTERN = "%s%s°%s'%s''"; + + public static final Pattern COORDINATE_PATTERN = + Pattern.compile("(.*)°(.*)'(.*)''"); + + private static final long serialVersionUID = 1L; + + public static final String PROPERTY_SIGN = "sign"; + + public static final String PROPERTY_DEGREE = "degree"; + + public static final String PROPERTY_MINUTE = "minute"; + + public static final String PROPERTY_SECOND = "second"; + + protected boolean sign; + + protected Integer degree; + + protected Integer minute; + + protected Integer second; + + public static DmsCoordinate empty() { + return new DmsCoordinate(); + } + + /** + * Methode statique de fabrique de position a partir d'un autre {@link DmsCoordinate}. + * + * Note : Si la valeur vaut <code>null</code>, alors on + * reinitialise les composants de la position a <code>null</code> et la + * methode {@link #isNull()} vaudra alors {@code true}. + * + * @param decimal la valeur au format decimal + * @return une nouvelle instance de position convertie + */ + public static DmsCoordinate valueOf(DmsCoordinate decimal) { + DmsCoordinate r = new DmsCoordinate(); + if (decimal != null) { + r.setSign(decimal.isSign()); + r.setDegree(decimal.getDegree()); + r.setMinute(decimal.getMinute()); + r.setSecond(decimal.getSecond()); + } + return r; + } + + /** + * Methode statique de fabrique de position a partir d'une valeur du format + * decimal. + * + * Note : Si la valeur (au format decimal) vaut <code>null</code>, alors on + * reinitialise les composants de la position a <code>null</code> et la + * methode {@link #isNull()} vaudra alors {@code true}. + * + * @param decimal la valeur au format decimal + * @return une nouvelle instance de position convertie + */ + public static DmsCoordinate valueOf(Float decimal) { + DmsCoordinate r = new DmsCoordinate(); + r.fromDecimal(decimal); + return r; + } + + /** + * Methode statique de fabrique de position a partir d'une valeur du format + * degre-minute-seconde. + * + * @param d la valeur des degres + * @param m la valeur des minutes + * @param s la valeur des secondes + * @return une nouvelle instance de position convertie + */ + public static DmsCoordinate valueOf(boolean sign, Integer d, Integer m, Integer s) { + DmsCoordinate r = new DmsCoordinate(); + r.setSign(sign); + r.setDegree(d); + r.setMinute(m); + r.setSecond(s); + return r; + } + + public boolean isSign() { + return sign; + } + + public Integer getDegree() { + return degree; + } + + public Integer getMinute() { + return minute; + } + + public Integer getSecond() { + return second; + } + + public void setSign(boolean sign) { + Object oldValue = isSign(); + this.sign = sign; + firePropertyChange(PROPERTY_SIGN, oldValue, sign); + } + + public void setDegree(Integer degree) { + Object oldValue = getDegree(); + this.degree = degree; + firePropertyChange(PROPERTY_DEGREE, oldValue, degree); + } + + public void setMinute(Integer minute) { + Object oldValue = getMinute(); + this.minute = minute; + firePropertyChange(PROPERTY_MINUTE, oldValue, minute); + } + + public void setSecond(Integer second) { + Object oldValue = getSecond(); + this.second = second; + firePropertyChange(PROPERTY_SECOND, oldValue, second); + } + + public boolean isDegreeNull() { + return degree == null || degree == 0; + } + + public boolean isMinuteNull() { + return minute == null || minute == 0; + } + + public boolean isSecondNull() { + return second == null || second == 0; + } + + /** + * @return {@code true} si aucune composante n'est renseignée, + * {@code false} autrement. + */ + public boolean isNull() { + return degree == null && minute == null && second == null; + } + + /** + * Mets a jour les composants de la position a partir d'une valeur decimal. + * + * Note : Si la valeur (au format decimal) vaut <code>null</code>, alors on + * reinitialise les composants de la position a <code>null</code> et la + * methode {@link #isNull()} vaudra alors {@code true}. + * + * @param decimal la valeur decimale a convertir (qui peut etre nulle). + */ + public void fromDecimal(Float decimal) { + Integer d = null; + Integer m = null; + Integer s = null; + boolean si = false; + if (decimal != null) { + si = decimal < 0; + + decimal = Math.abs(decimal); + int remain = 0; + + d = (int) (Math.round(decimal + 0.5) - 1); + m = 0; + s = 0; + decimal = 60.0f * (decimal - d); + if (decimal > 0) { + m = (int) (Math.round(decimal + 0.5) - 1); + decimal = 60 * (decimal - m); + if (decimal > 0) { + s = (int) (Math.round(decimal + 0.5) - 1); + remain = (int) (10 * (decimal - s)); + } + } + if (remain > 9) { + s++; + } + if (s == 60) { + m++; + s = 0; + } + if (m == 60) { + d++; + m = 0; + } + } + + degree = d; + minute = m; + second = s; + sign = si; + + if (decimal != null) { + removeTrailingZero(); + } + } + + public Float toDecimal() { + if (isNull()) { + return null; + } + Integer d = getNotNullDegree(); + Integer m = getNotNullMinute(); + + Integer s = getNotNullSecond(); + + Float result = Float.valueOf(d); + + if (m > 0) { + result += (float) m / 60; + if (s == 0) { + result += 0.5f / 3600; + } + } + if (s > 0) { + result += ((float) s + 0.5f) / 3600; + } + + if (sign) { + result *= -1; + } + return result; + } + + public DmsCoordinate addTrailingZero() { + if (degree == null) { + degree = 0; + } + if (minute == null) { + minute = 0; + } + if (second == null) { + second = 0; + } + return this; + } + + public DmsCoordinate removeTrailingZero() { + if (degree != null && degree == 0) { + degree = null; + } + if (minute != null && minute == 0) { + minute = null; + } + if (second != null && second == 0) { + second = null; + } + return this; + } + + public Integer getSignedDegree() { + Integer result = null; + if (!isDegreeNull()) { + result = degree; + if (isSign()) { + result *= -1; + } + } + return result; + } + + public int getNotNullDegree() { + return isDegreeNull() ? 0 : degree; + } + + public int getNotNullMinute() { + return isMinuteNull() ? 0 : minute; + } + + + public int getNotNullSecond() { + return isSecondNull() ? 0 : second; + } + + public boolean isLatitudeDegreeValid() { + return isDegreeValid(false); + } + + public boolean isLongitudeDegreeValid() { + return isDegreeValid(true); + } + + public boolean isMinuteValid() { + boolean result = true; + if (!isMinuteNull()) { + if (60 == minute) { + + // check minute and second are null + result = isSecondNull(); + } else { + result = 0 <= minute && minute < 60; + } + } + return result; + } + + public boolean isSecondValid() { + return isSecondNull() || (0 <= second && second < 60); + } + + @Override + public String toString() { + return "DmsCoordinateComponent{" + + "sign=" + sign + + ", degree=" + degree + + ", minute=" + minute + + ", second=" + second + + '}'; + } + + protected boolean isDegreeValid(boolean longitude) { + boolean result = true; + if (!isDegreeNull()) { + int bound = longitude ? 180 : 90; + if (bound == degree) { + + // check minute and second are null + result = isMinuteNull() && isSecondNull(); + } else { + result = degree < bound; + } + } + return result; + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateConverter.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateConverter.java new file mode 100644 index 0000000..84158f1 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateConverter.java @@ -0,0 +1,144 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.beanutils.ConversionException; +import org.apache.commons.lang3.StringUtils; +import org.nuiton.converter.NuitonConverter; + +import java.util.regex.Matcher; + +import static org.nuiton.i18n.I18n.t; + +/** + * Created on 11/25/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class DmsCoordinateConverter implements NuitonConverter<DmsCoordinate> { + + protected boolean useSign; + + protected boolean forLongitude; + + public void setUseSign(boolean useSign) { + this.useSign = useSign; + } + + public void setForLongitude(boolean forLongitude) { + this.forLongitude = forLongitude; + } + + @Override + public <T> T convert(Class<T> aClass, Object value) { + + if (!isEnabled(aClass)) { + throw new ConversionException( + t("jaxx.error.no.convertor.coordinateDms", value)); + } + + Object result = null; + + if (value == null) { + + if (aClass.equals(String.class)) { + + result = String.format( + DmsCoordinate.COORDINATE_STRING_PATTERN, + useSign ? "-" : "", + StringUtils.leftPad("", forLongitude ? 3 : 2, ' '), + StringUtils.leftPad("", 2, ' '), + StringUtils.leftPad("", 2, ' ')); + } + } else { + + if (aClass.equals(value.getClass())) { + + // same class, no convertion to do + result = value; + } else if (value instanceof String) { + + // String to Value + + Matcher matcher = DmsCoordinate.COORDINATE_PATTERN.matcher((String) value); + + if (matcher.matches()) { + + String degresStr = matcher.group(1).replaceAll("\\s", ""); + String minutesStr = matcher.group(2).replaceAll("\\s", ""); + String secondsStr = matcher.group(3).replaceAll("\\s", ""); + + Integer degre = degresStr.isEmpty() || "-".equals(degresStr) ? null : Math.abs(Integer.valueOf(degresStr)); + Integer minutes = minutesStr.isEmpty() ? null : Integer.valueOf(minutesStr); + Integer seconds = secondsStr.isEmpty() ? null : Integer.valueOf(secondsStr); + + boolean signed = degresStr.contains("-"); + result = DmsCoordinate.valueOf(signed, + degre, + minutes, + seconds); + } + + } else if (value instanceof DmsCoordinate) { + + // Value to String + + DmsCoordinate coordinate = (DmsCoordinate) value; + + boolean sign = coordinate.isSign(); + String signStr = sign ? "-" : ""; + + Integer degree = coordinate.getDegree(); + String degreeStr = degree == null ? "" : degree.toString(); + + Integer minute = coordinate.getMinute(); + String minuteStr = minute == null ? "" : minute.toString(); + + Integer second = coordinate.getSecond(); + String secondStr = second == null ? "" : second.toString(); + + result = String.format( + DmsCoordinate.COORDINATE_STRING_PATTERN, + signStr, + StringUtils.leftPad(degreeStr, forLongitude ? 3 : 2, ' '), + StringUtils.leftPad(minuteStr, 2, ' '), + StringUtils.leftPad(secondStr, 2, ' ')); + } + } + return aClass.cast(result); + + } + + protected boolean isEnabled(Class<?> aClass) { + return String.class.isAssignableFrom(aClass) || + DmsCoordinate.class.isAssignableFrom(aClass); + } + + @Override + public Class<DmsCoordinate> getType() { + return DmsCoordinate.class; + } + +} + diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.jaxx diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.jcss b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.jcss similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.jcss rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.jcss diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorHandler.java new file mode 100644 index 0000000..17bbefd --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorHandler.java @@ -0,0 +1,317 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import com.google.common.base.Preconditions; +import org.nuiton.jaxx.runtime.spi.UIHandler; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.beans.BeanUtil; + +import javax.swing.JFormattedTextField; +import javax.swing.text.DefaultFormatterFactory; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Method; +import java.text.ParseException; + +/** + * Created on 10/16/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class DmsCoordinateEditorHandler implements UIHandler<DmsCoordinateEditor>{ + + /** Logger. */ + private static final Log log = + LogFactory.getLog(DmsCoordinateEditorHandler.class); + + protected DmsCoordinateEditor ui; + + protected Method signMutator; + + protected Method degreMutator; + + protected Method minuteMutator; + + protected Method secondMutator; + + protected boolean valueIsAdjusting; + + protected boolean valueModelIsAdjusting; + + protected DmsCoordinateConverter signedConverter; + + protected DmsCoordinateConverter unsignedConverter; + + protected DefaultFormatterFactory signedFormatterFactory; + + protected DefaultFormatterFactory unsignedFormatterFactory; + +// public DmsCoordinateEditorHandler(DmsCoordinateEditor ui) { +// this.ui = ui; +// +// // can't use the one from ConverterUtil since we deal with some internal states +// this.signedConverter = new DmsCoordinateConverter(); +// this.signedConverter.setUseSign(true); +// this.unsignedConverter = new DmsCoordinateConverter(); +// } + + @Override + public void beforeInit(DmsCoordinateEditor ui) { + this.ui=ui; + // can't use the one from ConverterUtil since we deal with some internal states + this.signedConverter = new DmsCoordinateConverter(); + this.signedConverter.setUseSign(true); + this.unsignedConverter = new DmsCoordinateConverter(); + } + + @Override + public void afterInit(DmsCoordinateEditor ui) { + // nothing special to do here + } + + public void init(boolean longitudeEditor) { + + final DmsCoordinateEditorModel model = ui.getModel(); + + Preconditions.checkNotNull(model.getBean(), "could not find bean in " + ui); + Preconditions.checkNotNull(model.getPropertySign(), "could not find propertySign in " + ui); + Preconditions.checkNotNull(model.getPropertyDegree(), "could not find propertyDegree in " + ui); + Preconditions.checkNotNull(model.getPropertyMinute(), "could not find propertyMinute in " + ui); + Preconditions.checkNotNull(model.getPropertySecond(), "could not find propertySecond in " + ui); + + Object bean = model.getBean(); + signMutator = BeanUtil.getMutator(bean, model.getPropertySign()); + Preconditions.checkNotNull(signMutator, "could not find mutator for " + model.getPropertySign()); + + degreMutator = BeanUtil.getMutator(bean, model.getPropertyDegree()); + Preconditions.checkNotNull(degreMutator, "could not find mutator for " + model.getPropertyDegree()); + + minuteMutator = BeanUtil.getMutator(bean, model.getPropertyMinute()); + Preconditions.checkNotNull(minuteMutator, "could not find mutator for " + model.getPropertyMinute()); + + secondMutator = BeanUtil.getMutator(bean, model.getPropertySecond()); + Preconditions.checkNotNull(secondMutator, "could not find mutator for " + model.getPropertySecond()); + + signedConverter.setForLongitude(longitudeEditor); + unsignedConverter.setForLongitude(longitudeEditor); + + { + // prepare unsigned formatter factory + String pattern = getMaskFormatterPattern(longitudeEditor, false); + MaskFormatterFromConverter<DmsCoordinate> maskFormatter; + try { + maskFormatter = MaskFormatterFromConverter.newFormatter( + DmsCoordinate.class, + pattern, unsignedConverter); + maskFormatter.setValidCharacters(" 01234567890"); + maskFormatter.setCommitsOnValidEdit(true); + unsignedFormatterFactory = new DefaultFormatterFactory(maskFormatter); + } catch (ParseException e) { + // can't happen here + throw new RuntimeException(e); + } + } + { + // prepare signed formatter factory + String pattern = getMaskFormatterPattern(longitudeEditor, true); + MaskFormatterFromConverter<DmsCoordinate> maskFormatter; + try { + maskFormatter = MaskFormatterFromConverter.newFormatter( + DmsCoordinate.class, + pattern, signedConverter); + maskFormatter.setValidCharacters(" 01234567890"); + maskFormatter.setCommitsOnValidEdit(true); + signedFormatterFactory = new DefaultFormatterFactory(maskFormatter); + } catch (ParseException e) { + // can't happen here + throw new RuntimeException(e); + } + } + + JFormattedTextField editor = ui.getEditor(); + editor.setFormatterFactory(model.isSign() ? + signedFormatterFactory : + unsignedFormatterFactory); + editor.setFocusLostBehavior(JFormattedTextField.COMMIT); + + // When editor changes his value, propagate it to model + editor.addPropertyChangeListener("value", new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + DmsCoordinate newValue = (DmsCoordinate) evt.getNewValue(); + if (log.isDebugEnabled()) { + log.debug("Value has changed: " + newValue); + } + model.setValue(newValue); + } + }); + + // When model sign changed, let's push it back in bean + model.addPropertyChangeListener( + DmsCoordinateEditorModel.PROPERTY_SIGN, + new ModelPropertyChangeListener(model, signMutator)); + + // When model degre changed, let's push it back in bean + model.addPropertyChangeListener( + DmsCoordinateEditorModel.PROPERTY_DEGREE, + new ModelPropertyChangeListener(model, degreMutator)); + + // When model minute changed, let's push it back in bean + model.addPropertyChangeListener( + DmsCoordinateEditorModel.PROPERTY_MINUTE, + new ModelPropertyChangeListener(model, minuteMutator)); + + // When model second changed, let's push it back in bean + model.addPropertyChangeListener( + DmsCoordinateEditorModel.PROPERTY_SECOND, + new ModelPropertyChangeListener(model, secondMutator)); + } + + public void setValue(DmsCoordinate value, boolean pushToModel) { + + if (valueModelIsAdjusting) { + // avoid re-entrant code + return; + } + + valueIsAdjusting = !pushToModel; + + try { + ui.getEditor().setValue(value); + } finally { + valueIsAdjusting = false; + } + } + + public void resetEditor() { + + // set null value to model + setValue(null, true); + + // use back unsigned format + ui.getEditor().setFormatterFactory(unsignedFormatterFactory); + } + + public void onKeyReleased(KeyEvent e) { + + JFormattedTextField source = (JFormattedTextField) e.getSource(); + + char keyChar = e.getKeyChar(); + int caretPosition = source.getCaretPosition(); + if (log.isDebugEnabled()) { + log.debug("Key pressed: " + keyChar + " (caret position: " + caretPosition + ")"); + } + + if (keyChar == '-') { + + DmsCoordinate value = (DmsCoordinate) source.getValue(); + + DefaultFormatterFactory newFactory; + + // try to switch unsigned to signed + + boolean useSign = ui.getModel().isSign(); + + if (useSign) { + + if (log.isDebugEnabled()) { + log.debug("Switch to unsigned"); + } + + newFactory = unsignedFormatterFactory; + + // remove a sign + caretPosition--; + } else { + // switch to signed + if (log.isDebugEnabled()) { + log.debug("Switch to signed"); + } + newFactory = signedFormatterFactory; + + // add a sign + caretPosition++; + } + + DmsCoordinate newValue = DmsCoordinate.valueOf(value); + newValue.setSign(!useSign); + + source.setFormatterFactory(newFactory); + source.setValue(newValue); + + e.consume(); + + source.setCaretPosition(caretPosition); + } + } + + protected String getMaskFormatterPattern(boolean longitudeEditor, + boolean useSign) { + String pattern = "**°**''**''''"; + if (longitudeEditor) { + // add one more degre + pattern = "*" + pattern; + } + if (useSign) { + pattern = "-" + pattern; + } + return pattern; + } + + private class ModelPropertyChangeListener implements PropertyChangeListener { + + private final DmsCoordinateEditorModel model; + + private final Method mutator; + + private ModelPropertyChangeListener(DmsCoordinateEditorModel model, Method mutator) { + this.model = model; + this.mutator = mutator; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (!valueIsAdjusting) { + Object newValue = evt.getNewValue(); + + try { + + valueModelIsAdjusting = true; + try { + mutator.invoke(model.getBean(), newValue); + } finally { + valueModelIsAdjusting = false; + } + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorModel.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorModel.java new file mode 100644 index 0000000..b2b7f17 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorModel.java @@ -0,0 +1,122 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import java.io.Serializable; + +/** + * Created on 10/16/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class DmsCoordinateEditorModel extends DmsCoordinate { + + public static final String PROPERTY_BEAN = "bean"; + + public static final String PROPERTY_PROPERTY_SIGN = "propertySign"; + + public static final String PROPERTY_PROPERTY_DEGREE = "propertyDegree"; + + public static final String PROPERTY_PROPERTY_MINUTE = "propertyMinute"; + + public static final String PROPERTY_PROPERTY_SECOND = "propertySecond"; + + private static final long serialVersionUID = 1L; + + /** Bean where to push data. */ + protected Serializable bean; + + /** Name of the property of the bean to fire the change of the {@link #sign}. */ + protected String propertySign; + + /** Name of the property of the bean to fire the change of the {@link #degree}. */ + protected String propertyDegree; + + /** Name of the property of the bean to fire the change of the {@link #minute}. */ + protected String propertyMinute; + + /** Name of the property of the bean to fire the change of the {@link #second}. */ + protected String propertySecond; + + public Serializable getBean() { + return bean; + } + + public void setBean(Serializable bean) { + Object oldValue = getBean(); + this.bean = bean; + firePropertyChange(PROPERTY_BEAN, oldValue, bean); + } + + public String getPropertySign() { + return propertySign; + } + + public void setPropertySign(String propertySign) { + Object oldValue = getPropertySign(); + this.propertySign = propertySign; + firePropertyChange(PROPERTY_PROPERTY_SIGN, oldValue, propertySign); + } + + public String getPropertyDegree() { + return propertyDegree; + } + + public void setPropertyDegree(String propertyDegree) { + Object oldValue = getPropertyDegree(); + this.propertyDegree = propertyDegree; + firePropertyChange(PROPERTY_PROPERTY_DEGREE, oldValue, propertyDegree); + } + + public String getPropertyMinute() { + return propertyMinute; + } + + public void setPropertyMinute(String propertyMinute) { + Object oldValue = getPropertyMinute(); + this.propertyMinute = propertyMinute; + firePropertyChange(PROPERTY_PROPERTY_MINUTE, oldValue, propertyMinute); + } + + public String getPropertySecond() { + return propertySecond; + } + + public void setPropertySecond(String propertySecond) { + Object oldValue = getPropertySecond(); + this.propertySecond = propertySecond; + firePropertyChange(PROPERTY_PROPERTY_SECOND, oldValue, propertySecond); + } + + public void setValue(DmsCoordinate value) { + setSign(value != null && value.isSign()); + setDegree(value == null ? null : value.getDegree()); + setMinute(value == null ? null : value.getMinute()); + setSecond(value == null ? null : value.getSecond()); + } + + public String getStringPattern() { + return COORDINATE_STRING_PATTERN; + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/MaskFormatterFromConverter.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/MaskFormatterFromConverter.java new file mode 100644 index 0000000..ab675eb --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/gis/MaskFormatterFromConverter.java @@ -0,0 +1,75 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.beanutils.Converter; + +import javax.swing.text.MaskFormatter; +import java.text.ParseException; + +/** + * Created on 11/25/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class MaskFormatterFromConverter<O> extends MaskFormatter { + + private static final long serialVersionUID = 1L; + + private final Converter converter; + + private final Class<O> type; + + public static <O> MaskFormatterFromConverter<O> newFormatter(Class<O> type, + String pattern, + Converter converter) throws ParseException { + return new MaskFormatterFromConverter<O>(type, pattern, converter); + } + + protected MaskFormatterFromConverter(Class<O> type, + String pattern, + Converter converter) throws ParseException { + super(pattern); + this.type = type; + this.converter = converter; + } + + @Override + public String valueToString(Object value) throws ParseException { + return (String) converter.convert(String.class, value); + } + + @Override + public Object stringToValue(String value) throws ParseException { + return converter.convert(type, value); + } + + protected Converter getConverter() { + return converter; + } + + protected Class<O> getType() { + return type; + } +} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/package.html b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/package.html similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/package.html rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/editor/package.html diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/ActionCheckListModel.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/ActionCheckListModel.java new file mode 100644 index 0000000..e40d205 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/ActionCheckListModel.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ + +package org.nuiton.jaxx.runtime.swing.list; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; + +public class ActionCheckListModel<T> implements CheckListModel<T> { + + protected final List<ListDataListener> listeners = Collections.synchronizedList( new ArrayList<ListDataListener>()); + protected final CheckListModel<T> originalModel; + + protected final CheckListAction<T> actionCheckAll = new CheckListAction.CheckAll<T>(); + + @SuppressWarnings("unchecked") + protected final List<CheckListAction<T>> actionItems = Arrays.asList( actionCheckAll ); + protected final Set<CheckListAction<T>> checks = new HashSet<CheckListAction<T>>(); + + public ActionCheckListModel( final CheckListModel<T> originalModel ) { + + if ( originalModel == null ) throw new NullPointerException(); + this.originalModel = originalModel; + + //react on original model changes + this.originalModel.addListDataListener( new ListDataListener () { + + @Override + public void intervalAdded(ListDataEvent e) { + ListDataEvent event = toDecoratedEvent(e); + for( ListDataListener l: listeners ) { + l.intervalAdded(event); + } + } + + @Override + public void intervalRemoved(ListDataEvent e) { + ListDataEvent event = toDecoratedEvent(e); + for( ListDataListener l: listeners ) { + l.intervalRemoved(event); + } + } + + @Override + public void contentsChanged(ListDataEvent e) { + ListDataEvent event = toDecoratedEvent(e); + for( ListDataListener l: listeners ) { + l.contentsChanged(event); + } + if ( originalModel.getCheckedItems().size() < originalModel.getOriginalSize() ) { + checks.remove(actionCheckAll); + } else { + checks.add(actionCheckAll); + } + fireListDataChanged(); + } + }); + } + + @Override + public int getSize() { + return originalModel.getSize() + actionItems.size(); + } + + @Override + public int getOriginalSize() { + return originalModel.getOriginalSize() + actionItems.size(); + } + + @Override + public Object getElementAt(int index) { + if ( isDecoratedIndex(index)) { + return actionItems.get(index); + } else { + return originalModel.getElementAt( toOriginalIndex(index)); + } + } + + private int toOriginalIndex( int index ) { + return index - actionItems.size(); + } + + private int toDecoratedIndex( int index ) { + return index + actionItems.size(); + } + + private boolean isDecoratedIndex( int index ) { + int size = actionItems.size(); + return size > 0 && index >= 0 && index < size; + } + + + @Override + public void addListDataListener(ListDataListener l) { + listeners.add(l); + } + + @Override + public void removeListDataListener(ListDataListener l) { + listeners.remove(l); + } + + private void fireListDataChanged() { + ListDataEvent e = new ListDataEvent( this, 0, 0, getSize() ); + for( ListDataListener l: listeners ) { + l.contentsChanged(e); + } + } + + private ListDataEvent toDecoratedEvent( ListDataEvent e ) { + return new ListDataEvent( + e.getSource(), + e.getType(), + toDecoratedIndex(e.getIndex0()), + toDecoratedIndex(e.getIndex1())); + } + + @Override + public boolean isCheckedIndex(int index) { + if ( isDecoratedIndex(index)) { + return checks.contains(actionItems.get(index)); + } else { + return originalModel.isCheckedIndex( toOriginalIndex(index)); + } + + } + + @Override + public void setCheckedIndex(int index, boolean value) { + if ( isDecoratedIndex(index)) { + CheckListAction<T> item = actionItems.get(index); + item.check(originalModel, value); + if ( value ) checks.add(item); else checks.remove(item); + fireListDataChanged(); + } else { + originalModel.setCheckedIndex( toOriginalIndex(index), value); + } + } + + @Override + public Collection<T> getCheckedItems() { + return originalModel.getCheckedItems(); + } + + @Override + public void setCheckedItems(Collection<T> items) { + originalModel.setCheckedItems(items); + } + +// @Override +// public void filter(String filter, Decorator<Object> decorator, CheckListFilterType filterType) { +// originalModel.filter(filter, decorator, filterType); +// } + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckList.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckList.java new file mode 100644 index 0000000..dd84d77 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckList.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + * + */ + +package org.nuiton.jaxx.runtime.swing.list; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseListener; +import java.util.Collection; + +import javax.swing.AbstractAction; +import javax.swing.JList; +import javax.swing.KeyStroke; +import javax.swing.ListSelectionModel; + +/** + * The decorator for JList which makes it work like check list + * UI can be designed using JList and which can be later decorated to become a check list + * @author Eugene Ryzhikov + * @author Kevin Morin + * + * @param <T> list item type + */ +public class CheckList<T> { + + private final JList list; + private static final MouseAdapter checkBoxEditor = new CheckListEditor(); + + /** + * Wraps the standard JList and makes it work like check list + */ + public CheckList() { + + this.list = new JList(); + this.list.getSelectionModel().setSelectionMode( ListSelectionModel.SINGLE_SELECTION); + + if ( !isEditorAttached() ) list.addMouseListener(checkBoxEditor); + this.list.setCellRenderer(new CheckListRenderer()); + + setupKeyboardActions(list); + + } + + @SuppressWarnings("serial") + private void setupKeyboardActions(final JList list) { + String actionKey = "toggle-check"; + list.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0), actionKey); + list.getActionMap().put(actionKey, new AbstractAction(){ + + @Override + public void actionPerformed(ActionEvent e) { + toggleIndex(list.getSelectedIndex()); + }}); + } + + private boolean isEditorAttached() { + + for( MouseListener ml: list.getMouseListeners() ) { + if ( ml instanceof CheckListEditor ) return true; + } + return false; + + } + + public JList getList() { + return list; + } + + /** + * Sets data to a check list. Simplification for setting new the model + * @param data + */ + public void setData( Collection<T> data ) { + setModel( new DefaultCheckListModel<T>(data)); + } + + /** + * Sets the model for check list. + * @param model + */ + public void setModel( CheckListModel<T> model ) { + list.setModel(model); + } + + @SuppressWarnings("unchecked") + public CheckListModel<T> getModel() { + return (CheckListModel<T>) list.getModel(); + } + + /** + * Returns a collection of checked items. + * @return collection of checked items. Empty collection if nothing is selected + */ + public Collection<T> getCheckedItems() { + return getModel().getCheckedItems(); + } + + /** + * Resets checked elements + * @param elements + */ + public void setCheckedItems( Collection<T> elements ) { + getModel().setCheckedItems(elements); + } + + public void toggleIndex( int index ) { + if ( index >= 0 && index < list.getModel().getSize()) { + CheckListModel<T> model = getModel(); + model.setCheckedIndex(index, !model.isCheckedIndex(index)); + } + } + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckListAction.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckListAction.java new file mode 100644 index 0000000..8b608f4 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckListAction.java @@ -0,0 +1,58 @@ +package org.nuiton.jaxx.runtime.swing.list; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + + +import java.util.ArrayList; +import java.util.Collection; + +import static org.nuiton.i18n.I18n.t; + + +public interface CheckListAction<T> { + + void check( CheckListModel<T> model, boolean value ); + + public static class CheckAll<T> implements CheckListAction<T> { + + @Override + public String toString() { + return "(" + t("jaxx.list.check.all") + ")"; + } + + @SuppressWarnings("unchecked") + @Override + public void check(CheckListModel<T> model, boolean value) { + Collection<T> items = new ArrayList<T>(); + if (value) { + for( int i=0, s=model.getSize(); i<s; i++ ) { + items.add((T) model.getElementAt(i)); + } + } + model.setCheckedItems( items ); + + } + + } + +} \ No newline at end of file diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckListEditor.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckListEditor.java new file mode 100644 index 0000000..a58ec67 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckListEditor.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ + +package org.nuiton.jaxx.runtime.swing.list; + +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.Arrays; + +import javax.swing.JList; +import javax.swing.SwingUtilities; + + +/** + * Determines mouse click and + * 1. Toggles the check on selected item if clicked once + * 2. Clears checks and checks selected item if clicked more then once + * + * Created on Feb 4, 2011 + * @author Eugene Ryzhikov + * @author Kevin Morin + * + */ +final class CheckListEditor extends MouseAdapter { + @Override + public void mouseClicked(MouseEvent e) { + + if (!SwingUtilities.isLeftMouseButton(e)) return; + + JList list = (JList) e.getSource(); + if ( !list.isEnabled() || (!(list.getModel() instanceof CheckListModel<?>))) return; + + int index = list.locationToIndex(e.getPoint()); + if (index < 0) return; + + Rectangle bounds = list.getCellBounds(index, index); + + if ( bounds.contains(e.getPoint()) ) { + + @SuppressWarnings("unchecked") + CheckListModel<Object> model = (CheckListModel<Object>) list.getModel(); + + if ( e.getClickCount() > 1 ) { + // clear all and check selected for more then 1 clicks + model.setCheckedItems( Arrays.asList( model.getElementAt(index))); + } else { + // simple toggle for 1 click + model.setCheckedIndex(index, !model.isCheckedIndex(index)); + } + e.consume(); + } + + } + +} + diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckListModel.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckListModel.java new file mode 100644 index 0000000..cace614 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckListModel.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ + +package org.nuiton.jaxx.runtime.swing.list; + +import java.util.Collection; + +import javax.swing.ListModel; + +public interface CheckListModel<T> extends ListModel { + + /** + * Returns the check state of the element at specified position + * @param index element index + * @return true if element at specified position is checked + * @throws IndexOutOfBoundsException if index is out of range + */ + boolean isCheckedIndex(int index); + + /** + * Sets the check state of the element at specified position + * @param index element index + * @param value + * @throws IndexOutOfBoundsException if index is out of range + */ + void setCheckedIndex(int index, boolean value); + + /** + * Returns a collections of checked items + * @return + */ + Collection<T> getCheckedItems(); + + /** + * Sets checked items + * @param items + */ + void setCheckedItems(Collection<T> items); + + /** + * Returns the number of items before the filter was applied + * @return + */ + int getOriginalSize(); + +} \ No newline at end of file diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckListRenderer.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckListRenderer.java new file mode 100644 index 0000000..ee296d0 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/CheckListRenderer.java @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ + +package org.nuiton.jaxx.runtime.swing.list; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Rectangle; +import java.io.Serializable; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.Icon; +import javax.swing.JCheckBox; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; + +public class CheckListRenderer extends JCheckBox implements ListCellRenderer, Serializable { + + private static final long serialVersionUID = 1L; + + private static final Border NO_FOCUS_BORDER = new EmptyBorder(1, 1, 1, 1); + private static final Border SAFE_NO_FOCUS_BORDER = NO_FOCUS_BORDER; // may change in the feature + + /** + * Constructs a default renderer object for an item in a list. + */ + public CheckListRenderer() { + super(); + setOpaque(true); + setBorder(getNoFocusBorder()); + } + + private static Border getNoFocusBorder() { + if (System.getSecurityManager() != null) { + return SAFE_NO_FOCUS_BORDER; + } else { + return NO_FOCUS_BORDER; + } + } + + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, + boolean cellHasFocus) { + + setComponentOrientation(list.getComponentOrientation()); + + Color bg = null; + Color fg = null; + + JList.DropLocation dropLocation = list.getDropLocation(); + if (dropLocation != null && !dropLocation.isInsert() && dropLocation.getIndex() == index) { + + bg = UIManager.getColor("List.dropCellBackground"); + fg = UIManager.getColor("List.dropCellForeground"); + + isSelected = true; + } + + if (isSelected) { + setBackground(bg == null ? list.getSelectionBackground() : bg); + setForeground(fg == null ? list.getSelectionForeground() : fg); + } else { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + } + + if (value instanceof Icon) { + setIcon((Icon) value); + setText(""); + } else { + setIcon(null); + setText(getObjectAsText(value)); + } + + setSelected( isChecked(list, index)); + + setEnabled(list.isEnabled()); + setFont(list.getFont()); + + Border border = null; + if (cellHasFocus) { + if (isSelected) { + border = UIManager.getBorder("List.focusSelectedCellHighlightBorder"); + } + if (border == null) { + border = UIManager.getBorder("List.focusCellHighlightBorder"); + } + } else { + border = getNoFocusBorder(); + } + setBorder(border); + + return this; + } + + protected String getObjectAsText(Object obj) { + return (obj == null) ? "" : obj.toString(); + } + + private boolean isChecked(JList list, int index) { + + if (list.getModel() instanceof CheckListModel<?>) { + return ((CheckListModel<?>) list.getModel()).isCheckedIndex(index); + } else { + return false; + } + + } + + /** + * @return true if the background is opaque and differs from the JList's background; false otherwise + */ + @Override + public boolean isOpaque() { + Color back = getBackground(); + Component p = getParent(); + if (p != null) { + p = p.getParent(); + } + // p should now be the JList. + boolean colorMatch = (back != null) && (p != null) && back.equals(p.getBackground()) && p.isOpaque(); + return !colorMatch && super.isOpaque(); + } + + @Override + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + + if ("text".equals(propertyName) || + (("font".equals(propertyName) || "foreground".equals(propertyName)) && + oldValue != newValue && getClientProperty(javax.swing.plaf.basic.BasicHTML.propertyKey) != null)) { + + super.firePropertyChange(propertyName, oldValue, newValue); + } + } + + // Methods below are overridden for performance reasons. + + @Override + public void validate() { + } + + @Override + public void invalidate() { + } + + @Override + public void repaint() { + } + + @Override + public void revalidate() { + } + + @Override + public void repaint(long tm, int x, int y, int width, int height) { + } + + @Override + public void repaint(Rectangle r) { + } + + @Override + public void firePropertyChange(String propertyName, byte oldValue, byte newValue) { + } + + @Override + public void firePropertyChange(String propertyName, char oldValue, char newValue) { + } + + @Override + public void firePropertyChange(String propertyName, short oldValue, short newValue) { + } + + @Override + public void firePropertyChange(String propertyName, int oldValue, int newValue) { + } + + @Override + public void firePropertyChange(String propertyName, long oldValue, long newValue) { + } + + @Override + public void firePropertyChange(String propertyName, float oldValue, float newValue) { + } + + @Override + public void firePropertyChange(String propertyName, double oldValue, double newValue) { + } + + @Override + public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { + } + + @SuppressWarnings("serial") + public static class UIResource extends DefaultListCellRenderer implements javax.swing.plaf.UIResource { + } + +} \ No newline at end of file diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/DefaultCheckListModel.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/DefaultCheckListModel.java new file mode 100644 index 0000000..ff6e708 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/DefaultCheckListModel.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ + +package org.nuiton.jaxx.runtime.swing.list; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.swing.AbstractListModel; + +/** + * Default model for check list. It is based on the list of items + * Implementation of checks is based on HashSet of checked items + * + * @author Eugene Ryzhikov + * @author Kevin Morin + * + * @param <T> list element type + */ +public class DefaultCheckListModel<T> extends AbstractListModel implements CheckListModel<T> { + + private static final long serialVersionUID = 1L; + + protected final List<T> data = new ArrayList<T>(); + protected final Set<T> checks = new HashSet<T>(); + + public DefaultCheckListModel( Collection<? extends T> data ) { + + if ( data == null ) return; + for (T object : data) { + this.data.add( object ); + checks.clear(); + } + } + + public DefaultCheckListModel( T... data ) { + this( Arrays.asList( data )); + } + + /* (non-Javadoc) + * @see org.oxbow.swingbits.list.ICheckListModel#getSize() + */ + @Override + public int getSize() { + return data().size(); + } + + @Override + public int getOriginalSize() { + return data.size(); + } + + protected List<T> data() { + return data; + } + + + /* (non-Javadoc) + * @see org.oxbow.swingbits.list.ICheckListModel#getElementAt(int) + */ + @Override + public Object getElementAt(int index) { + return data().get(index); + } + + /* (non-Javadoc) + * @see org.oxbow.swingbits.list.ICheckListModel#isChecked(int) + */ + @Override + public boolean isCheckedIndex( int index ) { + return checks.contains( data().get(index)); + } + + /* (non-Javadoc) + * @see org.oxbow.swingbits.list.ICheckListModel#setChecked(int, boolean) + */ + @Override + public void setCheckedIndex( int index, boolean value ) { + T o = data().get(index); + if ( value ) checks.add(o); else checks.remove(o); + fireContentsChanged(this, index, index); + } + + /* (non-Javadoc) + * @see org.oxbow.swingbits.list.ICheckListModel#getChecked() + */ + @Override + public Collection<T> getCheckedItems() { + List<T> items = new ArrayList<T>(checks); + items.retainAll(data); + return Collections.unmodifiableList( items ); + } + + /* (non-Javadoc) + * @see org.oxbow.swingbits.list.ICheckListModel#setChecked(java.util.Collection) + */ + @Override + public void setCheckedItems( Collection<T> items ) { + + List<T> correctedItems = new ArrayList<T>(items); + correctedItems.retainAll(data); + + checks.clear(); + checks.addAll( correctedItems ); + fireContentsChanged(this, 0, checks.size()-1); + } + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/CheckListFilterType.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/CheckListFilterType.java new file mode 100644 index 0000000..384ccad --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/CheckListFilterType.java @@ -0,0 +1,54 @@ +package org.nuiton.jaxx.runtime.swing.list.filter; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + + +public enum CheckListFilterType { + + STARTS_WITH { + + @Override + public boolean include( String element, String filter ) { + + if ( element == null || filter == null ) return false; + return element.startsWith(filter); + + } + + }, + + CONTAINS { + + @Override + public boolean include( String element, String filter ) { + + if ( element == null || filter == null ) return false; + return element.toLowerCase().contains(filter.toLowerCase()); + + } + + }; + + public abstract boolean include( String element, String filter ); + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/DefaultFilterableCheckListModel.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/DefaultFilterableCheckListModel.java new file mode 100644 index 0000000..e317c04 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/DefaultFilterableCheckListModel.java @@ -0,0 +1,84 @@ +package org.nuiton.jaxx.runtime.swing.list.filter; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.swing.list.DefaultCheckListModel; +import org.nuiton.decorator.Decorator; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * @author Kevin Morin (Code Lutin) + * @since 2.13 + */ +public class DefaultFilterableCheckListModel<T> extends DefaultCheckListModel<T> implements FilterableCheckListModel<T> { + + private List<T> filteredData = null; + + public DefaultFilterableCheckListModel(Collection<? extends T> data) { + super(data); + } + + public DefaultFilterableCheckListModel(T... data) { + super(Arrays.asList(data)); + } + + protected List<T> data() { + return filteredData == null ? data: filteredData; + } + + @Override + public void filter(String filter, Decorator<Object> decorator, CheckListFilterType filterType) { + + if ( filter == null || filter.trim().length() == 0 ) { + filteredData = null; + } else { + + CheckListFilterType ft = filterType == null? CheckListFilterType.CONTAINS: filterType; + + String f = filter.toLowerCase(); + + List<T> fData = new ArrayList<T>(); + + for( T o: data ) { + String decorated; + if (o != null && decorator != null) { + decorated = decorator.toString(o); + } else { + decorated = JAXXUtil.getStringValue(o); + } + if ( ft.include(decorated, f)) { + fData.add(o); + } + } + filteredData = fData; + } + + fireContentsChanged( this, 0, data.size()-1); + } + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/FilterableActionCheckListModel.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/FilterableActionCheckListModel.java new file mode 100644 index 0000000..4dfd6d5 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/FilterableActionCheckListModel.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ + +package org.nuiton.jaxx.runtime.swing.list.filter; + +import org.nuiton.jaxx.runtime.swing.list.ActionCheckListModel; +import org.nuiton.decorator.Decorator; + +public class FilterableActionCheckListModel<T> extends ActionCheckListModel<T> implements FilterableCheckListModel<T> { + + public FilterableActionCheckListModel(final DefaultFilterableCheckListModel<T> originalModel) { + super(originalModel); + } + + @Override + public void filter(String filter, Decorator<Object> decorator, CheckListFilterType filterType) { + ((DefaultFilterableCheckListModel) originalModel).filter(filter, decorator, filterType); + } + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/FilterableCheckList.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/FilterableCheckList.java new file mode 100644 index 0000000..696d10b --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/FilterableCheckList.java @@ -0,0 +1,55 @@ +package org.nuiton.jaxx.runtime.swing.list.filter; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.swing.list.CheckList; +import org.nuiton.jaxx.runtime.swing.list.CheckListModel; +import org.nuiton.decorator.Decorator; + +/** + * @author Kevin Morin (Code Lutin) + * @since 2.13 + */ +public class FilterableCheckList<T> extends CheckList<T> { + + /** + * Sets the model for check list. + * @param model + */ + public void setModel( CheckListModel<T> model ) { + getList().setModel(model); + } + + @SuppressWarnings("unchecked") + public FilterableCheckListModel<T> getModel() { + return (FilterableCheckListModel<T>) getList().getModel(); + } + + /** + * Filters list view without losing actual data + * @param filter + */ + public void filter( String filter, Decorator<Object> decorator, CheckListFilterType filterType ) { + getModel().filter(filter, decorator, filterType); + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/FilterableCheckListModel.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/FilterableCheckListModel.java new file mode 100644 index 0000000..70c60dd --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/list/filter/FilterableCheckListModel.java @@ -0,0 +1,40 @@ +package org.nuiton.jaxx.runtime.swing.list.filter; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 CodeLutin + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.swing.list.CheckListModel; +import org.nuiton.decorator.Decorator; + +/** + * @author Kevin Morin (Code Lutin) + * @since 2.13 + */ +public interface FilterableCheckListModel<T> extends CheckListModel<T> { + + /** + * Filters list view without losing actual data + * @param filter + */ + void filter( String filter, Decorator<Object> decorator, CheckListFilterType filterType ); + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/log/JAXXLog4jAppender.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/log/JAXXLog4jAppender.java new file mode 100644 index 0000000..d9065b0 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/log/JAXXLog4jAppender.java @@ -0,0 +1,139 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.log; + +import org.apache.log4j.Level; +import org.apache.log4j.WriterAppender; +import org.apache.log4j.spi.LoggingEvent; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.LinkedList; +import java.util.List; + +/** + * @author Sylvain Lletellier + */ +public class JAXXLog4jAppender extends WriterAppender { + + public static final String PROPERTY_LOGS = "logs"; + public static final String PROPERTY_LEVEL = "level"; + + protected List<LoggingEvent> events; + protected StringBuilder logs; + protected Level level; + + protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + + public JAXXLog4jAppender() { + events = new LinkedList<LoggingEvent>(); + logs = new StringBuilder(); + } + + public String getLogs() { + return logs.toString(); + } + + public void setLogs(String logs) { + String oldValue = getLogs(); + this.logs = new StringBuilder(logs); + firePropertyChange(PROPERTY_LOGS, oldValue, logs); + } + + public Level getLevel() { + if (level == null) { + level = Level.ALL; + } + return level; + } + + public void setLevel(Level level) { + Level oldValue = getLevel(); + this.level = level; + firePropertyChange(PROPERTY_LEVEL, oldValue, level); + updateLogs(); + } + + @Override + public void append(LoggingEvent event) { + super.append(event); + if (event != null) { + events.add(event); + updateLog(event); + } + } + + protected void updateLogs() { + String oldValue = getLogs(); + logs = new StringBuilder(); + for (LoggingEvent event : events) { + updateLog(event); + } + firePropertyChange(PROPERTY_LOGS, oldValue, getLogs()); + } + + protected void updateLog(LoggingEvent event) { + Level level = event.getLevel(); + if (getLevel() != null && level.isGreaterOrEqual(getLevel())) { + String log = this.layout.format(event); + appendLog(log); + if(layout.ignoresThrowable()) { + String[] errorLogs = event.getThrowableStrRep(); + if (errorLogs != null) { + for (String errorLog : errorLogs) { + appendLog(errorLog + "\n"); + } + } + } + } + } + + protected void appendLog(String log) { + String oldValue = getLogs(); + logs.append(log); + firePropertyChange(PROPERTY_LOGS, oldValue, getLogs()); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + protected void firePropertyChange(String propertyName, Object newValue) { + firePropertyChange(propertyName, null, newValue); + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/log/JAXXLog4jHandler.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/log/JAXXLog4jHandler.java new file mode 100644 index 0000000..a726c0c --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/log/JAXXLog4jHandler.java @@ -0,0 +1,124 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.log; + +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.SwingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.apache.log4j.PatternLayout; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JRootPane; +import javax.swing.KeyStroke; +import java.awt.Component; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * @author Sylvain Lletellier + */ +public class JAXXLog4jHandler { + + private static final Log log = LogFactory.getLog(JAXXLog4jHandler.class); + + protected JAXXLog4jUI ui; + + protected static JAXXLog4jAppender appender; + + public JAXXLog4jHandler(JAXXLog4jUI ui) { + this.ui = ui; + } + + /** + * Init {@link JAXXLog4jAppender} with level INFO and pattern : %5p [%t] (%F:%L) %M - %m%n + */ + public static void init() { + init("INFO", "%5p [%t] (%F:%L) %M - %m%n"); + } + + /** + * Init {@link JAXXLog4jAppender} with specific {@link Level} and {@link PatternLayout} + * + * @param level specify log4j {@link Level} + * @param patternLayout log4j {@link PatternLayout} to display + */ + public static void init(String level, String patternLayout) { + Logger logger = Logger.getRootLogger(); + + if (appender == null) { + appender = new JAXXLog4jAppender(); + logger.addAppender(appender); + } + appender.setLevel(Level.toLevel(level)); + appender.setLayout(new PatternLayout(patternLayout)); + } + + final protected Action closeAction = new AbstractAction("close") { + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + JDialog container = ui.getParentContainer(JDialog.class); + if (container != null) { + container.dispose(); + } else { + ui.setVisible(false); + } + } + }; + + public JAXXLog4jAppender getAppender() { + return appender; + } + + public void showInDialog(Frame ui, boolean undecorated) { + JDialog f = new JDialog(ui, this.ui.getTitle(), false); + f.add(this.ui); + f.setResizable(true); + f.setSize(550, 450); + f.setUndecorated(undecorated); + JRootPane rootPane = f.getRootPane(); + rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ESCAPE"), "close"); + rootPane.getActionMap().put("close", closeAction); + f.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + Component ui = (Component) e.getSource(); + if (log.isInfoEnabled()) { + log.info("destroy ui " + ui); + } + JAXXUtil.destroy(ui); + JAXXUtil.destroy(JAXXLog4jHandler.this.ui); + } + }); + SwingUtil.center(ui, f); + f.setVisible(true); + } +} diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jUI.jaxx b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/log/JAXXLog4jUI.jaxx similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jUI.jaxx rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/log/JAXXLog4jUI.jaxx diff --git a/jaxx-widgets/src/main/java/jaxx/runtime/swing/package.html b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/package.html similarity index 100% rename from jaxx-widgets/src/main/java/jaxx/runtime/swing/package.html rename to jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/package.html diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DateCellRenderer.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DateCellRenderer.java new file mode 100644 index 0000000..61fe82d --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/renderer/DateCellRenderer.java @@ -0,0 +1,60 @@ +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.runtime.swing.renderer; + +import java.awt.Component; +import java.text.SimpleDateFormat; +import java.util.Date; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import org.apache.commons.lang3.StringUtils; + +/** + * @author Sylvain Lletellier + */ +public class DateCellRenderer implements TableCellRenderer { + + protected TableCellRenderer delegate; + protected SimpleDateFormat dateFormat; + + public DateCellRenderer(TableCellRenderer renderer, String datePattern) { + this.delegate = renderer; + dateFormat = new SimpleDateFormat(); + if (datePattern != null) { + dateFormat.applyPattern(datePattern); + } + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + JLabel render = (JLabel) delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + Date date = (Date) value; + String formatedDate = StringUtils.EMPTY; + if (date != null) { + formatedDate = dateFormat.format(date); + } + render.setText(formatedDate); + return render; + + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/session/BeanDoubleListState.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/session/BeanDoubleListState.java new file mode 100644 index 0000000..d75e4e6 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/session/BeanDoubleListState.java @@ -0,0 +1,89 @@ +package org.nuiton.jaxx.runtime.swing.session; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.swing.editor.bean.BeanDoubleList; + +/** + * @author Kevin Morin - morin@codelutin.com + * @since 2.5.21 + */ +public class BeanDoubleListState implements State { + + protected int index = 0; + + protected boolean reverseSort = false; + + public BeanDoubleListState() { + } + + public BeanDoubleListState(int index, boolean reverseSort) { + this.index = index; + this.reverseSort = reverseSort; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public boolean isReverseSort() { + return reverseSort; + } + + public void setReverseSort(boolean reverseSort) { + this.reverseSort = reverseSort; + } + + protected BeanDoubleList checkComponent(Object o) { + if (o == null) { + throw new IllegalArgumentException("null component"); + } + if (!(o instanceof BeanDoubleList)) { + throw new IllegalArgumentException("invalid component"); + } + return (BeanDoubleList) o; + } + + @Override + public State getState(Object o) { + BeanDoubleList list = checkComponent(o); + return new BeanDoubleListState(list.getIndex(), list.isReverseSort()); + } + + @Override + public void setState(Object o, State state) { + if (!(state instanceof BeanDoubleListState)) { + throw new IllegalArgumentException("invalid state"); + } + BeanDoubleList list = checkComponent(o); + BeanDoubleListState beanDoubleListState = (BeanDoubleListState) state; + list.setIndex(beanDoubleListState.getIndex()); + list.setReverseSort(beanDoubleListState.isReverseSort()); + } + + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/session/BeanFilterableComboBoxState.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/session/BeanFilterableComboBoxState.java new file mode 100644 index 0000000..ad8e245 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/session/BeanFilterableComboBoxState.java @@ -0,0 +1,89 @@ +package org.nuiton.jaxx.runtime.swing.session; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.nuiton.jaxx.runtime.swing.editor.bean.BeanFilterableComboBox; + +/** + * @author Kevin Morin - morin@codelutin.com + * @since 2.5.20 + */ +public class BeanFilterableComboBoxState implements State { + + protected int index = 0; + + protected boolean reverseSort = false; + + public BeanFilterableComboBoxState() { + } + + public BeanFilterableComboBoxState(int index, boolean reverseSort) { + this.index = index; + this.reverseSort = reverseSort; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public boolean isReverseSort() { + return reverseSort; + } + + public void setReverseSort(boolean reverseSort) { + this.reverseSort = reverseSort; + } + + protected BeanFilterableComboBox checkComponent(Object o) { + if (o == null) { + throw new IllegalArgumentException("null component"); + } + if (!(o instanceof BeanFilterableComboBox)) { + throw new IllegalArgumentException("invalid component"); + } + return (BeanFilterableComboBox) o; + } + + @Override + public State getState(Object o) { + BeanFilterableComboBox combo = checkComponent(o); + return new BeanFilterableComboBoxState(combo.getIndex(), combo.isReverseSort()); + } + + @Override + public void setState(Object o, State state) { + if (!(state instanceof BeanFilterableComboBoxState)) { + throw new IllegalArgumentException("invalid state"); + } + BeanFilterableComboBox combo = checkComponent(o); + BeanFilterableComboBoxState bfcbState = (BeanFilterableComboBoxState) state; + combo.setIndex(bfcbState.getIndex()); + combo.setReverseSort(bfcbState.isReverseSort()); + } + + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/AbstractTableFilter.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/AbstractTableFilter.java new file mode 100644 index 0000000..51eb5bd --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/AbstractTableFilter.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ + +package org.nuiton.jaxx.runtime.swing.table.filter; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.ComparatorUtils; +import org.apache.commons.collections4.Transformer; +import org.apache.commons.lang3.ObjectUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.swing.JTable; + +/** + * Partial implementation of table filter + * + * Created on Feb 10, 2011 + * @author Eugene Ryzhikov + * @author Kevin Morin + * + * @param <T> + */ +@SuppressWarnings("serial") +public abstract class AbstractTableFilter<T extends JTable> implements TableFilter<T> { + + private final Set<FilterChangeListener> listeners = Collections.synchronizedSet( new HashSet<FilterChangeListener>()); + + private final T table; + private final TableFilterState filterState = new TableFilterState(); + private Map<Integer, Integer> columnDistnctIntemNumbers = new HashMap<Integer, Integer>(); + + public AbstractTableFilter( T table ) { + this.table = table; + } + + @Override + public T getTable() { + return table; + } + + protected abstract boolean execute(int col, Collection<Object> items); + + @Override + public boolean apply(int col, Collection<Object> items) { + setFilterState(col, items); + boolean result; + if ( result = execute( col, items ) ) fireFilterChange(); + return result; + } + + @Override + public final void addChangeListener( FilterChangeListener listener ) { + if ( listener != null ) listeners.add(listener); + } + + @Override + public final void removeChangeListener( FilterChangeListener listener ) { + if ( listener != null ) listeners.remove(listener); + } + + public final void fireFilterChange() { + for( FilterChangeListener l: listeners ) { + l.filterChanged(AbstractTableFilter.this); + } + } + + @Override + public Collection<Object> getDistinctColumnItems( int column ) { + Collection<Object> result = collectDistinctColumnItems( column ); + columnDistnctIntemNumbers.put(column, result != null ? result.size() : 0); + return result; + + } + + private Collection<Object> collectDistinctColumnItems( final int column ) { +// Set<Object> set = new HashSet<Object>(); // to collect unique items +// int nullIndex = -1; +// for( int row=0; row<table.getModel().getRowCount(); row++) { +// Object value = table.getModel().getValueAt( row, column); +// // adding null to TreeSet will produce NPE, just remember we had it +// if ( value == null ) { +// nullIndex = row; +// } else { +// set.add( new DistinctColumnItem(value, row )); +// } +// } + Set<Object> set = distinctValuesForColumn(column); + List<Object> result = null; + if (set != null) { + result = new ArrayList<Object>(set); + // if ( nullIndex >= 0 ) result.add(0, null); // add null to resulting collection if we had it + + Collections.sort(result, new Comparator<Object>() { + @Override + public int compare(Object o1, Object o2) { + return ComparatorUtils.transformedComparator(ComparatorUtils.NATURAL_COMPARATOR, + new Transformer<Object, Comparable>() { + @Override + public Comparable transform(Object input) { + return AbstractTableFilter.this.toString(input); + } + }).compare(o1, o2); + } + }); + + } + return result; + } + + @Override + public Collection<Object> getFilterState( int column ) { + return filterState.getValues(column); + } + + @Override + public boolean isFiltered( int column ) { + Collection<Object> checks = getFilterState( column ); + return CollectionUtils.isNotEmpty(checks) && !ObjectUtils.equals(columnDistnctIntemNumbers.get(column), checks.size()); + } + + @Override + public boolean includeRow( TableFilter.Row row ) { + return filterState.include(row); + } + + public void setFilterState(int column, Collection<Object> values ) { + filterState.setValues(column, values); + } + + public void clear() { + filterState.clear(); + fireFilterChange(); + } + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/FilterChangeListener.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/FilterChangeListener.java new file mode 100644 index 0000000..a61e320 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/FilterChangeListener.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ + +package org.nuiton.jaxx.runtime.swing.table.filter; + +public interface FilterChangeListener { + + void filterChanged( TableFilter<?> filter ); +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/FilterTableHeaderRenderer.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/FilterTableHeaderRenderer.java new file mode 100644 index 0000000..1e4cdc9 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/FilterTableHeaderRenderer.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ + +package org.nuiton.jaxx.runtime.swing.table.filter; + +import org.nuiton.jaxx.runtime.swing.CompoundIcon; +import org.nuiton.jaxx.runtime.swing.JAXXWidgetUtil; + +import java.awt.Component; +import java.awt.Image; + +import javax.swing.*; +import javax.swing.table.TableCellRenderer; + +/** + * Table header renderer to show the column filter state + * + * Created on Feb 10, 2011 + * @author Eugene Ryzhikov + * @author Kevin Morin + * + */ +class FilterTableHeaderRenderer extends JComponent implements TableCellRenderer { + + private static final long serialVersionUID = 1L; + + private ImageIcon icon; + private final TableFilter<?> tableFilter; + private boolean rendererInit = true; + private int originalHorizontalTextPosition; + + public FilterTableHeaderRenderer( TableFilter<?> tableFilter ) { + this.tableFilter = tableFilter; + } + + private Icon getFilterIcon() { + + if (icon == null) { + icon = JAXXWidgetUtil.createImageIcon("funnel.png"); + icon = new ImageIcon( icon.getImage().getScaledInstance( 12, 12, Image.SCALE_SMOOTH )); + } + return icon; + + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, + boolean hasFocus, int row, int column) { + + final JLabel label = (JLabel) table.getTableHeader().getDefaultRenderer() + .getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + if ( rendererInit ) { + originalHorizontalTextPosition = label.getHorizontalTextPosition(); + rendererInit = false; + } + + int modelColumn = table.convertColumnIndexToModel(column); + if ( tableFilter.isFiltered(modelColumn) ) { + + Icon originalIcon = label.getIcon(); + if ( originalIcon == null ) { + label.setIcon( getFilterIcon() ); + } else { + label.setIcon( new CompoundIcon( getFilterIcon(), originalIcon ) ); + } + label.setHorizontalTextPosition( JLabel.TRAILING ); + + } else { + label.setHorizontalTextPosition( originalHorizontalTextPosition ); + } + + return label; + } + + // following methods are overriden for performance reasons + + @Override + public void validate() {} + + @Override + public void revalidate() {} + + @Override + public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {} + + @Override + public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {} + +} \ No newline at end of file diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/JTableFilter.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/JTableFilter.java new file mode 100644 index 0000000..9600f2f --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/JTableFilter.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ + +package org.nuiton.jaxx.runtime.swing.table.filter; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +import javax.swing.DefaultRowSorter; +import javax.swing.JTable; +import javax.swing.RowFilter; +import javax.swing.RowSorter; +import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; + +public class JTableFilter extends AbstractTableFilter<JTable> { + + private static final long serialVersionUID = 1L; + + private final TableRowFilter filter = new TableRowFilter(); + + public JTableFilter( JTable table) { + super(table); + } + + @Override + protected boolean execute(int col, Collection<Object> items) { + + RowSorter<?> rs = getTable().getRowSorter(); + + if (!( rs instanceof DefaultRowSorter )) return false; + + DefaultRowSorter<?, ?> drs = (DefaultRowSorter<?, ?>) rs; + + @SuppressWarnings("unchecked") + RowFilter<Object,Object> prevFilter = (RowFilter<Object, Object>) drs.getRowFilter(); + if ( !(prevFilter instanceof TableRowFilter)) { + filter.setParentFilter(prevFilter); + } + + drs.setRowFilter(filter); + return true; + + } + + class TableRowFilter extends RowFilter<Object,Object> implements Serializable { + + private static final long serialVersionUID = 1L; + + private RowFilter<Object, Object> parentFilter; + + public RowFilter<Object, Object> getParentFilter() { + return parentFilter; + } + + public void setParentFilter( RowFilter<Object, Object> parentFilter ) { + this.parentFilter = (parentFilter == null || parentFilter == this )? null: parentFilter; + } + + @Override + public boolean include( final RowFilter.Entry<? extends Object, ? extends Object> entry) { + + // use parent filter condition + if ( parentFilter != null && !parentFilter.include(entry)) return false; + + return includeRow( new TableFilter.Row() { + + @Override + public Object getValue(int column) { return entry.getValue(column); } + + @Override + public int getValueCount() { return entry.getValueCount(); } + + }); + + } + + } + + public void modelChanged( TableModel model ) { + getTable().setRowSorter( new TableRowSorter<TableModel>( model )); + } + + @Override + public Set<Object> distinctValuesForColumn(int i) { + //TODO + return null; + } + + @Override + public String toString(Object o) { + //TODO + return null; + } + + public void clear() { + super.clear(); + Collection<Object> items = Collections.emptyList(); + for( int column=0; column<getTable().getModel().getColumnCount(); column++) { + execute(column, items); + } + } +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableAwareCheckListRenderer.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableAwareCheckListRenderer.java new file mode 100644 index 0000000..bf52131 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableAwareCheckListRenderer.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ +package org.nuiton.jaxx.runtime.swing.table.filter; + +import org.nuiton.jaxx.runtime.JAXXUtil; +import org.nuiton.jaxx.runtime.swing.list.CheckListRenderer; +import org.nuiton.decorator.Decorator; + +import java.awt.Component; + +import javax.swing.JList; + +@SuppressWarnings("serial") +public class TableAwareCheckListRenderer extends CheckListRenderer { + + private final Decorator<Object> decorator; + + public TableAwareCheckListRenderer(Decorator<Object> decorator ) { + this.decorator = decorator; + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + String text; + if (value != null && decorator != null) { + text = decorator.toString(value); + } else { + text = JAXXUtil.getStringValue(value); + } + setText(text); + return this; + + } + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableFilter.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableFilter.java new file mode 100644 index 0000000..816c923 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableFilter.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ + + +package org.nuiton.jaxx.runtime.swing.table.filter; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Set; + +import javax.swing.JTable; +import javax.swing.table.TableModel; + +public interface TableFilter<T extends JTable> extends Serializable { + + /** + * The table under filter + * @return + */ + T getTable(); + + /** + * + * @param column model column index + * @return + */ + Collection<Object> getDistinctColumnItems( int column ); + + /** + * + * @param column model column index + * @return + */ + Collection<Object> getFilterState( int column ); + + /** + * Checks if column is filtered + * @param column model column index + * @return true if column is filtered + */ + boolean isFiltered( int column ); + + boolean includeRow( Row entry ); + + /** + * Apply filter for specified column based on collection of distinct items + * @param col + * @param items + * @return + */ + boolean apply( int col, Collection<Object> items ); + + public interface Row { + int getValueCount(); + Object getValue( int column ); + } + + void addChangeListener( FilterChangeListener listener ); + void removeChangeListener( FilterChangeListener listener ); + + /** + * Clear the filter + */ + void clear(); + + /** + * Describes what filter has to do when table model changes + * @param model + */ + void modelChanged( TableModel model ); + + Set<Object> distinctValuesForColumn(int i); + + String toString(Object o); + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableFilterColumnPopup.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableFilterColumnPopup.java new file mode 100644 index 0000000..68da901 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableFilterColumnPopup.java @@ -0,0 +1,581 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ + + +package org.nuiton.jaxx.runtime.swing.table.filter; + +import org.nuiton.jaxx.runtime.swing.JAXXWidgetUtil; +import org.nuiton.jaxx.runtime.swing.JSearchTextField; +import org.nuiton.jaxx.runtime.swing.list.filter.CheckListFilterType; +import org.nuiton.jaxx.runtime.swing.list.filter.DefaultFilterableCheckListModel; +import org.nuiton.jaxx.runtime.swing.list.filter.FilterableActionCheckListModel; +import org.nuiton.jaxx.runtime.swing.list.filter.FilterableCheckList; +import org.nuiton.jaxx.runtime.swing.list.filter.FilterableCheckListModel; +import org.apache.commons.collections4.CollectionUtils; +import org.nuiton.decorator.Decorator; + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableColumnModel; + +import static org.nuiton.i18n.I18n.t; + +class TableFilterColumnPopup extends MouseAdapter { + + static class ColumnAttrs { + public Dimension preferredSize; + } + + private boolean enabled = false; + + private final FilterableCheckList<Object> filterList = new FilterableCheckList(); + private final JSearchTextField searchField = new JSearchTextField(); + + private final Map<Integer, ColumnAttrs> colAttrs = new HashMap<Integer, ColumnAttrs>(); + private int mColumnIndex = -1; + + private final TableFilter<?> filter; + private boolean searchable; + private Decorator<Object> decorator; + private boolean actionsVisible = true; + private boolean useTableRenderers = false; + + private final JPopupMenu menu; + + private Dimension defaultSize = null; + + public TableFilterColumnPopup(TableFilter<?> filter) { + + menu = new ResizablePopupMenu() { + + private static final long serialVersionUID = 1L; + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + if (menu.getComponentCount() == 0) { + JComponent content = buildContent(); + if (defaultSize == null) { + defaultSize = content.getPreferredSize(); + } else { + content.setPreferredSize(defaultSize); + } + + menu.add(content); + + } + beforeShow(); + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + beforeHide(); + } + + }; + + this.filter = filter; + filterList.getList().setVisibleRowCount(8); + + setupTableHeader(); + filter.getTable().addPropertyChangeListener("tableHeader", new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + setupTableHeader(); + } + } + ); + filter.getTable().addPropertyChangeListener("model", new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + colAttrs.clear(); + } + } + ); + + searchField.getDocument().addDocumentListener(new DocumentListener() { + + @Override + public void removeUpdate(DocumentEvent e) { + perform(e); + } + + @Override + public void insertUpdate(DocumentEvent e) { + perform(e); + } + + @Override + public void changedUpdate(DocumentEvent e) { + perform(e); + } + + private void perform(DocumentEvent e) { + String text = searchField.getText(); + + //#3601 [TABLE FILTER] uncheck the "all" action when the user starts typing in the search field + if (actionsVisible) { + FilterableCheckListModel<Object> model = filterList.getModel(); + if (model.isCheckedIndex(0)) { + model.setCheckedIndex(0, false); + } + + } + filterList.filter(text, decorator, CheckListFilterType.CONTAINS); + } + + }); + + } + + public final Dimension getDefaultSize() { + return defaultSize; + } + + public final void setDefaultSize(Dimension dimension) { + defaultSize = dimension; + } + + public final Dimension getPreferredSize() { + return menu.getPreferredSize(); + } + + public final void setPreferredSize(Dimension preferredSize) { + menu.setPreferredSize(preferredSize); + } + + /** + * Shows Popup in predefined location + * + * @param invoker + * @param x + * @param y + */ + public void show(Component invoker, int x, int y) { + menu.show(invoker, x, y); + } + + /** + * Shows popup in predefined location + * + * @param invoker + * @param location + */ + public void show(Component invoker, Point location) { + show(invoker, location.x, location.y); + } + + /** + * Hides popup + */ + public final void hide() { + menu.setVisible(false); + } + + public void setSearchable(boolean searchable) { + this.searchable = searchable; + } + + public void searchDecorator(Decorator<Object> decorator) { + this.decorator = decorator; + } + + public void setActionsVisible(boolean actionsVisible) { + this.actionsVisible = actionsVisible; + } + + public void setUseTableRenderers(boolean reuseRenderers) { + this.useTableRenderers = reuseRenderers; + } + + private void setupTableHeader() { + JTableHeader header = filter.getTable().getTableHeader(); + if (header != null) header.addMouseListener(this); + } + + protected JComponent buildContent() { + + JPanel owner = new JPanel(new BorderLayout(3, 3)); + owner.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); + owner.setPreferredSize(new Dimension(250, 150)); // default popup size + + Box commands = new Box(BoxLayout.LINE_AXIS); + + JToolBar toolbar = new JToolBar(); + toolbar.setFloatable(false); + toolbar.setOpaque(false); + toolbar.add(new CommandAction( + t("jaxx.table.filter.popup.button.clearAll"), + JAXXWidgetUtil.createImageIcon("funnel_delete.png")) { + @Override + protected boolean perform() { + return clearAllFilters(); + } + }); + commands.add(toolbar); + + commands.add(Box.createHorizontalGlue()); + + commands.add(new JButton(new CommandAction(t("jaxx.table.filter.popup.button.apply")) { + @Override + protected boolean perform() { + return applyColumnFilter(); + } + }) + ); + commands.add(Box.createHorizontalStrut(5)); + commands.add(new JButton(new CommandAction(t("jaxx.table.filter.popup.button.cancel")))); + commands.setBorder(BorderFactory.createEmptyBorder(3, 0, 3, 0)); + commands.setBackground(UIManager.getColor("Panel.background")); + commands.setOpaque(true); + + if (searchable) { + owner.add(searchField, BorderLayout.NORTH); + } + owner.add(new JScrollPane(filterList.getList()), BorderLayout.CENTER); + owner.add(commands, BorderLayout.SOUTH); + + return owner; + + } + + private boolean applyColumnFilter() { + Collection<Object> checked = filterList.getCheckedItems(); + FilterableCheckListModel<Object> model = filterList.getModel(); + model.filter("", decorator, CheckListFilterType.CONTAINS); // clear filter to get true results + filter.apply(mColumnIndex, checked); + return true; + } + + private boolean clearAllFilters() { + filter.clear(); + return true; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + // Popup menus are triggered differently on different platforms + // Therefore, isPopupTrigger should be checked in both mousePressed and mouseReleased + // events for for proper cross-platform functionality + + @Override + public void mousePressed(MouseEvent e) { + if (enabled && e.isPopupTrigger()) showFilterPopup(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + if (enabled && e.isPopupTrigger()) showFilterPopup(e); + } + + private void showFilterPopup(MouseEvent e) { + JTableHeader header = (JTableHeader) (e.getSource()); + TableColumnModel colModel = filter.getTable().getColumnModel(); + + // The index of the column whose header was clicked + int vColumnIndex = colModel.getColumnIndexAtX(e.getX()); + if (vColumnIndex < 0) return; + + + // Determine if mouse was clicked between column heads + Rectangle headerRect = filter.getTable().getTableHeader().getHeaderRect(vColumnIndex); + if (vColumnIndex == 0) { + headerRect.width -= 2; + } else { + headerRect.grow(-2, 0); + } + + // Mouse was clicked between column heads + if (!headerRect.contains(e.getX(), e.getY())) return; + + // restore popup's size for the column + mColumnIndex = filter.getTable().convertColumnIndexToModel(vColumnIndex); + setPreferredSize(getColumnAttrs(vColumnIndex).preferredSize); + + Collection<Object> distinctItems = filter.getDistinctColumnItems(mColumnIndex); + if (distinctItems != null) { + + DefaultFilterableCheckListModel<Object> model = new DefaultFilterableCheckListModel<Object>(distinctItems); + filterList.setModel(actionsVisible ? new FilterableActionCheckListModel<Object>(model) : model); + Collection<Object> checked = filter.getFilterState(mColumnIndex); + + // replace empty checked items with full selection + filterList.setCheckedItems(CollectionUtils.isEmpty(checked) ? distinctItems : checked); + + if (useTableRenderers) { + filterList.getList().setCellRenderer(new TableAwareCheckListRenderer(decorator)); + } + + // show pop-up + show(header, headerRect.x, header.getHeight()); + } + } + + private ColumnAttrs getColumnAttrs(int column) { + ColumnAttrs attrs = colAttrs.get(column); + if (attrs == null) { + attrs = new ColumnAttrs(); + colAttrs.put(column, attrs); + } + + return attrs; + } + + protected void beforeShow() { + if (searchable) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + searchField.setText(""); + searchField.requestFocusInWindow(); + } + }); + } + } + + public void beforeHide() { + // save pop-up's dimensions before pop-up becomes hidden + getColumnAttrs(mColumnIndex).preferredSize = getPreferredSize(); + } + + /** + * Simple action to for the popup window. + * To use - override perform method. + * + * Created on Feb 4, 2011 + * + * @author Eugene Ryzhikov + */ + protected class CommandAction extends AbstractAction { + + private static final long serialVersionUID = 1L; + + public CommandAction(String name, Icon icon) { + super(name, icon); + + if (icon != null) { + putValue(Action.SHORT_DESCRIPTION, name); + putValue(Action.NAME, null); + } + + } + + public CommandAction(String name) { + super(name); + } + + @Override + public final void actionPerformed(ActionEvent e) { + if (perform()) hide(); + } + + /** + * Preforms action + * + * @return true if popup should be closed + */ + protected boolean perform() { + return true; + } + } + + protected class ResizablePopupMenu extends JPopupMenu implements PopupMenuListener { + + private static final long serialVersionUID = 1L; + + private static final int DOT_SIZE = 2; + private static final int DOT_START = 2; + private static final int DOT_STEP = 4; + + public ResizablePopupMenu() { + super(); + new PopupMenuResizer(this); + addPopupMenuListener(this); + } + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + } + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + } + + @Override + public void paintChildren(Graphics g) { + super.paintChildren(g); + drawResizer(g); + } + + private void drawResizer(Graphics g) { + + int x = getWidth() - 2; + int y = getHeight() - 2; + + Graphics g2 = g.create(); + + try { + for (int dy = DOT_START, j = 2; j > 0; j--, dy += DOT_STEP) { + for (int dx = DOT_START, i = 0; i < j; i++, dx += DOT_STEP) { + drawDot(g2, x - dx, y - dy); + } + } + + } finally { + g2.dispose(); + } + }; + + private void drawDot(Graphics g, int x, int y) { + g.setColor(Color.WHITE); + g.fillRect(x, y, DOT_SIZE, DOT_SIZE); + g.setColor(Color.LIGHT_GRAY); + g.fillRect(x - 1, y - 1, DOT_SIZE, DOT_SIZE); + } + + } + + /** + * Allows to resize popup with the mouse. + * + * Created on Aug 6, 2010 + * + * @author exr0bs5 + */ + protected class PopupMenuResizer extends MouseAdapter { + + private final JPopupMenu menu; + + private static final int REZSIZE_SPOT_SIZE = 10; + + private Point mouseStart = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE); + + private Dimension startSize; + + private boolean isResizing = false; + + public PopupMenuResizer(JPopupMenu menu) { + this.menu = menu; + this.menu.setLightWeightPopupEnabled(true); + menu.addMouseListener(this); + menu.addMouseMotionListener(this); + } + + private boolean isInResizeSpot(Point point) { + + if (point == null) return false; + + Rectangle resizeSpot = new Rectangle( + menu.getWidth() - REZSIZE_SPOT_SIZE, + menu.getHeight() - REZSIZE_SPOT_SIZE, + REZSIZE_SPOT_SIZE, + REZSIZE_SPOT_SIZE); + + return resizeSpot.contains(point); + + } + + @Override + public void mouseMoved(MouseEvent e) { + + menu.setCursor( + Cursor.getPredefinedCursor( + isInResizeSpot(e.getPoint()) ? Cursor.SE_RESIZE_CURSOR : Cursor.DEFAULT_CURSOR)); + } + + private Point toScreen(MouseEvent e) { + + Point p = e.getPoint(); + SwingUtilities.convertPointToScreen(p, e.getComponent()); + return p; + + } + + @Override + public void mousePressed(MouseEvent e) { + mouseStart = toScreen(e); + startSize = menu.getSize(); + isResizing = isInResizeSpot(e.getPoint()); + } + + @Override + public void mouseReleased(MouseEvent e) { + mouseStart = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE); + isResizing = false; + } + + @Override + public void mouseDragged(MouseEvent e) { + + if (!isResizing) return; + + Point p = toScreen(e); + + int dx = p.x - mouseStart.x; + int dy = p.y - mouseStart.y; + + + Dimension minDim = menu.getMinimumSize(); + // Dimension maxDim = menu.getMaximumSize(); + Dimension newDim = new Dimension(startSize.width + dx, startSize.height + dy); + + if (newDim.width >= minDim.width && newDim.height >= minDim.height /*&& + newDim.width <= maxDim.width && newDim.height <= maxDim.height*/) { + menu.setPopupSize(newDim); + } + + } + } + +} + diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableFilterState.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableFilterState.java new file mode 100644 index 0000000..610d370 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableFilterState.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ + +package org.nuiton.jaxx.runtime.swing.table.filter; + +import org.apache.commons.collections4.CollectionUtils; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +class TableFilterState implements Serializable { + + private static final long serialVersionUID = 1L; + + // no set - filter cleared; set - some kind of filtering + private final Map<Integer,Set<Object>> data = new HashMap<Integer,Set<Object>>(); + + /** + * Clears filtering for specific column + */ + public void clear( int column ) { + data.remove(column); + } + + + /** + * Clears all filtering + */ + public void clear() { + data.clear(); + } + + private Set<Object> prepareValueSet( int column ) { + Set<Object> vals = data.get(column); + if ( vals == null ) { + vals = new HashSet<Object>(); + data.put(column, vals); + } + return vals; + } + + + /** + * Adds filter value for specified column + * @param column + * @param value + */ + public void addValue( int column, Object value ) { + prepareValueSet(column).add(value); + } + + + /** + * Adds a collection of filter values for specified column + * @param column + * @param values + */ + public void addValues( int column, Collection<Object> values ) { + prepareValueSet(column).addAll(values); + } + + /** + * Resets a collection of filter values for specified column + * @param column + * @param values + */ + public void setValues( int column, Collection<Object> values ) { + data.remove(column); + if (CollectionUtils.isNotEmpty(values)) { + prepareValueSet(column).addAll(values); + } + } + + public Collection<Object> getValues( int column ) { + Set<Object> vals = data.get(column); + return vals == null? Collections.<Object>emptySet(): vals; + } + + /** + * Standard test for row inclusion using current filter values + * @param entry + * @return true if row has to be included + */ + public boolean include( TableFilter.Row entry ) { + + for( int col=0; col< entry.getValueCount(); col++ ) { + Collection<Object> values = getValues(col); + if ( CollectionUtils.isEmpty(values) ) continue; // no filtering for this column + if ( !values.contains( entry.getValue(col) )) return false; + } + return true; + + } + + +} diff --git a/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableRowFilterSupport.java b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableRowFilterSupport.java new file mode 100644 index 0000000..1dbd7f9 --- /dev/null +++ b/jaxx-widgets/src/main/java/org/nuiton/jaxx/runtime/swing/table/filter/TableRowFilterSupport.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2009-2011, EzWare + * 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 the + * EzWare 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR 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. + * + * %%Ignore-License%% + */ + +package org.nuiton.jaxx.runtime.swing.table.filter; + +import org.nuiton.decorator.Decorator; + +import java.awt.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Collections; + +import javax.swing.JTable; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; + +public final class TableRowFilterSupport { + + private boolean searchable = false; + private Decorator<Object> decorator; + private final TableFilter<?> filter; + private boolean actionsVisible = true; + private boolean useTableRenderers = false; + private Dimension popupDefaultSize = null; + + private TableRowFilterSupport( TableFilter<?> filter ) { + if ( filter == null ) throw new NullPointerException(); + //this.table = table; + this.filter = filter; + } + + public static TableRowFilterSupport forFilter( TableFilter<?> filter ) { + return new TableRowFilterSupport(filter); + } + + /** + * Additional actions visible in column filter list + * @param visible + * @return + */ + public TableRowFilterSupport actions( boolean visible ) { + this.actionsVisible = visible; + return this; + } + + /** + * Comlumn filter list is searchable + * @param searchable + * @return + */ + public TableRowFilterSupport searchable( boolean searchable) { + this.searchable = searchable; + return this; + } + + public TableRowFilterSupport searchDecorator( Decorator<Object> decorator ) { + this.decorator = decorator; + return this; + } + + public TableRowFilterSupport useTableRenderers( boolean value ) { + this.useTableRenderers = value; + return this; + } + + public TableRowFilterSupport setPopupDefaultSize(Dimension popupDefaultSize) { + this.popupDefaultSize = popupDefaultSize; + return this; + } + + public JTable apply() { + + final TableFilterColumnPopup filterPopup = new TableFilterColumnPopup(filter); + filterPopup.setEnabled(true); + filterPopup.setActionsVisible(actionsVisible); + filterPopup.setSearchable(searchable); + filterPopup.searchDecorator(decorator); + filterPopup.setUseTableRenderers(useTableRenderers); + filterPopup.setDefaultSize(popupDefaultSize); + + setupTableHeader(); + + return filter.getTable(); + } + + private void setupTableHeader() { + + final JTable table = filter.getTable(); + + filter.addChangeListener(new FilterChangeListener() { + + @Override + public void filterChanged(TableFilter<?> filter) { + table.getTableHeader().repaint(); + + } + }); + + // make sure that search component is reset after table model changes + setupHeaderRenderers(table.getModel(), true ); +// table.addPropertyChangeListener("model", new PropertyChangeListener() { +// +// public void propertyChange(PropertyChangeEvent evt) { +// +// FilterTableHeaderRenderer headerRenderer = new FilterTableHeaderRenderer(filter); +// filter.modelChanged((TableModel) evt.getNewValue()); +// +// for( TableColumn c: Collections.list( filter.getTable().getColumnModel().getColumns()) ) { +// c.setHeaderRenderer( headerRenderer ); +// } +// }} +// +// ); + } + + private void setupHeaderRenderers( TableModel newModel, boolean fullSetup ) { + + final JTable table = filter.getTable(); + + FilterTableHeaderRenderer headerRenderer = new FilterTableHeaderRenderer(filter); + filter.modelChanged( newModel ); + + for( TableColumn c: Collections.list( table.getColumnModel().getColumns()) ) { + c.setHeaderRenderer( headerRenderer ); + } + + if ( !fullSetup ) return; + + PropertyChangeListener listener = new PropertyChangeListener() { + + public void propertyChange(PropertyChangeEvent e) { + setupHeaderRenderers(table.getModel(), false); + } + + }; + table.addPropertyChangeListener("model", listener); + table.addPropertyChangeListener("columnModel", listener); + + } + +} diff --git a/jaxx-widgets/src/main/resources/META-INF/services/org.nuiton.converter.NuitonConverter b/jaxx-widgets/src/main/resources/META-INF/services/org.nuiton.converter.NuitonConverter index 3ec3f9a..e26305d 100644 --- a/jaxx-widgets/src/main/resources/META-INF/services/org.nuiton.converter.NuitonConverter +++ b/jaxx-widgets/src/main/resources/META-INF/services/org.nuiton.converter.NuitonConverter @@ -1,2 +1,2 @@ -jaxx.runtime.swing.editor.gis.DmsCoordinateConverter -jaxx.runtime.swing.editor.gis.DmdCoordinateConverter \ No newline at end of file +org.nuiton.jaxx.runtime.swing.editor.gis.DmsCoordinateConverter +org.nuiton.jaxx.runtime.swing.editor.gis.DmdCoordinateConverter \ No newline at end of file diff --git a/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmdCoordinateConverterTest.java b/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmdCoordinateConverterTest.java deleted file mode 100644 index e8d58f5..0000000 --- a/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmdCoordinateConverterTest.java +++ /dev/null @@ -1,102 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.junit.Assert; -import org.junit.Test; -import org.nuiton.converter.ConverterUtil; - -/** - * Created on 11/25/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class DmdCoordinateConverterTest { - - @Test - public void testConvert() throws Exception { - - ConverterUtil.initConverters(); - - testConversion(false, "- ° '44", DmdCoordinate.valueOf(-0.007333f)); - testConversion(false, " ° '44", DmdCoordinate.valueOf(0.007333f)); - testConversion(false, " ° '99", DmdCoordinate.valueOf(false, null, null, 99)); - testConversion(false, " ° ' ", DmdCoordinate.empty()); - testConversion(false, " °39'99", DmdCoordinate.valueOf(false, null, 39, 99)); - testConversion(false, " °39' ", DmdCoordinate.valueOf(false, null, 39, null)); - testConversion(false, " 0°39'99", DmdCoordinate.valueOf(false, 0, 39, 99)); - testConversion(false, " 0° ' ", DmdCoordinate.valueOf(false, 0, null, null)); - - testConversion(true, "- ° '44", DmdCoordinate.valueOf(-0.007333f)); - testConversion(true, " ° '44", DmdCoordinate.valueOf(0.007333f)); - testConversion(true, " ° ' ", DmdCoordinate.empty()); - testConversion(true, " ° '99", DmdCoordinate.valueOf(false, null, null, 99)); - testConversion(true, " °39'99", DmdCoordinate.valueOf(false, null, 39, 99)); - testConversion(true, " °39' ", DmdCoordinate.valueOf(false, null, 39, null)); - testConversion(true, " 0°39'99", DmdCoordinate.valueOf(false, 0, 39, 99)); - testConversion(true, " 0° ' ", DmdCoordinate.valueOf(false, 0, null, null)); - } - - protected void testConversion(boolean forLongitude, String expectedString, DmdCoordinate expectedCoordinate) { - - DmdCoordinateConverter converter = (DmdCoordinateConverter) ConverterUtil.getConverter(DmdCoordinate.class); - converter.setForLongitude(forLongitude); - Assert.assertNotNull(converter); - - String actualStr; - DmdCoordinate actualCoordinate; - - // String -> DmdCoordinate - - actualCoordinate = (DmdCoordinate) converter.convert(DmdCoordinate.class, expectedString); - Assert.assertNotNull(actualCoordinate); - Assert.assertEquals(actualCoordinate.isSign(), expectedCoordinate.isSign()); - Assert.assertEquals(actualCoordinate.getDegree(), expectedCoordinate.getDegree()); - Assert.assertEquals(actualCoordinate.getMinute(), expectedCoordinate.getMinute()); - Assert.assertEquals(actualCoordinate.getDecimal(), expectedCoordinate.getDecimal()); - - // DmdCoordinate -> String - - actualStr = (String) converter.convert(String.class, expectedCoordinate); - - Assert.assertNotNull(actualStr); - Assert.assertEquals(expectedString, actualStr); - - // String -> String - - actualStr = (String) converter.convert(String.class, expectedString); - - Assert.assertNotNull(actualStr); - Assert.assertEquals(expectedString, actualStr); - - // DmdCoordinate -> DmdCoordinate - - actualCoordinate = (DmdCoordinate) converter.convert(DmdCoordinate.class, expectedCoordinate); - Assert.assertNotNull(actualCoordinate); - Assert.assertEquals(actualCoordinate.isSign(), expectedCoordinate.isSign()); - Assert.assertEquals(actualCoordinate.getDegree(), expectedCoordinate.getDegree()); - Assert.assertEquals(actualCoordinate.getMinute(), expectedCoordinate.getMinute()); - Assert.assertEquals(actualCoordinate.getDecimal(), expectedCoordinate.getDecimal()); - } -} diff --git a/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorTest.java b/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorTest.java deleted file mode 100644 index ea0ae7d..0000000 --- a/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorTest.java +++ /dev/null @@ -1,212 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.beans.AbstractSerializableBean; - -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; -import javax.swing.border.TitledBorder; -import java.awt.BorderLayout; -import java.awt.GridLayout; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.text.ParseException; - -/** - * To test the {@link DmsCoordinateEditor}. - * - * Created on 10/17/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class DmdCoordinateEditorTest { - - /** Logger. */ - private static final Log log = - LogFactory.getLog(DmdCoordinateEditorTest.class); - - public static class EditorBean extends AbstractSerializableBean { - - private static final long serialVersionUID = 1L; - - public static final String PROPERTY_LONGITUDE_SIGN = "longitudeSign"; - - public static final String PROPERTY_LONGITUDE_DEGREE = "longitudeDegree"; - - public static final String PROPERTY_LONGITUDE_MINUTE = "longitudeMinute"; - - public static final String PROPERTY_LONGITUDE_DECIMAL = "longitudeDecimal"; - - public static final String PROPERTY_LATITUDE_SIGN = "latitudeSign"; - - public static final String PROPERTY_LATITUDE_DEGREE = "latitudeDegree"; - - public static final String PROPERTY_LATITUDE_MINUTE = "latitudeMinute"; - - public static final String PROPERTY_LATITUDE_DECIMAL = "latitudeDecimal"; - - protected final DmdCoordinate longitude = DmdCoordinate.empty(); - - protected final DmdCoordinate latitude = DmdCoordinate.empty(); - - public DmdCoordinate getLongitude() { - return longitude; - } - - public void setLongitudeDegree(Integer degre) { - Object oldValue = longitude.getDegree(); - longitude.setDegree(degre); - firePropertyChange(PROPERTY_LONGITUDE_DEGREE, oldValue, degre); - } - - public void setLongitudeMinute(Integer minute) { - Object oldValue = longitude.getMinute(); - longitude.setMinute(minute); - firePropertyChange(PROPERTY_LONGITUDE_MINUTE, oldValue, minute); - } - - public void setLongitudeDecimal(Integer decimal) { - Object oldValue = longitude.getDecimal(); - longitude.setDecimal(decimal); - firePropertyChange(PROPERTY_LONGITUDE_DECIMAL, oldValue, decimal); - } - - public void setLongitudeSign(boolean sign) { - Object oldValue = longitude.isSign(); - longitude.setSign(sign); - firePropertyChange(PROPERTY_LONGITUDE_SIGN, oldValue, sign); - } - - public DmdCoordinate getLatitude() { - return latitude; - } - - public void setLatitudeSign(boolean sign) { - Object oldValue = latitude.isSign(); - latitude.setSign(sign); - firePropertyChange(PROPERTY_LATITUDE_SIGN, oldValue, sign); - } - - public void setLatitudeDegree(Integer degre) { - Object oldValue = latitude.getDegree(); - latitude.setDegree(degre); - firePropertyChange(PROPERTY_LATITUDE_DEGREE, oldValue, degre); - } - - public void setLatitudeMinute(Integer minute) { - Object oldValue = latitude.getMinute(); - latitude.setMinute(minute); - firePropertyChange(PROPERTY_LATITUDE_MINUTE, oldValue, minute); - } - - public void setLatitudeDecimal(Integer decimal) { - Object oldValue = latitude.getDecimal(); - latitude.setDecimal(decimal); - firePropertyChange(PROPERTY_LATITUDE_DECIMAL, oldValue, decimal); - } - - @Override - public String toString() { - return "EditorBean{" + - "longitude=" + longitude + - ", latitude=" + latitude + - '}'; - } - } - - public static void main(String[] args) throws ParseException { - - - EditorBean bean = new EditorBean(); - - DmdCoordinateEditor longitudeEditor = new DmdCoordinateEditor(); - longitudeEditor.setBean(bean); - longitudeEditor.setPropertySign(EditorBean.PROPERTY_LONGITUDE_SIGN); - longitudeEditor.setPropertyDegree(EditorBean.PROPERTY_LONGITUDE_DEGREE); - longitudeEditor.setPropertyMinute(EditorBean.PROPERTY_LONGITUDE_MINUTE); - longitudeEditor.setPropertyDecimal(EditorBean.PROPERTY_LONGITUDE_DECIMAL); - longitudeEditor.setShowReset(true); - longitudeEditor.init(true); - - DmdCoordinateEditor latitudeEditor = new DmdCoordinateEditor(); - latitudeEditor.setBean(bean); - latitudeEditor.setPropertySign(EditorBean.PROPERTY_LATITUDE_SIGN); - latitudeEditor.setPropertyDegree(EditorBean.PROPERTY_LATITUDE_DEGREE); - latitudeEditor.setPropertyMinute(EditorBean.PROPERTY_LATITUDE_MINUTE); - latitudeEditor.setPropertyDecimal(EditorBean.PROPERTY_LATITUDE_DECIMAL); - latitudeEditor.setShowReset(true); - latitudeEditor.init(false); - - final JLabel latitudeResult = new JLabel(); - final JLabel longitudeResult = new JLabel(); - - bean.addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - EditorBean source = (EditorBean) evt.getSource(); - String propertyName = evt.getPropertyName(); - if (log.isInfoEnabled()) { - log.info("[" + propertyName + "] value changed: " + evt.getNewValue()); - } - if (propertyName.startsWith("longitude")) { - longitudeResult.setText(source.getLongitude().toString()); - } else { - - latitudeResult.setText(source.getLatitude().toString()); - } - } - }); - - JPanel longitudeEditorPanel = new JPanel(new GridLayout()); - longitudeEditorPanel.setBorder(new TitledBorder("Longitude")); - longitudeEditorPanel.add(BorderLayout.CENTER, longitudeEditor); - longitudeEditorPanel.add(BorderLayout.EAST, longitudeResult); - - JPanel latitudeEditorPanel = new JPanel(new GridLayout()); - latitudeEditorPanel.setBorder(new TitledBorder("Latitude")); - latitudeEditorPanel.add(BorderLayout.CENTER, latitudeEditor); - latitudeEditorPanel.add(BorderLayout.EAST, latitudeResult); - - JPanel panel = new JPanel(new GridLayout(0, 1)); - panel.add(longitudeEditorPanel); - panel.add(latitudeEditorPanel); - - final JDialog frame = new JDialog(); - - frame.setContentPane(panel); - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - frame.setSize(800, 200); - frame.setVisible(true); - } - }); - } -} diff --git a/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmdCoordinateTest.java b/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmdCoordinateTest.java deleted file mode 100644 index 6f0960c..0000000 --- a/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmdCoordinateTest.java +++ /dev/null @@ -1,136 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.junit.Assert; -import org.junit.Test; - -/** - * Created on 10/25/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class DmdCoordinateTest { - - @Test - public void testFromDecimal() throws Exception { - - { - DmdCoordinate coordinate = DmdCoordinate.empty(); - - coordinate.fromDecimal(42.7f); - - assertDmdCoordinate(coordinate, false, 42, 42, null); - - coordinate.addTrailingZero(); - - assertDmdCoordinate(coordinate, false, 42, 42, 0); - - coordinate.removeTrailingZero(); - - assertDmdCoordinate(coordinate, false, 42, 42, null); - } - - { - DmdCoordinate coordinate = DmdCoordinate.empty(); - - float decimalExcepted = 42.707f; - coordinate.fromDecimal(decimalExcepted); - - assertDmdCoordinate(coordinate, false, 42, 42, 42); - - Float decimal = coordinate.toDecimal(); - Assert.assertEquals(decimalExcepted, decimal, 0.001); - } - } - - @Test - public void testToDecimal() throws Exception { - - { - DmdCoordinate coordinate = DmdCoordinate.empty(); - coordinate.setDegree(42); - coordinate.setMinute(42); - coordinate.setDecimal(42); - Float actual = coordinate.toDecimal(); - Float expected = 42.707f; - Assert.assertEquals(expected, actual, 0.001); - } - - { - DmdCoordinate coordinate = DmdCoordinate.empty(); - coordinate.setDegree(12); - coordinate.setMinute(12); - Float actual = coordinate.toDecimal(); - Float expected = 12.2f; - Assert.assertEquals(expected, actual, 0.0001); - - coordinate.fromDecimal(expected); - - assertDmdCoordinate(coordinate, false, 12, 12, null); - } - - { - DmdCoordinate component = DmdCoordinate.empty(); - component.setDegree(12); - component.setMinute(12); - component.setDecimal(20); - Float actual = component.toDecimal(); - Float expected = 12.203333f; - Assert.assertEquals(expected, actual, 0.001); - - component.fromDecimal(expected); - - assertDmdCoordinate(component, false, 12, 12, 20); - - } - } - - @Test - public void testValueOf() throws Exception { - - DmdCoordinate coordinate = DmdCoordinate.valueOf(-0.007333f); - Assert.assertNotNull(coordinate); - Assert.assertTrue(coordinate.isDegreeNull()); - Assert.assertTrue(coordinate.isMinuteNull()); - - Assert.assertTrue(coordinate.isDegreeValid(true)); - Assert.assertTrue(coordinate.isMinuteValid()); - Assert.assertTrue(coordinate.isDecimalValid()); - - assertDmdCoordinate(coordinate, true, null, null, 44); - } - - public static void assertDmdCoordinate(DmdCoordinate coordinate, - boolean expectedSign, - Integer expectedDegree, - Integer expectedMinute, - Integer expectedDecimal) { - Assert.assertNotNull(coordinate); - Assert.assertEquals(expectedSign, coordinate.isSign()); - Assert.assertEquals(expectedDegree, coordinate.getDegree()); - Assert.assertEquals(expectedMinute, coordinate.getMinute()); - Assert.assertEquals(expectedDecimal, coordinate.getDecimal()); - } -} diff --git a/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmsCoordinateConverterTest.java b/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmsCoordinateConverterTest.java deleted file mode 100644 index 2f80a08..0000000 --- a/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmsCoordinateConverterTest.java +++ /dev/null @@ -1,105 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.junit.Assert; -import org.junit.Test; -import org.nuiton.converter.ConverterUtil; - -/** - * Created on 11/25/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class DmsCoordinateConverterTest { - - - @Test - public void testConvert() throws Exception { - - ConverterUtil.initConverters(); - - testConversion(false, "- ° '26''", DmsCoordinate.valueOf(-0.007333f)); - testConversion(false, " ° '26''", DmsCoordinate.valueOf(0.007333f)); - testConversion(false, " ° '59''", DmsCoordinate.valueOf(false, null, null, 59)); - testConversion(false, " ° ' ''", DmsCoordinate.empty()); - testConversion(false, " °39'59''", DmsCoordinate.valueOf(false, null, 39, 59)); - testConversion(false, " °39' ''", DmsCoordinate.valueOf(false, null, 39, null)); - testConversion(false, " 0°39'59''", DmsCoordinate.valueOf(false, 0, 39, 59)); - testConversion(false, " 0° ' ''", DmsCoordinate.valueOf(false, 0, null, null)); - - testConversion(true, "- ° '26''", DmsCoordinate.valueOf(-0.007333f)); - testConversion(true, " ° '26''", DmsCoordinate.valueOf(0.007333f)); - testConversion(true, " ° ' ''", DmsCoordinate.empty()); - testConversion(true, " ° '59''", DmsCoordinate.valueOf(false, null, null, 59)); - testConversion(true, " °39'59''", DmsCoordinate.valueOf(false, null, 39, 59)); - testConversion(true, " °39' ''", DmsCoordinate.valueOf(false, null, 39, null)); - testConversion(true, " 0°39'59''", DmsCoordinate.valueOf(false, 0, 39, 59)); - testConversion(true, " 0° ' ''", DmsCoordinate.valueOf(false, 0, null, null)); - } - - protected void testConversion(boolean forLongitude, - String expectedString, - DmsCoordinate expectedCoordinate) { - - DmsCoordinateConverter converter = (DmsCoordinateConverter) ConverterUtil.getConverter(DmsCoordinate.class); - converter.setForLongitude(forLongitude); - Assert.assertNotNull(converter); - - String actualStr; - DmsCoordinate actualCoordinate; - - // String -> DmsCoordinate - - actualCoordinate = (DmsCoordinate) converter.convert(DmsCoordinate.class, expectedString); - Assert.assertNotNull(actualCoordinate); - Assert.assertEquals(actualCoordinate.isSign(), expectedCoordinate.isSign()); - Assert.assertEquals(actualCoordinate.getDegree(), expectedCoordinate.getDegree()); - Assert.assertEquals(actualCoordinate.getMinute(), expectedCoordinate.getMinute()); - Assert.assertEquals(actualCoordinate.getSecond(), expectedCoordinate.getSecond()); - - // DmsCoordinate -> String - - actualStr = (String) converter.convert(String.class, expectedCoordinate); - - Assert.assertNotNull(actualStr); - Assert.assertEquals(expectedString, actualStr); - - // String -> String - - actualStr = (String) converter.convert(String.class, expectedString); - - Assert.assertNotNull(actualStr); - Assert.assertEquals(expectedString, actualStr); - - // DmsCoordinate -> DmsCoordinate - - actualCoordinate = (DmsCoordinate) converter.convert(DmsCoordinate.class, expectedCoordinate); - Assert.assertNotNull(actualCoordinate); - Assert.assertEquals(actualCoordinate.isSign(), expectedCoordinate.isSign()); - Assert.assertEquals(actualCoordinate.getDegree(), expectedCoordinate.getDegree()); - Assert.assertEquals(actualCoordinate.getMinute(), expectedCoordinate.getMinute()); - Assert.assertEquals(actualCoordinate.getSecond(), expectedCoordinate.getSecond()); - } -} diff --git a/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorTest.java b/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorTest.java deleted file mode 100644 index 9dc2db6..0000000 --- a/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorTest.java +++ /dev/null @@ -1,214 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.beans.AbstractSerializableBean; - -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; -import javax.swing.border.TitledBorder; -import java.awt.BorderLayout; -import java.awt.GridLayout; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.text.ParseException; - -/** - * To test the {@link DmsCoordinateEditor}. - * - * Created on 10/17/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class DmsCoordinateEditorTest { - - /** Logger. */ - private static final Log log = - LogFactory.getLog(DmsCoordinateEditorTest.class); - - public static class EditorBean extends AbstractSerializableBean { - - private static final long serialVersionUID = 1L; - - public static final String PROPERTY_LONGITUDE_SIGN = "longitudeSign"; - - public static final String PROPERTY_LONGITUDE_DEGREE = "longitudeDegree"; - - public static final String PROPERTY_LONGITUDE_MINUTE = "longitudeMinute"; - - public static final String PROPERTY_LONGITUDE_SECOND = "longitudeSecond"; - - public static final String PROPERTY_LATITUDE_SIGN = "latitudeSign"; - - public static final String PROPERTY_LATITUDE_DEGREE = "latitudeDegree"; - - public static final String PROPERTY_LATITUDE_MINUTE = "latitudeMinute"; - - public static final String PROPERTY_LATITUDE_SECOND = "latitudeSecond"; - - protected final DmsCoordinate longitude = DmsCoordinate.empty(); - - protected final DmsCoordinate latitude = DmsCoordinate.empty(); - - public DmsCoordinate getLongitude() { - return longitude; - } - - public void setLongitudeDegree(Integer degre) { - Object oldValue = longitude.getDegree(); - longitude.setDegree(degre); - firePropertyChange(PROPERTY_LONGITUDE_DEGREE, oldValue, degre); - } - - public void setLongitudeMinute(Integer minute) { - Object oldValue = longitude.getMinute(); - longitude.setMinute(minute); - firePropertyChange(PROPERTY_LONGITUDE_MINUTE, oldValue, minute); - } - - public void setLongitudeSecond(Integer seconde) { - Object oldValue = longitude.getSecond(); - - longitude.setSecond(seconde); - firePropertyChange(PROPERTY_LONGITUDE_SECOND, oldValue, seconde); - } - - public void setLongitudeSign(boolean sign) { - Object oldValue = longitude.isSign(); - longitude.setSign(sign); - firePropertyChange(PROPERTY_LONGITUDE_SIGN, oldValue, sign); - } - - public DmsCoordinate getLatitude() { - return latitude; - } - - public void setLatitudeDegree(Integer degre) { - Object oldValue = latitude.getDegree(); - latitude.setDegree(degre); - firePropertyChange(PROPERTY_LATITUDE_DEGREE, oldValue, degre); - } - - public void setLatitudeMinute(Integer minute) { - Object oldValue = latitude.getMinute(); - latitude.setMinute(minute); - firePropertyChange(PROPERTY_LATITUDE_MINUTE, oldValue, minute); - } - - - public void setLatitudeSecond(Integer seconde) { - Object oldValue = latitude.getSecond(); - latitude.setSecond(seconde); - firePropertyChange(PROPERTY_LATITUDE_SECOND, oldValue, seconde); - } - - public void setLatitudeSign(boolean sign) { - Object oldValue = latitude.isSign(); - latitude.setSign(sign); - firePropertyChange(PROPERTY_LATITUDE_SIGN, oldValue, sign); - } - - @Override - public String toString() { - return "EditorBean{" + - "longitude=" + longitude + - ", latitude=" + latitude + - '}'; - } - } - - public static void main(String[] args) throws ParseException { - - - EditorBean bean = new EditorBean(); - - DmsCoordinateEditor longitudeEditor = new DmsCoordinateEditor(); - longitudeEditor.setBean(bean); - longitudeEditor.setPropertySign(EditorBean.PROPERTY_LONGITUDE_SIGN); - longitudeEditor.setPropertyDegree(EditorBean.PROPERTY_LONGITUDE_DEGREE); - longitudeEditor.setPropertyMinute(EditorBean.PROPERTY_LONGITUDE_MINUTE); - longitudeEditor.setPropertySecond(EditorBean.PROPERTY_LONGITUDE_SECOND); - longitudeEditor.setShowReset(true); - longitudeEditor.init(true); - - DmsCoordinateEditor latitudeEditor = new DmsCoordinateEditor(); - latitudeEditor.setBean(bean); - latitudeEditor.setPropertySign(EditorBean.PROPERTY_LATITUDE_SIGN); - latitudeEditor.setPropertyDegree(EditorBean.PROPERTY_LATITUDE_DEGREE); - latitudeEditor.setPropertyMinute(EditorBean.PROPERTY_LATITUDE_MINUTE); - latitudeEditor.setPropertySecond(EditorBean.PROPERTY_LATITUDE_SECOND); - latitudeEditor.setShowReset(true); - latitudeEditor.init(false); - - final JLabel latitudeResult = new JLabel(); - final JLabel longitudeResult = new JLabel(); - - bean.addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - EditorBean source = (EditorBean) evt.getSource(); - String propertyName = evt.getPropertyName(); - if (log.isInfoEnabled()) { - log.info("[" + propertyName + "] value changed: " + evt.getNewValue()); - } - if (propertyName.startsWith("longitude")) { - longitudeResult.setText(source.getLongitude().toString()); - } else { - - latitudeResult.setText(source.getLatitude().toString()); - } - } - }); - - JPanel longitudeEditorPanel = new JPanel(new GridLayout()); - longitudeEditorPanel.setBorder(new TitledBorder("Longitude")); - longitudeEditorPanel.add(BorderLayout.CENTER, longitudeEditor); - longitudeEditorPanel.add(BorderLayout.EAST, longitudeResult); - - JPanel latitudeEditorPanel = new JPanel(new GridLayout()); - latitudeEditorPanel.setBorder(new TitledBorder("Latitude")); - latitudeEditorPanel.add(BorderLayout.CENTER, latitudeEditor); - latitudeEditorPanel.add(BorderLayout.EAST, latitudeResult); - - JPanel panel = new JPanel(new GridLayout(0, 1)); - panel.add(longitudeEditorPanel); - panel.add(latitudeEditorPanel); - - final JDialog frame = new JDialog(); - - frame.setContentPane(panel); - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - frame.setSize(800, 200); - frame.setVisible(true); - } - }); - } -} diff --git a/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmsCoordinateTest.java b/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmsCoordinateTest.java deleted file mode 100644 index c58d56e..0000000 --- a/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/gis/DmsCoordinateTest.java +++ /dev/null @@ -1,131 +0,0 @@ -package jaxx.runtime.swing.editor.gis; - -/* - * #%L - * JAXX :: Widgets - * %% - * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit - * %% - * This program 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 General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -import org.junit.Assert; -import org.junit.Test; - -/** - * Created on 11/25/13. - * - * @author Tony Chemit - chemit@codelutin.com - * @since 2.6 - */ -public class DmsCoordinateTest { - - @Test - public void testFromDecimal() throws Exception { - - { - DmsCoordinate actual = DmsCoordinate.empty(); - - actual.fromDecimal(42.7f); - - assertDmsCoordinate(actual, false, 42, 42, null); - } - - { - DmsCoordinate actual = DmsCoordinate.empty(); - - float decimalExcepted = 42.711f; - actual.fromDecimal(decimalExcepted); - - assertDmsCoordinate(actual, false, 42, 42, 39); - - Float decimal = actual.toDecimal(); - Assert.assertEquals(decimalExcepted, decimal, 0.001); - } - } - - @Test - public void testToDecimal() throws Exception { - - { - DmsCoordinate coordinate = DmsCoordinate.empty(); - coordinate.setDegree(42); - coordinate.setMinute(42); - coordinate.setSecond(42); - Float floatValue = coordinate.toDecimal(); - Float expected = 42.711f; - Assert.assertEquals(expected, floatValue, 0.001); - } - - { - DmsCoordinate coordinate = DmsCoordinate.empty(); - coordinate.setDegree(12); - coordinate.setMinute(12); - - Float floatValue = coordinate.toDecimal(); - Float expected = 12.2001f; - Assert.assertEquals(expected, floatValue, 0.001); - - coordinate.fromDecimal(expected); - assertDmsCoordinate(coordinate, false, 12, 12, null); - - } - - { - DmsCoordinate coordinate = DmsCoordinate.empty(); - coordinate.setDegree(12); - coordinate.setMinute(12); - coordinate.setSecond(20); - Float floatValue = coordinate.toDecimal(); - Float expected = 12.20569f; - Assert.assertEquals(expected, floatValue, 0.001); - - coordinate.fromDecimal(expected); - - assertDmsCoordinate(coordinate, false, 12, 12, 20); - } - } - - - @Test - public void testValueOf() throws Exception { - - DmsCoordinate coordinate = DmsCoordinate.valueOf(-0.007333f); - Assert.assertNotNull(coordinate); - Assert.assertTrue(coordinate.isDegreeNull()); - Assert.assertTrue(coordinate.isMinuteNull()); - Assert.assertFalse(coordinate.isSecondNull()); - - - Assert.assertTrue(coordinate.isDegreeValid(true)); - Assert.assertTrue(coordinate.isMinuteValid()); - Assert.assertTrue(coordinate.isSecondValid()); - - assertDmsCoordinate(coordinate, true, null, null, 26); - } - - public static void assertDmsCoordinate(DmsCoordinate coordinate, - boolean expectedSign, - Integer expectedDegree, - Integer expectedMinute, - Integer expectedSecond) { - Assert.assertNotNull(coordinate); - Assert.assertEquals(expectedSign, coordinate.isSign()); - Assert.assertEquals(expectedDegree, coordinate.getDegree()); - Assert.assertEquals(expectedMinute, coordinate.getMinute()); - Assert.assertEquals(expectedSecond, coordinate.getSecond()); - } -} diff --git a/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateConverterTest.java b/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateConverterTest.java new file mode 100644 index 0000000..542dc9d --- /dev/null +++ b/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateConverterTest.java @@ -0,0 +1,102 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.junit.Assert; +import org.junit.Test; +import org.nuiton.converter.ConverterUtil; + +/** + * Created on 11/25/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class DmdCoordinateConverterTest { + + @Test + public void testConvert() throws Exception { + + ConverterUtil.initConverters(); + + testConversion(false, "- ° '44", DmdCoordinate.valueOf(-0.007333f)); + testConversion(false, " ° '44", DmdCoordinate.valueOf(0.007333f)); + testConversion(false, " ° '99", DmdCoordinate.valueOf(false, null, null, 99)); + testConversion(false, " ° ' ", DmdCoordinate.empty()); + testConversion(false, " °39'99", DmdCoordinate.valueOf(false, null, 39, 99)); + testConversion(false, " °39' ", DmdCoordinate.valueOf(false, null, 39, null)); + testConversion(false, " 0°39'99", DmdCoordinate.valueOf(false, 0, 39, 99)); + testConversion(false, " 0° ' ", DmdCoordinate.valueOf(false, 0, null, null)); + + testConversion(true, "- ° '44", DmdCoordinate.valueOf(-0.007333f)); + testConversion(true, " ° '44", DmdCoordinate.valueOf(0.007333f)); + testConversion(true, " ° ' ", DmdCoordinate.empty()); + testConversion(true, " ° '99", DmdCoordinate.valueOf(false, null, null, 99)); + testConversion(true, " °39'99", DmdCoordinate.valueOf(false, null, 39, 99)); + testConversion(true, " °39' ", DmdCoordinate.valueOf(false, null, 39, null)); + testConversion(true, " 0°39'99", DmdCoordinate.valueOf(false, 0, 39, 99)); + testConversion(true, " 0° ' ", DmdCoordinate.valueOf(false, 0, null, null)); + } + + protected void testConversion(boolean forLongitude, String expectedString, DmdCoordinate expectedCoordinate) { + + DmdCoordinateConverter converter = (DmdCoordinateConverter) ConverterUtil.getConverter(DmdCoordinate.class); + converter.setForLongitude(forLongitude); + Assert.assertNotNull(converter); + + String actualStr; + DmdCoordinate actualCoordinate; + + // String -> DmdCoordinate + + actualCoordinate = (DmdCoordinate) converter.convert(DmdCoordinate.class, expectedString); + Assert.assertNotNull(actualCoordinate); + Assert.assertEquals(actualCoordinate.isSign(), expectedCoordinate.isSign()); + Assert.assertEquals(actualCoordinate.getDegree(), expectedCoordinate.getDegree()); + Assert.assertEquals(actualCoordinate.getMinute(), expectedCoordinate.getMinute()); + Assert.assertEquals(actualCoordinate.getDecimal(), expectedCoordinate.getDecimal()); + + // DmdCoordinate -> String + + actualStr = (String) converter.convert(String.class, expectedCoordinate); + + Assert.assertNotNull(actualStr); + Assert.assertEquals(expectedString, actualStr); + + // String -> String + + actualStr = (String) converter.convert(String.class, expectedString); + + Assert.assertNotNull(actualStr); + Assert.assertEquals(expectedString, actualStr); + + // DmdCoordinate -> DmdCoordinate + + actualCoordinate = (DmdCoordinate) converter.convert(DmdCoordinate.class, expectedCoordinate); + Assert.assertNotNull(actualCoordinate); + Assert.assertEquals(actualCoordinate.isSign(), expectedCoordinate.isSign()); + Assert.assertEquals(actualCoordinate.getDegree(), expectedCoordinate.getDegree()); + Assert.assertEquals(actualCoordinate.getMinute(), expectedCoordinate.getMinute()); + Assert.assertEquals(actualCoordinate.getDecimal(), expectedCoordinate.getDecimal()); + } +} diff --git a/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorTest.java b/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorTest.java new file mode 100644 index 0000000..616105a --- /dev/null +++ b/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorTest.java @@ -0,0 +1,212 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.beans.AbstractSerializableBean; + +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.border.TitledBorder; +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.text.ParseException; + +/** + * To test the {@link DmsCoordinateEditor}. + * + * Created on 10/17/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class DmdCoordinateEditorTest { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(DmdCoordinateEditorTest.class); + + public static class EditorBean extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + public static final String PROPERTY_LONGITUDE_SIGN = "longitudeSign"; + + public static final String PROPERTY_LONGITUDE_DEGREE = "longitudeDegree"; + + public static final String PROPERTY_LONGITUDE_MINUTE = "longitudeMinute"; + + public static final String PROPERTY_LONGITUDE_DECIMAL = "longitudeDecimal"; + + public static final String PROPERTY_LATITUDE_SIGN = "latitudeSign"; + + public static final String PROPERTY_LATITUDE_DEGREE = "latitudeDegree"; + + public static final String PROPERTY_LATITUDE_MINUTE = "latitudeMinute"; + + public static final String PROPERTY_LATITUDE_DECIMAL = "latitudeDecimal"; + + protected final DmdCoordinate longitude = DmdCoordinate.empty(); + + protected final DmdCoordinate latitude = DmdCoordinate.empty(); + + public DmdCoordinate getLongitude() { + return longitude; + } + + public void setLongitudeDegree(Integer degre) { + Object oldValue = longitude.getDegree(); + longitude.setDegree(degre); + firePropertyChange(PROPERTY_LONGITUDE_DEGREE, oldValue, degre); + } + + public void setLongitudeMinute(Integer minute) { + Object oldValue = longitude.getMinute(); + longitude.setMinute(minute); + firePropertyChange(PROPERTY_LONGITUDE_MINUTE, oldValue, minute); + } + + public void setLongitudeDecimal(Integer decimal) { + Object oldValue = longitude.getDecimal(); + longitude.setDecimal(decimal); + firePropertyChange(PROPERTY_LONGITUDE_DECIMAL, oldValue, decimal); + } + + public void setLongitudeSign(boolean sign) { + Object oldValue = longitude.isSign(); + longitude.setSign(sign); + firePropertyChange(PROPERTY_LONGITUDE_SIGN, oldValue, sign); + } + + public DmdCoordinate getLatitude() { + return latitude; + } + + public void setLatitudeSign(boolean sign) { + Object oldValue = latitude.isSign(); + latitude.setSign(sign); + firePropertyChange(PROPERTY_LATITUDE_SIGN, oldValue, sign); + } + + public void setLatitudeDegree(Integer degre) { + Object oldValue = latitude.getDegree(); + latitude.setDegree(degre); + firePropertyChange(PROPERTY_LATITUDE_DEGREE, oldValue, degre); + } + + public void setLatitudeMinute(Integer minute) { + Object oldValue = latitude.getMinute(); + latitude.setMinute(minute); + firePropertyChange(PROPERTY_LATITUDE_MINUTE, oldValue, minute); + } + + public void setLatitudeDecimal(Integer decimal) { + Object oldValue = latitude.getDecimal(); + latitude.setDecimal(decimal); + firePropertyChange(PROPERTY_LATITUDE_DECIMAL, oldValue, decimal); + } + + @Override + public String toString() { + return "EditorBean{" + + "longitude=" + longitude + + ", latitude=" + latitude + + '}'; + } + } + + public static void main(String[] args) throws ParseException { + + + EditorBean bean = new EditorBean(); + + DmdCoordinateEditor longitudeEditor = new DmdCoordinateEditor(); + longitudeEditor.setBean(bean); + longitudeEditor.setPropertySign(EditorBean.PROPERTY_LONGITUDE_SIGN); + longitudeEditor.setPropertyDegree(EditorBean.PROPERTY_LONGITUDE_DEGREE); + longitudeEditor.setPropertyMinute(EditorBean.PROPERTY_LONGITUDE_MINUTE); + longitudeEditor.setPropertyDecimal(EditorBean.PROPERTY_LONGITUDE_DECIMAL); + longitudeEditor.setShowReset(true); + longitudeEditor.init(true); + + DmdCoordinateEditor latitudeEditor = new DmdCoordinateEditor(); + latitudeEditor.setBean(bean); + latitudeEditor.setPropertySign(EditorBean.PROPERTY_LATITUDE_SIGN); + latitudeEditor.setPropertyDegree(EditorBean.PROPERTY_LATITUDE_DEGREE); + latitudeEditor.setPropertyMinute(EditorBean.PROPERTY_LATITUDE_MINUTE); + latitudeEditor.setPropertyDecimal(EditorBean.PROPERTY_LATITUDE_DECIMAL); + latitudeEditor.setShowReset(true); + latitudeEditor.init(false); + + final JLabel latitudeResult = new JLabel(); + final JLabel longitudeResult = new JLabel(); + + bean.addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + EditorBean source = (EditorBean) evt.getSource(); + String propertyName = evt.getPropertyName(); + if (log.isInfoEnabled()) { + log.info("[" + propertyName + "] value changed: " + evt.getNewValue()); + } + if (propertyName.startsWith("longitude")) { + longitudeResult.setText(source.getLongitude().toString()); + } else { + + latitudeResult.setText(source.getLatitude().toString()); + } + } + }); + + JPanel longitudeEditorPanel = new JPanel(new GridLayout()); + longitudeEditorPanel.setBorder(new TitledBorder("Longitude")); + longitudeEditorPanel.add(BorderLayout.CENTER, longitudeEditor); + longitudeEditorPanel.add(BorderLayout.EAST, longitudeResult); + + JPanel latitudeEditorPanel = new JPanel(new GridLayout()); + latitudeEditorPanel.setBorder(new TitledBorder("Latitude")); + latitudeEditorPanel.add(BorderLayout.CENTER, latitudeEditor); + latitudeEditorPanel.add(BorderLayout.EAST, latitudeResult); + + JPanel panel = new JPanel(new GridLayout(0, 1)); + panel.add(longitudeEditorPanel); + panel.add(latitudeEditorPanel); + + final JDialog frame = new JDialog(); + + frame.setContentPane(panel); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + frame.setSize(800, 200); + frame.setVisible(true); + } + }); + } +} diff --git a/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateTest.java b/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateTest.java new file mode 100644 index 0000000..d53f6b7 --- /dev/null +++ b/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmdCoordinateTest.java @@ -0,0 +1,136 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created on 10/25/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class DmdCoordinateTest { + + @Test + public void testFromDecimal() throws Exception { + + { + DmdCoordinate coordinate = DmdCoordinate.empty(); + + coordinate.fromDecimal(42.7f); + + assertDmdCoordinate(coordinate, false, 42, 42, null); + + coordinate.addTrailingZero(); + + assertDmdCoordinate(coordinate, false, 42, 42, 0); + + coordinate.removeTrailingZero(); + + assertDmdCoordinate(coordinate, false, 42, 42, null); + } + + { + DmdCoordinate coordinate = DmdCoordinate.empty(); + + float decimalExcepted = 42.707f; + coordinate.fromDecimal(decimalExcepted); + + assertDmdCoordinate(coordinate, false, 42, 42, 42); + + Float decimal = coordinate.toDecimal(); + Assert.assertEquals(decimalExcepted, decimal, 0.001); + } + } + + @Test + public void testToDecimal() throws Exception { + + { + DmdCoordinate coordinate = DmdCoordinate.empty(); + coordinate.setDegree(42); + coordinate.setMinute(42); + coordinate.setDecimal(42); + Float actual = coordinate.toDecimal(); + Float expected = 42.707f; + Assert.assertEquals(expected, actual, 0.001); + } + + { + DmdCoordinate coordinate = DmdCoordinate.empty(); + coordinate.setDegree(12); + coordinate.setMinute(12); + Float actual = coordinate.toDecimal(); + Float expected = 12.2f; + Assert.assertEquals(expected, actual, 0.0001); + + coordinate.fromDecimal(expected); + + assertDmdCoordinate(coordinate, false, 12, 12, null); + } + + { + DmdCoordinate component = DmdCoordinate.empty(); + component.setDegree(12); + component.setMinute(12); + component.setDecimal(20); + Float actual = component.toDecimal(); + Float expected = 12.203333f; + Assert.assertEquals(expected, actual, 0.001); + + component.fromDecimal(expected); + + assertDmdCoordinate(component, false, 12, 12, 20); + + } + } + + @Test + public void testValueOf() throws Exception { + + DmdCoordinate coordinate = DmdCoordinate.valueOf(-0.007333f); + Assert.assertNotNull(coordinate); + Assert.assertTrue(coordinate.isDegreeNull()); + Assert.assertTrue(coordinate.isMinuteNull()); + + Assert.assertTrue(coordinate.isDegreeValid(true)); + Assert.assertTrue(coordinate.isMinuteValid()); + Assert.assertTrue(coordinate.isDecimalValid()); + + assertDmdCoordinate(coordinate, true, null, null, 44); + } + + public static void assertDmdCoordinate(DmdCoordinate coordinate, + boolean expectedSign, + Integer expectedDegree, + Integer expectedMinute, + Integer expectedDecimal) { + Assert.assertNotNull(coordinate); + Assert.assertEquals(expectedSign, coordinate.isSign()); + Assert.assertEquals(expectedDegree, coordinate.getDegree()); + Assert.assertEquals(expectedMinute, coordinate.getMinute()); + Assert.assertEquals(expectedDecimal, coordinate.getDecimal()); + } +} diff --git a/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateConverterTest.java b/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateConverterTest.java new file mode 100644 index 0000000..0a11097 --- /dev/null +++ b/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateConverterTest.java @@ -0,0 +1,105 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.junit.Assert; +import org.junit.Test; +import org.nuiton.converter.ConverterUtil; + +/** + * Created on 11/25/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class DmsCoordinateConverterTest { + + + @Test + public void testConvert() throws Exception { + + ConverterUtil.initConverters(); + + testConversion(false, "- ° '26''", DmsCoordinate.valueOf(-0.007333f)); + testConversion(false, " ° '26''", DmsCoordinate.valueOf(0.007333f)); + testConversion(false, " ° '59''", DmsCoordinate.valueOf(false, null, null, 59)); + testConversion(false, " ° ' ''", DmsCoordinate.empty()); + testConversion(false, " °39'59''", DmsCoordinate.valueOf(false, null, 39, 59)); + testConversion(false, " °39' ''", DmsCoordinate.valueOf(false, null, 39, null)); + testConversion(false, " 0°39'59''", DmsCoordinate.valueOf(false, 0, 39, 59)); + testConversion(false, " 0° ' ''", DmsCoordinate.valueOf(false, 0, null, null)); + + testConversion(true, "- ° '26''", DmsCoordinate.valueOf(-0.007333f)); + testConversion(true, " ° '26''", DmsCoordinate.valueOf(0.007333f)); + testConversion(true, " ° ' ''", DmsCoordinate.empty()); + testConversion(true, " ° '59''", DmsCoordinate.valueOf(false, null, null, 59)); + testConversion(true, " °39'59''", DmsCoordinate.valueOf(false, null, 39, 59)); + testConversion(true, " °39' ''", DmsCoordinate.valueOf(false, null, 39, null)); + testConversion(true, " 0°39'59''", DmsCoordinate.valueOf(false, 0, 39, 59)); + testConversion(true, " 0° ' ''", DmsCoordinate.valueOf(false, 0, null, null)); + } + + protected void testConversion(boolean forLongitude, + String expectedString, + DmsCoordinate expectedCoordinate) { + + DmsCoordinateConverter converter = (DmsCoordinateConverter) ConverterUtil.getConverter(DmsCoordinate.class); + converter.setForLongitude(forLongitude); + Assert.assertNotNull(converter); + + String actualStr; + DmsCoordinate actualCoordinate; + + // String -> DmsCoordinate + + actualCoordinate = (DmsCoordinate) converter.convert(DmsCoordinate.class, expectedString); + Assert.assertNotNull(actualCoordinate); + Assert.assertEquals(actualCoordinate.isSign(), expectedCoordinate.isSign()); + Assert.assertEquals(actualCoordinate.getDegree(), expectedCoordinate.getDegree()); + Assert.assertEquals(actualCoordinate.getMinute(), expectedCoordinate.getMinute()); + Assert.assertEquals(actualCoordinate.getSecond(), expectedCoordinate.getSecond()); + + // DmsCoordinate -> String + + actualStr = (String) converter.convert(String.class, expectedCoordinate); + + Assert.assertNotNull(actualStr); + Assert.assertEquals(expectedString, actualStr); + + // String -> String + + actualStr = (String) converter.convert(String.class, expectedString); + + Assert.assertNotNull(actualStr); + Assert.assertEquals(expectedString, actualStr); + + // DmsCoordinate -> DmsCoordinate + + actualCoordinate = (DmsCoordinate) converter.convert(DmsCoordinate.class, expectedCoordinate); + Assert.assertNotNull(actualCoordinate); + Assert.assertEquals(actualCoordinate.isSign(), expectedCoordinate.isSign()); + Assert.assertEquals(actualCoordinate.getDegree(), expectedCoordinate.getDegree()); + Assert.assertEquals(actualCoordinate.getMinute(), expectedCoordinate.getMinute()); + Assert.assertEquals(actualCoordinate.getSecond(), expectedCoordinate.getSecond()); + } +} diff --git a/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorTest.java b/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorTest.java new file mode 100644 index 0000000..b8cee0d --- /dev/null +++ b/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorTest.java @@ -0,0 +1,214 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.beans.AbstractSerializableBean; + +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.border.TitledBorder; +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.text.ParseException; + +/** + * To test the {@link DmsCoordinateEditor}. + * + * Created on 10/17/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class DmsCoordinateEditorTest { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(DmsCoordinateEditorTest.class); + + public static class EditorBean extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + public static final String PROPERTY_LONGITUDE_SIGN = "longitudeSign"; + + public static final String PROPERTY_LONGITUDE_DEGREE = "longitudeDegree"; + + public static final String PROPERTY_LONGITUDE_MINUTE = "longitudeMinute"; + + public static final String PROPERTY_LONGITUDE_SECOND = "longitudeSecond"; + + public static final String PROPERTY_LATITUDE_SIGN = "latitudeSign"; + + public static final String PROPERTY_LATITUDE_DEGREE = "latitudeDegree"; + + public static final String PROPERTY_LATITUDE_MINUTE = "latitudeMinute"; + + public static final String PROPERTY_LATITUDE_SECOND = "latitudeSecond"; + + protected final DmsCoordinate longitude = DmsCoordinate.empty(); + + protected final DmsCoordinate latitude = DmsCoordinate.empty(); + + public DmsCoordinate getLongitude() { + return longitude; + } + + public void setLongitudeDegree(Integer degre) { + Object oldValue = longitude.getDegree(); + longitude.setDegree(degre); + firePropertyChange(PROPERTY_LONGITUDE_DEGREE, oldValue, degre); + } + + public void setLongitudeMinute(Integer minute) { + Object oldValue = longitude.getMinute(); + longitude.setMinute(minute); + firePropertyChange(PROPERTY_LONGITUDE_MINUTE, oldValue, minute); + } + + public void setLongitudeSecond(Integer seconde) { + Object oldValue = longitude.getSecond(); + + longitude.setSecond(seconde); + firePropertyChange(PROPERTY_LONGITUDE_SECOND, oldValue, seconde); + } + + public void setLongitudeSign(boolean sign) { + Object oldValue = longitude.isSign(); + longitude.setSign(sign); + firePropertyChange(PROPERTY_LONGITUDE_SIGN, oldValue, sign); + } + + public DmsCoordinate getLatitude() { + return latitude; + } + + public void setLatitudeDegree(Integer degre) { + Object oldValue = latitude.getDegree(); + latitude.setDegree(degre); + firePropertyChange(PROPERTY_LATITUDE_DEGREE, oldValue, degre); + } + + public void setLatitudeMinute(Integer minute) { + Object oldValue = latitude.getMinute(); + latitude.setMinute(minute); + firePropertyChange(PROPERTY_LATITUDE_MINUTE, oldValue, minute); + } + + + public void setLatitudeSecond(Integer seconde) { + Object oldValue = latitude.getSecond(); + latitude.setSecond(seconde); + firePropertyChange(PROPERTY_LATITUDE_SECOND, oldValue, seconde); + } + + public void setLatitudeSign(boolean sign) { + Object oldValue = latitude.isSign(); + latitude.setSign(sign); + firePropertyChange(PROPERTY_LATITUDE_SIGN, oldValue, sign); + } + + @Override + public String toString() { + return "EditorBean{" + + "longitude=" + longitude + + ", latitude=" + latitude + + '}'; + } + } + + public static void main(String[] args) throws ParseException { + + + EditorBean bean = new EditorBean(); + + DmsCoordinateEditor longitudeEditor = new DmsCoordinateEditor(); + longitudeEditor.setBean(bean); + longitudeEditor.setPropertySign(EditorBean.PROPERTY_LONGITUDE_SIGN); + longitudeEditor.setPropertyDegree(EditorBean.PROPERTY_LONGITUDE_DEGREE); + longitudeEditor.setPropertyMinute(EditorBean.PROPERTY_LONGITUDE_MINUTE); + longitudeEditor.setPropertySecond(EditorBean.PROPERTY_LONGITUDE_SECOND); + longitudeEditor.setShowReset(true); + longitudeEditor.init(true); + + DmsCoordinateEditor latitudeEditor = new DmsCoordinateEditor(); + latitudeEditor.setBean(bean); + latitudeEditor.setPropertySign(EditorBean.PROPERTY_LATITUDE_SIGN); + latitudeEditor.setPropertyDegree(EditorBean.PROPERTY_LATITUDE_DEGREE); + latitudeEditor.setPropertyMinute(EditorBean.PROPERTY_LATITUDE_MINUTE); + latitudeEditor.setPropertySecond(EditorBean.PROPERTY_LATITUDE_SECOND); + latitudeEditor.setShowReset(true); + latitudeEditor.init(false); + + final JLabel latitudeResult = new JLabel(); + final JLabel longitudeResult = new JLabel(); + + bean.addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + EditorBean source = (EditorBean) evt.getSource(); + String propertyName = evt.getPropertyName(); + if (log.isInfoEnabled()) { + log.info("[" + propertyName + "] value changed: " + evt.getNewValue()); + } + if (propertyName.startsWith("longitude")) { + longitudeResult.setText(source.getLongitude().toString()); + } else { + + latitudeResult.setText(source.getLatitude().toString()); + } + } + }); + + JPanel longitudeEditorPanel = new JPanel(new GridLayout()); + longitudeEditorPanel.setBorder(new TitledBorder("Longitude")); + longitudeEditorPanel.add(BorderLayout.CENTER, longitudeEditor); + longitudeEditorPanel.add(BorderLayout.EAST, longitudeResult); + + JPanel latitudeEditorPanel = new JPanel(new GridLayout()); + latitudeEditorPanel.setBorder(new TitledBorder("Latitude")); + latitudeEditorPanel.add(BorderLayout.CENTER, latitudeEditor); + latitudeEditorPanel.add(BorderLayout.EAST, latitudeResult); + + JPanel panel = new JPanel(new GridLayout(0, 1)); + panel.add(longitudeEditorPanel); + panel.add(latitudeEditorPanel); + + final JDialog frame = new JDialog(); + + frame.setContentPane(panel); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + frame.setSize(800, 200); + frame.setVisible(true); + } + }); + } +} diff --git a/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateTest.java b/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateTest.java new file mode 100644 index 0000000..ff0177a --- /dev/null +++ b/jaxx-widgets/src/test/java/org/nuiton/jaxx/runtime/swing/editor/gis/DmsCoordinateTest.java @@ -0,0 +1,131 @@ +package org.nuiton.jaxx.runtime.swing.editor.gis; + +/* + * #%L + * JAXX :: Widgets + * %% + * Copyright (C) 2008 - 2014 Code Lutin, Tony Chemit + * %% + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created on 11/25/13. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.6 + */ +public class DmsCoordinateTest { + + @Test + public void testFromDecimal() throws Exception { + + { + DmsCoordinate actual = DmsCoordinate.empty(); + + actual.fromDecimal(42.7f); + + assertDmsCoordinate(actual, false, 42, 42, null); + } + + { + DmsCoordinate actual = DmsCoordinate.empty(); + + float decimalExcepted = 42.711f; + actual.fromDecimal(decimalExcepted); + + assertDmsCoordinate(actual, false, 42, 42, 39); + + Float decimal = actual.toDecimal(); + Assert.assertEquals(decimalExcepted, decimal, 0.001); + } + } + + @Test + public void testToDecimal() throws Exception { + + { + DmsCoordinate coordinate = DmsCoordinate.empty(); + coordinate.setDegree(42); + coordinate.setMinute(42); + coordinate.setSecond(42); + Float floatValue = coordinate.toDecimal(); + Float expected = 42.711f; + Assert.assertEquals(expected, floatValue, 0.001); + } + + { + DmsCoordinate coordinate = DmsCoordinate.empty(); + coordinate.setDegree(12); + coordinate.setMinute(12); + + Float floatValue = coordinate.toDecimal(); + Float expected = 12.2001f; + Assert.assertEquals(expected, floatValue, 0.001); + + coordinate.fromDecimal(expected); + assertDmsCoordinate(coordinate, false, 12, 12, null); + + } + + { + DmsCoordinate coordinate = DmsCoordinate.empty(); + coordinate.setDegree(12); + coordinate.setMinute(12); + coordinate.setSecond(20); + Float floatValue = coordinate.toDecimal(); + Float expected = 12.20569f; + Assert.assertEquals(expected, floatValue, 0.001); + + coordinate.fromDecimal(expected); + + assertDmsCoordinate(coordinate, false, 12, 12, 20); + } + } + + + @Test + public void testValueOf() throws Exception { + + DmsCoordinate coordinate = DmsCoordinate.valueOf(-0.007333f); + Assert.assertNotNull(coordinate); + Assert.assertTrue(coordinate.isDegreeNull()); + Assert.assertTrue(coordinate.isMinuteNull()); + Assert.assertFalse(coordinate.isSecondNull()); + + + Assert.assertTrue(coordinate.isDegreeValid(true)); + Assert.assertTrue(coordinate.isMinuteValid()); + Assert.assertTrue(coordinate.isSecondValid()); + + assertDmsCoordinate(coordinate, true, null, null, 26); + } + + public static void assertDmsCoordinate(DmsCoordinate coordinate, + boolean expectedSign, + Integer expectedDegree, + Integer expectedMinute, + Integer expectedSecond) { + Assert.assertNotNull(coordinate); + Assert.assertEquals(expectedSign, coordinate.isSign()); + Assert.assertEquals(expectedDegree, coordinate.getDegree()); + Assert.assertEquals(expectedMinute, coordinate.getMinute()); + Assert.assertEquals(expectedSecond, coordinate.getSecond()); + } +} diff --git a/jaxx-widgets/src/test/resources/log4j.properties b/jaxx-widgets/src/test/resources/log4j.properties index a9515ea..b7b98bb 100644 --- a/jaxx-widgets/src/test/resources/log4j.properties +++ b/jaxx-widgets/src/test/resources/log4j.properties @@ -26,6 +26,5 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) %M - %m%n -log4j.logger.jaxx.runtime.swing=DEBUG -#log4j.logger.jaxx.runtime.swing.editor.config.model.ConfigUIModelBuilder=DEBUG log4j.logger.org.nuiton=WARN +log4j.logger.org.nuiton.jaxx=INFO diff --git a/src/site/rst/BeanValidator.rst b/src/site/rst/BeanValidator.rst index 0ae0603..d85a6e0 100644 --- a/src/site/rst/BeanValidator.rst +++ b/src/site/rst/BeanValidator.rst @@ -68,7 +68,7 @@ Les attributs autorisés sont les suivants : * *errorListModel* : le modèle qui contient la liste des erreurs (et est liée au composant *errorList*), doit étendre *jaxx.runtime.validator.swing.SwingValidatorErrorListModel*. Si non présent on essayera le composent d'id *errorListModel*. - * *uiClass* : le FQN de la classe utilisé pour le rendu des erreurs sur les wigets d'édition. La classe doit étendre *jaxx.runtime.validator.swing.ui.AbstractBeanValidatorUI*. Si non présent, on utilise par défaut le render *jaxx.runtime.validator.swing.ui.IconValidationUI*. + * *uiClass* : le FQN de la classe utilisé pour le rendu des erreurs sur les wigets d'édition. La classe doit étendre *org.nuiton.jaxx.validator.swing.ui.AbstractBeanValidatorUI*. Si non présent, on utilise par défaut le render *org.nuiton.jaxx.validator.swing.ui.IconValidationUI*. Le tag supporte aussi l'ajout de tag *field* comme fils pour définir explicitement des champs à validater. @@ -90,12 +90,12 @@ Le tag supporte les attributs suivants : Les classes du runtime ====================== -Ce développement est dans le paquetage *jaxx.runtime.validator* (sauf pour l'interface *jaxx.runtime.JAXXValidator*). +Ce développement est dans le paquetage *jaxx.runtime.validator* (sauf pour l'interface *org.nuiton.jaxx.validator.JAXXValidator*). Il s'agit de l'ensemble des classes ajoutées dans le module *jaxx-core* pour encapsuler la validation dans les fichiers java générés à partir des fichiers JAXX. -interface jaxx.runtime.JAXXValidator +interface org.nuiton.jaxx.validator.JAXXValidator ************************************ Ce contrat a été ajouté à tous les objets JAXX générés (donc l'interface JAXXObject étend JAXXValidator). @@ -105,7 +105,7 @@ On définit ici uniquement des méthodes d'accès aux validateurs enregistrés d TODO on pourrait ajouter des méthodes pour savoir l'état de validation d'un validateur ? -classe jaxx.runtime.validator.swing.SwingValidator +classe org.nuiton.jaxx.validator.swing.SwingValidator ************************************************** Il s'agit de la classe principale d'encapsulation d'un validateur XWorks 2. diff --git a/src/site/rst/JAXXContext.rst b/src/site/rst/JAXXContext.rst index 125c771..f75ad9d 100644 --- a/src/site/rst/JAXXContext.rst +++ b/src/site/rst/JAXXContext.rst @@ -54,7 +54,7 @@ Le type de l'objet correspondant en fait à la classe de la donnée. Le nom qui est facultatif permet de pouvoir distinguer plusieurs données d'un même type dans le context. Si le nom n'est pas utilisé pour caractériser une données on fixera alors sa valeur à *null*. -Afin de pouvoir caractériser les entrées dans le context, une classe a été définie *jaxx.runtime.context.JAXXContextEntryDef*. +Afin de pouvoir caractériser les entrées dans le context, une classe a été définie *org.nuiton.jaxx.runtime.context.JAXXContextEntryDef*. Les méthodes de lecture *********************** @@ -109,7 +109,7 @@ de type *JAXXContext* non nommé qui le context courant qui sera détecté comme Cette entrée spéciale ne sera pas stockée avec les autres entrées afin d'optimiser les algorithmes d'injection et de restitution. -jaxx.runtime.context.JAXXInitialContext +org.nuiton.jaxx.runtime.context.JAXXInitialContext *************************************** On a implanté un second type de context qui lui peut servir à l'initialisation des JAXXObject. diff --git a/src/site/rst/NavigationModel.rst b/src/site/rst/NavigationModel.rst index 4b442ff..a15d953 100644 --- a/src/site/rst/NavigationModel.rst +++ b/src/site/rst/NavigationModel.rst @@ -117,7 +117,7 @@ jaxx.runtime.swing.navigation.handler.NavigationTreeHandlerWithCardLayout ========================================================================= Extension de *jaxx.runtime.swing.navigation.handler.AbstractNavigationHandler* pour -l'utilisation de CardLayout (*jaxx.runtime.swing.CardLayout2*). +l'utilisation de CardLayout (*org.nuiton.jaxx.runtime.swing.CardLayout2*). jaxx.runtime.swing.navigation.handler.NavigationMultiTreeHandler ================================================================ @@ -274,7 +274,7 @@ jaxx.runtime.swing.navigation.NavigationTreeSelectionAdapterWithCardLayout Il s'agit d'une implantation du listener précédent qui suppose que les uis associées aux noeuds sont affichées dans un unique container en utilisant le -layout *jaxx.runtime.swing.CardLayout2*. +layout *org.nuiton.jaxx.runtime.swing.CardLayout2*. La contrainte de chaque ui sera extactement le chemin de navigation du noeud associé. diff --git a/src/site/rst/index.rst b/src/site/rst/index.rst index 5fb8294..de83fe9 100644 --- a/src/site/rst/index.rst +++ b/src/site/rst/index.rst @@ -75,7 +75,7 @@ Cette option permet de détecter un handler associé à chaque fichier jaxx. Le handler doit porter le nom du fichier java associé au fichier jaxx suffixé par Handler. -Ce handler doit de plus implanter un nouveau contract *jaxx.runtime.spi.UIHandler*. +Ce handler doit de plus implanter un nouveau contract *org.nuiton.jaxx.runtime.spi.UIHandler*. Le contrat contient deux méthodes @@ -298,10 +298,10 @@ Voir https://forge.nuiton.org/issues/show/666 Nouvelle api d'assistant ________________________ -Le package *jaxx.runtime.swing.wizard.ext** contient une nouvelle api simplifié +Le package *org.nuiton.jaxx.runtime.swing.wizard.ext** contient une nouvelle api simplifié pour créer des assitants avec des modèles attachés aux étapes. -Cette api remplace celle du **jaxx.runtime.swing.wizard.WizardOperationXXX**. +Cette api remplace celle du **org.nuiton.jaxx.runtime.swing.wizard.WizardOperationXXX**. Voir https://forge.nuiton.org/issues/show/665 diff --git a/src/site/rst/old-compiler-doc/BeanValidator.rst b/src/site/rst/old-compiler-doc/BeanValidator.rst index f8cd87c..b85fc54 100644 --- a/src/site/rst/old-compiler-doc/BeanValidator.rst +++ b/src/site/rst/old-compiler-doc/BeanValidator.rst @@ -97,7 +97,7 @@ Les attributs autorisés sont les suivants : * *errorListModel* : le modèle qui contient la liste des erreurs (et est liée au composant *errorList*), doit étendre *jaxx.runtime.validator.swing.SwingValidatorErrorListModel*. Si non présent on essayera le composent d'id *errorListModel*. - * *uiClass* : le FQN de la classe utilisé pour le rendu des erreurs sur les wigets d'édition. La classe doit étendre *jaxx.runtime.validator.swing.ui.AbstractBeanValidatorUI*. Si non présent, on utilise par défaut le render *jaxx.runtime.validator.swing.ui.IconValidationUI*. + * *uiClass* : le FQN de la classe utilisé pour le rendu des erreurs sur les wigets d'édition. La classe doit étendre *org.nuiton.jaxx.validator.swing.ui.AbstractBeanValidatorUI*. Si non présent, on utilise par défaut le render *org.nuiton.jaxx.validator.swing.ui.IconValidationUI*. Le tag supporte aussi l'ajout de tag *field* comme fils pour définir explicitement des champs à validater. @@ -119,12 +119,12 @@ Le tag supporte les attributs suivants : Les classes du runtime ====================== -Ce développement est dans le paquetage *jaxx.runtime.validator* (sauf pour l'interface *jaxx.runtime.JAXXValidator*). +Ce développement est dans le paquetage *jaxx.runtime.validator* (sauf pour l'interface *org.nuiton.jaxx.validator.JAXXValidator*). Il s'agit de l'ensemble des classes ajoutées dans le module *jaxx-core* pour encapsuler la validation dans les fichiers java générés à partir des fichiers JAXX. -interface jaxx.runtime.JAXXValidator +interface org.nuiton.jaxx.validator.JAXXValidator ************************************ Ce contrat a été ajouté à tous les objets JAXX générés (donc l'interface JAXXObject étend JAXXValidator). diff --git a/src/site/rst/old-compiler-doc/JAXXContext.rst b/src/site/rst/old-compiler-doc/JAXXContext.rst index 368a10d..6ec5aa3 100644 --- a/src/site/rst/old-compiler-doc/JAXXContext.rst +++ b/src/site/rst/old-compiler-doc/JAXXContext.rst @@ -54,7 +54,7 @@ Le type de l'objet correspondant en fait à la classe de la donnée. Le nom qui est facultatif permet de pouvoir distinguer plusieurs données d'un même type dans le context. Si le nom n'est pas utilisé pour caractériser une données on fixera alors sa valeur à *null*. -Afin de pouvoir caractériser les entrées dans le context, une classe a été définie *jaxx.runtime.context.JAXXContextEntryDef*. +Afin de pouvoir caractériser les entrées dans le context, une classe a été définie *org.nuiton.jaxx.runtime.context.JAXXContextEntryDef*. Les méthodes de lecture *********************** @@ -109,7 +109,7 @@ de type *JAXXContext* *non nommé* qui le context courant qui sera détecté com Cette entrée spéciale ne sera pas stockée avec les autres entrées afin d'optimiser les algorithmes d'injection et de restitution. -jaxx.runtime.context.JAXXInitialContext +org.nuiton.jaxx.runtime.context.JAXXInitialContext *************************************** On a implanté un second type de context qui lui peut servir à l'initialisation des JAXXObject. diff --git a/src/site/rst/old-compiler-doc/NavigationTreeModel.rst b/src/site/rst/old-compiler-doc/NavigationTreeModel.rst index 3366816..8c871a6 100644 --- a/src/site/rst/old-compiler-doc/NavigationTreeModel.rst +++ b/src/site/rst/old-compiler-doc/NavigationTreeModel.rst @@ -174,7 +174,7 @@ jaxx.runtime.swing.navigation.NavigationTreeSelectionAdapterWithCardLayout ************************************************************************** Il s'agit d'une implantation du listener précédent qui suppose que les uis associées aux noeuds sont affichées dans un -unique container en utilisant le layout *jaxx.runtime.swing.CardLayout2*. +unique container en utilisant le layout *org.nuiton.jaxx.runtime.swing.CardLayout2*. La contrainte de chaque ui sera extactement le chemin de navigation du noeud associé. -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository jaxx. See https://gitlab.nuiton.org/nuiton/jaxx.git commit c3e3ecb0192ae3aca3b2d538c3d1cbfd9def6ec3 Author: Tony CHEMIT <chemit@codelutin.com> Date: Fri Dec 30 10:24:13 2016 +0100 Update jdk level to 1.8 (Fixes #2645) --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index bf02083..f6b6421 100644 --- a/pom.xml +++ b/pom.xml @@ -133,8 +133,8 @@ <projectId>jaxx</projectId> <ciViewId>Jaxx</ciViewId> - <javaVersion>1.6</javaVersion> - <signatureArtifactId>java16</signatureArtifactId> + <javaVersion>1.8</javaVersion> + <signatureArtifactId>java18</signatureArtifactId> <signatureVersion>1.0</signatureVersion> <mavenVersion>3.3.9</mavenVersion> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.
participants (1)
-
nuiton.org scm